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.assertThrows; 109 import static org.mockito.ArgumentMatchers.isNull; 110 import static org.mockito.Matchers.anyBoolean; 111 import static org.mockito.Matchers.anyLong; 112 import static org.mockito.Matchers.anyString; 113 import static org.mockito.Matchers.eq; 114 import static org.mockito.Mockito.any; 115 import static org.mockito.Mockito.anyInt; 116 import static org.mockito.Mockito.atLeastOnce; 117 import static org.mockito.Mockito.clearInvocations; 118 import static org.mockito.Mockito.doAnswer; 119 import static org.mockito.Mockito.doNothing; 120 import static org.mockito.Mockito.doThrow; 121 import static org.mockito.Mockito.inOrder; 122 import static org.mockito.Mockito.mock; 123 import static org.mockito.Mockito.never; 124 import static org.mockito.Mockito.reset; 125 import static org.mockito.Mockito.spy; 126 import static org.mockito.Mockito.timeout; 127 import static org.mockito.Mockito.times; 128 import static org.mockito.Mockito.verify; 129 import static org.mockito.Mockito.verifyNoMoreInteractions; 130 import static org.mockito.Mockito.verifyZeroInteractions; 131 import static org.mockito.Mockito.when; 132 133 import static java.util.Collections.emptyList; 134 import static java.util.Collections.singletonList; 135 136 import android.Manifest; 137 import android.annotation.Nullable; 138 import android.annotation.SuppressLint; 139 import android.annotation.UserIdInt; 140 import android.app.ActivityManager; 141 import android.app.ActivityManagerInternal; 142 import android.app.AlarmManager; 143 import android.app.AppOpsManager; 144 import android.app.AutomaticZenRule; 145 import android.app.IActivityManager; 146 import android.app.INotificationManager; 147 import android.app.ITransientNotification; 148 import android.app.IUriGrantsManager; 149 import android.app.Notification; 150 import android.app.Notification.MessagingStyle.Message; 151 import android.app.NotificationChannel; 152 import android.app.NotificationChannelGroup; 153 import android.app.NotificationManager; 154 import android.app.PendingIntent; 155 import android.app.Person; 156 import android.app.RemoteInput; 157 import android.app.RemoteInputHistoryItem; 158 import android.app.StatsManager; 159 import android.app.admin.DevicePolicyManagerInternal; 160 import android.app.usage.UsageStatsManagerInternal; 161 import android.companion.AssociationInfo; 162 import android.companion.ICompanionDeviceManager; 163 import android.content.BroadcastReceiver; 164 import android.content.ComponentName; 165 import android.content.ContentUris; 166 import android.content.Context; 167 import android.content.IIntentSender; 168 import android.content.Intent; 169 import android.content.IntentFilter; 170 import android.content.pm.ActivityInfo; 171 import android.content.pm.ApplicationInfo; 172 import android.content.pm.IPackageManager; 173 import android.content.pm.LauncherApps; 174 import android.content.pm.PackageManager; 175 import android.content.pm.PackageManagerInternal; 176 import android.content.pm.ParceledListSlice; 177 import android.content.pm.ShortcutInfo; 178 import android.content.pm.ShortcutServiceInternal; 179 import android.content.pm.UserInfo; 180 import android.content.pm.VersionedPackage; 181 import android.content.res.Resources; 182 import android.graphics.Color; 183 import android.graphics.drawable.Icon; 184 import android.media.AudioManager; 185 import android.media.IRingtonePlayer; 186 import android.media.session.MediaSession; 187 import android.net.Uri; 188 import android.os.Binder; 189 import android.os.Build; 190 import android.os.Bundle; 191 import android.os.IBinder; 192 import android.os.Looper; 193 import android.os.Parcel; 194 import android.os.Parcelable; 195 import android.os.PowerManager; 196 import android.os.PowerManager.WakeLock; 197 import android.os.Process; 198 import android.os.RemoteException; 199 import android.os.SystemClock; 200 import android.os.UserHandle; 201 import android.os.UserManager; 202 import android.os.WorkSource; 203 import android.permission.PermissionManager; 204 import android.provider.DeviceConfig; 205 import android.provider.MediaStore; 206 import android.provider.Settings; 207 import android.service.notification.Adjustment; 208 import android.service.notification.ConversationChannelWrapper; 209 import android.service.notification.NotificationListenerFilter; 210 import android.service.notification.NotificationListenerService; 211 import android.service.notification.NotificationRankingUpdate; 212 import android.service.notification.NotificationStats; 213 import android.service.notification.StatusBarNotification; 214 import android.service.notification.ZenPolicy; 215 import android.telecom.TelecomManager; 216 import android.telephony.TelephonyManager; 217 import android.test.suitebuilder.annotation.SmallTest; 218 import android.testing.AndroidTestingRunner; 219 import android.testing.TestableLooper; 220 import android.testing.TestableLooper.RunWithLooper; 221 import android.testing.TestablePermissions; 222 import android.testing.TestableResources; 223 import android.text.Html; 224 import android.text.TextUtils; 225 import android.util.ArrayMap; 226 import android.util.ArraySet; 227 import android.util.AtomicFile; 228 import android.util.Pair; 229 import android.util.Xml; 230 import android.widget.RemoteViews; 231 232 import androidx.test.InstrumentationRegistry; 233 234 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; 235 import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.Flag; 236 import com.android.internal.config.sysui.TestableFlagResolver; 237 import com.android.internal.logging.InstanceIdSequence; 238 import com.android.internal.logging.InstanceIdSequenceFake; 239 import com.android.internal.messages.nano.SystemMessageProto; 240 import com.android.internal.statusbar.NotificationVisibility; 241 import com.android.modules.utils.TypedXmlPullParser; 242 import com.android.modules.utils.TypedXmlSerializer; 243 import com.android.server.DeviceIdleInternal; 244 import com.android.server.LocalServices; 245 import com.android.server.SystemService; 246 import com.android.server.SystemService.TargetUser; 247 import com.android.server.UiServiceTestCase; 248 import com.android.server.job.JobSchedulerInternal; 249 import com.android.server.lights.LightsManager; 250 import com.android.server.lights.LogicalLight; 251 import com.android.server.notification.NotificationManagerService.NotificationAssistants; 252 import com.android.server.notification.NotificationManagerService.NotificationListeners; 253 import com.android.server.notification.NotificationManagerService.PostNotificationTracker; 254 import com.android.server.notification.NotificationManagerService.PostNotificationTrackerFactory; 255 import com.android.server.pm.PackageManagerService; 256 import com.android.server.pm.UserManagerInternal; 257 import com.android.server.policy.PermissionPolicyInternal; 258 import com.android.server.statusbar.StatusBarManagerInternal; 259 import com.android.server.uri.UriGrantsManagerInternal; 260 import com.android.server.utils.quota.MultiRateLimiter; 261 import com.android.server.wm.ActivityTaskManagerInternal; 262 import com.android.server.wm.WindowManagerInternal; 263 264 import com.google.android.collect.Lists; 265 import com.google.common.collect.ImmutableList; 266 267 import org.junit.After; 268 import org.junit.Assert; 269 import org.junit.Before; 270 import org.junit.Test; 271 import org.junit.runner.RunWith; 272 import org.mockito.ArgumentCaptor; 273 import org.mockito.ArgumentMatcher; 274 import org.mockito.ArgumentMatchers; 275 import org.mockito.InOrder; 276 import org.mockito.Mock; 277 import org.mockito.MockitoAnnotations; 278 import org.mockito.invocation.InvocationOnMock; 279 import org.mockito.stubbing.Answer; 280 281 import java.io.BufferedInputStream; 282 import java.io.BufferedOutputStream; 283 import java.io.ByteArrayInputStream; 284 import java.io.ByteArrayOutputStream; 285 import java.io.File; 286 import java.io.FileOutputStream; 287 import java.util.ArrayList; 288 import java.util.Arrays; 289 import java.util.Collections; 290 import java.util.List; 291 import java.util.Map; 292 import java.util.concurrent.CountDownLatch; 293 import java.util.function.Consumer; 294 295 296 @SmallTest 297 @RunWith(AndroidTestingRunner.class) 298 @SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service. 299 @RunWithLooper 300 public class NotificationManagerServiceTest extends UiServiceTestCase { 301 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId"; 302 private static final String TEST_PACKAGE = "The.name.is.Package.Test.Package"; 303 private static final String PKG_NO_CHANNELS = "com.example.no.channels"; 304 private static final int TEST_TASK_ID = 1; 305 private static final int UID_HEADLESS = 1_000_000; 306 private static final int TOAST_DURATION = 2_000; 307 private static final int SECONDARY_DISPLAY_ID = 42; 308 309 private final int mUid = Binder.getCallingUid(); 310 private final @UserIdInt int mUserId = UserHandle.getUserId(mUid); 311 312 private TestableNotificationManagerService mService; 313 private INotificationManager mBinderService; 314 private NotificationManagerInternal mInternalService; 315 private ShortcutHelper mShortcutHelper; 316 @Mock 317 private IPackageManager mPackageManager; 318 @Mock 319 private PackageManager mPackageManagerClient; 320 @Mock 321 private PackageManagerInternal mPackageManagerInternal; 322 @Mock 323 private PermissionPolicyInternal mPermissionPolicyInternal; 324 @Mock 325 private WindowManagerInternal mWindowManagerInternal; 326 @Mock 327 private PermissionHelper mPermissionHelper; 328 private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake(); 329 private final String PKG = mContext.getPackageName(); 330 private TestableLooper mTestableLooper; 331 @Mock 332 private RankingHelper mRankingHelper; 333 @Mock private PreferencesHelper mPreferencesHelper; 334 AtomicFile mPolicyFile; 335 File mFile; 336 @Mock 337 private NotificationUsageStats mUsageStats; 338 @Mock 339 private UsageStatsManagerInternal mAppUsageStats; 340 @Mock 341 private AudioManager mAudioManager; 342 @Mock 343 private LauncherApps mLauncherApps; 344 @Mock 345 private ShortcutServiceInternal mShortcutServiceInternal; 346 @Mock 347 private UserManager mUserManager; 348 @Mock 349 ActivityManager mActivityManager; 350 @Mock 351 TelecomManager mTelecomManager; 352 @Mock 353 Resources mResources; 354 @Mock 355 RankingHandler mRankingHandler; 356 @Mock 357 ActivityManagerInternal mAmi; 358 @Mock 359 JobSchedulerInternal mJsi; 360 @Mock 361 private Looper mMainLooper; 362 @Mock 363 private NotificationManager mMockNm; 364 @Mock 365 private PermissionManager mPermissionManager; 366 @Mock 367 private DevicePolicyManagerInternal mDevicePolicyManager; 368 @Mock 369 private PowerManager mPowerManager; 370 private final ArrayList<WakeLock> mAcquiredWakeLocks = new ArrayList<>(); 371 private final TestPostNotificationTrackerFactory mPostNotificationTrackerFactory = 372 new TestPostNotificationTrackerFactory(); 373 374 @Mock 375 IIntentSender pi1; 376 377 private static final int MAX_POST_DELAY = 1000; 378 379 private NotificationChannel mTestNotificationChannel = new NotificationChannel( 380 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 381 382 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0; 383 384 private static final String VALID_CONVO_SHORTCUT_ID = "shortcut"; 385 private static final String SEARCH_SELECTOR_PKG = "searchSelector"; 386 @Mock 387 private NotificationListeners mListeners; 388 @Mock 389 private NotificationListenerFilter mNlf; 390 @Mock private NotificationAssistants mAssistants; 391 @Mock private ConditionProviders mConditionProviders; 392 private ManagedServices.ManagedServiceInfo mListener; 393 @Mock private ICompanionDeviceManager mCompanionMgr; 394 @Mock SnoozeHelper mSnoozeHelper; 395 @Mock GroupHelper mGroupHelper; 396 @Mock 397 IBinder mPermOwner; 398 @Mock 399 IActivityManager mAm; 400 @Mock 401 ActivityTaskManagerInternal mAtm; 402 @Mock 403 IUriGrantsManager mUgm; 404 @Mock 405 UriGrantsManagerInternal mUgmInternal; 406 @Mock 407 AppOpsManager mAppOpsManager; 408 private AppOpsManager.OnOpChangedListener mOnPermissionChangeListener; 409 @Mock 410 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback 411 mNotificationAssistantAccessGrantedCallback; 412 @Mock 413 UserManager mUm; 414 @Mock 415 UserManagerInternal mUmInternal; 416 @Mock 417 NotificationHistoryManager mHistoryManager; 418 @Mock 419 StatsManager mStatsManager; 420 @Mock 421 AlarmManager mAlarmManager; 422 @Mock 423 MultiRateLimiter mToastRateLimiter; 424 BroadcastReceiver mPackageIntentReceiver; 425 BroadcastReceiver mUserSwitchIntentReceiver; 426 NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); 427 TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker; 428 429 TestableFlagResolver mTestFlagResolver = new TestableFlagResolver(); 430 431 private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( 432 1 << 30); 433 @Mock 434 StatusBarManagerInternal mStatusBar; 435 436 private NotificationManagerService.WorkerHandler mWorkerHandler; 437 438 private class TestableToastCallback extends ITransientNotification.Stub { 439 @Override show(IBinder windowToken)440 public void show(IBinder windowToken) { 441 } 442 443 @Override hide()444 public void hide() { 445 } 446 } 447 448 private class TestPostNotificationTrackerFactory implements PostNotificationTrackerFactory { 449 450 private final List<PostNotificationTracker> mCreatedTrackers = new ArrayList<>(); 451 452 @Override newTracker(@ullable WakeLock optionalWakeLock)453 public PostNotificationTracker newTracker(@Nullable WakeLock optionalWakeLock) { 454 PostNotificationTracker tracker = PostNotificationTrackerFactory.super.newTracker( 455 optionalWakeLock); 456 mCreatedTrackers.add(tracker); 457 return tracker; 458 } 459 } 460 461 @Before setUp()462 public void setUp() throws Exception { 463 // Shell permisssions will override permissions of our app, so add all necessary permissions 464 // for this test here: 465 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( 466 "android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG", 467 "android.permission.READ_DEVICE_CONFIG", 468 "android.permission.READ_CONTACTS"); 469 470 MockitoAnnotations.initMocks(this); 471 472 DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class); 473 when(deviceIdleInternal.getNotificationAllowlistDuration()).thenReturn(3000L); 474 475 LocalServices.removeServiceForTest(UserManagerInternal.class); 476 LocalServices.addService(UserManagerInternal.class, mUmInternal); 477 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class); 478 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal); 479 LocalServices.removeServiceForTest(WindowManagerInternal.class); 480 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal); 481 LocalServices.removeServiceForTest(StatusBarManagerInternal.class); 482 LocalServices.addService(StatusBarManagerInternal.class, mStatusBar); 483 LocalServices.removeServiceForTest(DeviceIdleInternal.class); 484 LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal); 485 LocalServices.removeServiceForTest(ActivityManagerInternal.class); 486 LocalServices.addService(ActivityManagerInternal.class, mAmi); 487 LocalServices.removeServiceForTest(JobSchedulerInternal.class); 488 LocalServices.addService(JobSchedulerInternal.class, mJsi); 489 LocalServices.removeServiceForTest(PackageManagerInternal.class); 490 LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal); 491 LocalServices.removeServiceForTest(PermissionPolicyInternal.class); 492 LocalServices.addService(PermissionPolicyInternal.class, mPermissionPolicyInternal); 493 mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager); 494 mContext.addMockSystemService(NotificationManager.class, mMockNm); 495 496 doNothing().when(mContext).sendBroadcastAsUser(any(), any()); 497 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any()); 498 499 setDpmAppOppsExemptFromDismissal(false); 500 501 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, 502 mNotificationInstanceIdSequence); 503 504 // Use this testable looper. 505 mTestableLooper = TestableLooper.get(this); 506 // MockPackageManager - default returns ApplicationInfo with matching calling UID 507 mContext.setMockPackageManager(mPackageManagerClient); 508 509 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())) 510 .thenAnswer((Answer<ApplicationInfo>) invocation -> { 511 Object[] args = invocation.getArguments(); 512 return getApplicationInfo((String) args[0], mUid); 513 }); 514 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 515 .thenAnswer((Answer<ApplicationInfo>) invocation -> { 516 Object[] args = invocation.getArguments(); 517 return getApplicationInfo((String) args[0], mUid); 518 }); 519 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid); 520 when(mPackageManagerInternal.isSameApp(anyString(), anyInt(), anyInt())).thenAnswer( 521 (Answer<Boolean>) invocation -> { 522 Object[] args = invocation.getArguments(); 523 return (int) args[1] == mUid; 524 }); 525 final LightsManager mockLightsManager = mock(LightsManager.class); 526 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class)); 527 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); 528 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); 529 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner); 530 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG}); 531 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG}); 532 when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())) 533 .thenReturn(INVALID_TASK_ID); 534 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class)); 535 when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0}); 536 537 when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(true); 538 539 ActivityManager.AppTask task = mock(ActivityManager.AppTask.class); 540 List<ActivityManager.AppTask> taskList = new ArrayList<>(); 541 ActivityManager.RecentTaskInfo taskInfo = new ActivityManager.RecentTaskInfo(); 542 taskInfo.taskId = TEST_TASK_ID; 543 when(task.getTaskInfo()).thenReturn(taskInfo); 544 taskList.add(task); 545 when(mAtm.getAppTasks(anyString(), anyInt())).thenReturn(taskList); 546 547 // write to a test file; the system file isn't readable from tests 548 mFile = new File(mContext.getCacheDir(), "test.xml"); 549 mFile.createNewFile(); 550 final String preupgradeXml = "<notification-policy></notification-policy>"; 551 mPolicyFile = new AtomicFile(mFile); 552 FileOutputStream fos = mPolicyFile.startWrite(); 553 fos.write(preupgradeXml.getBytes()); 554 mPolicyFile.finishWrite(fos); 555 556 // Setup managed services 557 when(mNlf.isTypeAllowed(anyInt())).thenReturn(true); 558 when(mNlf.isPackageAllowed(any())).thenReturn(true); 559 when(mNlf.isPackageAllowed(null)).thenReturn(true); 560 when(mListeners.getNotificationListenerFilter(any())).thenReturn(mNlf); 561 mListener = mListeners.new ManagedServiceInfo( 562 null, new ComponentName(PKG, "test_class"), 563 mUserId, true, null, 0, 123); 564 ComponentName defaultComponent = ComponentName.unflattenFromString("config/device"); 565 ArraySet<ComponentName> components = new ArraySet<>(); 566 components.add(defaultComponent); 567 when(mListeners.getDefaultComponents()).thenReturn(components); 568 when(mConditionProviders.getDefaultPackages()) 569 .thenReturn(new ArraySet<>(Arrays.asList("config"))); 570 when(mAssistants.getDefaultComponents()).thenReturn(components); 571 when(mAssistants.queryPackageForServices( 572 anyString(), anyInt(), anyInt())).thenReturn(components); 573 when(mListeners.checkServiceTokenLocked(null)).thenReturn(mListener); 574 ManagedServices.Config listenerConfig = new ManagedServices.Config(); 575 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS; 576 when(mListeners.getConfig()).thenReturn(listenerConfig); 577 ManagedServices.Config assistantConfig = new ManagedServices.Config(); 578 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS; 579 when(mAssistants.getConfig()).thenReturn(assistantConfig); 580 ManagedServices.Config dndConfig = new ManagedServices.Config(); 581 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS; 582 when(mConditionProviders.getConfig()).thenReturn(dndConfig); 583 584 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true); 585 586 // Use the real PowerManager to back up the mock w.r.t. creating WakeLocks. 587 // This is because 1) we need a mock to verify() calls and tracking the created WakeLocks, 588 // but 2) PowerManager and WakeLock perform their own checks (e.g. correct arguments, don't 589 // call release twice, etc) and we want the test to fail if such misuse happens, too. 590 PowerManager realPowerManager = mContext.getSystemService(PowerManager.class); 591 when(mPowerManager.newWakeLock(anyInt(), anyString())).then( 592 (Answer<WakeLock>) invocation -> { 593 WakeLock wl = realPowerManager.newWakeLock(invocation.getArgument(0), 594 invocation.getArgument(1)); 595 mAcquiredWakeLocks.add(wl); 596 return wl; 597 }); 598 mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true); 599 DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, 600 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "true", false); 601 602 // apps allowed as convos 603 mService.setStringArrayResourceValue(PKG_O); 604 605 TestableResources tr = mContext.getOrCreateTestableResources(); 606 tr.addOverride(com.android.internal.R.string.config_defaultSearchSelectorPackageName, 607 SEARCH_SELECTOR_PKG); 608 609 doAnswer(invocation -> { 610 mOnPermissionChangeListener = invocation.getArgument(2); 611 return null; 612 }).when(mAppOpsManager).startWatchingMode(eq(AppOpsManager.OP_POST_NOTIFICATION), any(), 613 any()); 614 when(mUmInternal.isUserInitialized(anyInt())).thenReturn(true); 615 616 mWorkerHandler = spy(mService.new WorkerHandler(mTestableLooper.getLooper())); 617 mService.init(mWorkerHandler, mRankingHandler, mPackageManager, mPackageManagerClient, 618 mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr, 619 mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAtm, 620 mAppUsageStats, mDevicePolicyManager, mUgm, mUgmInternal, 621 mAppOpsManager, mUm, mHistoryManager, mStatsManager, 622 mock(TelephonyManager.class), 623 mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class), 624 mTelecomManager, mLogger, mTestFlagResolver, mPermissionManager, 625 mPowerManager, mPostNotificationTrackerFactory); 626 // Return first true for RoleObserver main-thread check 627 when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false); 628 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper); 629 verify(mHistoryManager, never()).onBootPhaseAppsCanStart(); 630 mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START, mMainLooper); 631 verify(mHistoryManager).onBootPhaseAppsCanStart(); 632 633 mService.setAudioManager(mAudioManager); 634 635 mStrongAuthTracker = mService.new StrongAuthTrackerFake(mContext); 636 mService.setStrongAuthTracker(mStrongAuthTracker); 637 638 mShortcutHelper = mService.getShortcutHelper(); 639 mShortcutHelper.setLauncherApps(mLauncherApps); 640 mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal); 641 mShortcutHelper.setUserManager(mUserManager); 642 643 // Capture PackageIntentReceiver 644 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 645 ArgumentCaptor.forClass(BroadcastReceiver.class); 646 ArgumentCaptor<IntentFilter> intentFilterCaptor = 647 ArgumentCaptor.forClass(IntentFilter.class); 648 649 verify(mContext, atLeastOnce()).registerReceiverAsUser(broadcastReceiverCaptor.capture(), 650 any(), intentFilterCaptor.capture(), any(), any()); 651 verify(mContext, atLeastOnce()).registerReceiver(broadcastReceiverCaptor.capture(), 652 intentFilterCaptor.capture()); 653 List<BroadcastReceiver> broadcastReceivers = broadcastReceiverCaptor.getAllValues(); 654 List<IntentFilter> intentFilters = intentFilterCaptor.getAllValues(); 655 656 for (int i = 0; i < intentFilters.size(); i++) { 657 final IntentFilter filter = intentFilters.get(i); 658 if (filter.hasAction(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED) 659 && filter.hasAction(Intent.ACTION_PACKAGES_UNSUSPENDED) 660 && filter.hasAction(Intent.ACTION_PACKAGES_SUSPENDED)) { 661 mPackageIntentReceiver = broadcastReceivers.get(i); 662 } 663 if (filter.hasAction(Intent.ACTION_USER_SWITCHED)) { 664 mUserSwitchIntentReceiver = broadcastReceivers.get(i); 665 } 666 } 667 assertNotNull("package intent receiver should exist", mPackageIntentReceiver); 668 assertNotNull("User-switch receiver should exist", mUserSwitchIntentReceiver); 669 670 // Pretend the shortcut exists 671 List<ShortcutInfo> shortcutInfos = new ArrayList<>(); 672 ShortcutInfo info = mock(ShortcutInfo.class); 673 when(info.getPackage()).thenReturn(PKG); 674 when(info.getId()).thenReturn(VALID_CONVO_SHORTCUT_ID); 675 when(info.getUserId()).thenReturn(USER_SYSTEM); 676 when(info.isLongLived()).thenReturn(true); 677 when(info.isEnabled()).thenReturn(true); 678 shortcutInfos.add(info); 679 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos); 680 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), 681 anyString(), anyInt(), any())).thenReturn(true); 682 when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true); 683 mockIsUserVisible(DEFAULT_DISPLAY, true); 684 mockIsVisibleBackgroundUsersSupported(false); 685 686 // Set the testable bubble extractor 687 RankingHelper rankingHelper = mService.getRankingHelper(); 688 BubbleExtractor extractor = rankingHelper.findExtractor(BubbleExtractor.class); 689 extractor.setActivityManager(mActivityManager); 690 691 // Tests call directly into the Binder. 692 mBinderService = mService.getBinderService(); 693 mInternalService = mService.getInternalService(); 694 695 mBinderService.createNotificationChannels( 696 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 697 mBinderService.createNotificationChannels( 698 PKG_P, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 699 mBinderService.createNotificationChannels( 700 PKG_O, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); 701 assertNotNull(mBinderService.getNotificationChannel( 702 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID)); 703 clearInvocations(mRankingHandler); 704 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 705 706 mTestFlagResolver.setFlagOverride(FSI_FORCE_DEMOTE, false); 707 mTestFlagResolver.setFlagOverride(SHOW_STICKY_HUN_FOR_DENIED_FSI, false); 708 709 var checker = mock(TestableNotificationManagerService.ComponentPermissionChecker.class); 710 mService.permissionChecker = checker; 711 when(checker.check(anyString(), anyInt(), anyInt(), anyBoolean())) 712 .thenReturn(PackageManager.PERMISSION_DENIED); 713 } 714 715 @After assertNotificationRecordLoggerCallsValid()716 public void assertNotificationRecordLoggerCallsValid() { 717 waitForIdle(); // Finish async work, including all logging calls done by Runnables. 718 for (NotificationRecordLoggerFake.CallRecord call : mNotificationRecordLogger.getCalls()) { 719 if (call.wasLogged) { 720 assertNotNull(call.event); 721 if (call.event == NOTIFICATION_POSTED || call.event == NOTIFICATION_UPDATED) { 722 assertThat(call.postDurationMillisLogged).isGreaterThan(0); 723 } else { 724 assertThat(call.postDurationMillisLogged).isNull(); 725 } 726 } 727 } 728 assertThat(mNotificationRecordLogger.getPendingLogs()).isEmpty(); 729 } 730 731 @After assertAllTrackersFinishedOrCancelled()732 public void assertAllTrackersFinishedOrCancelled() { 733 waitForIdle(); // Finish async work. 734 // Verify that no trackers were left dangling. 735 for (PostNotificationTracker tracker : mPostNotificationTrackerFactory.mCreatedTrackers) { 736 assertThat(tracker.isOngoing()).isFalse(); 737 } 738 mPostNotificationTrackerFactory.mCreatedTrackers.clear(); 739 } 740 741 @After assertAllWakeLocksReleased()742 public void assertAllWakeLocksReleased() { 743 waitForIdle(); // Finish async work. 744 for (WakeLock wakeLock : mAcquiredWakeLocks) { 745 assertThat(wakeLock.isHeld()).isFalse(); 746 } 747 } 748 749 @After tearDown()750 public void tearDown() throws Exception { 751 if (mFile != null) mFile.delete(); 752 clearDeviceConfig(); 753 754 try { 755 mService.onDestroy(); 756 } catch (IllegalStateException | IllegalArgumentException e) { 757 // can throw if a broadcast receiver was never registered 758 } 759 760 InstrumentationRegistry.getInstrumentation() 761 .getUiAutomation().dropShellPermissionIdentity(); 762 // Remove scheduled messages that would be processed when the test is already done, and 763 // could cause issues, for example, messages that remove/cancel shown toasts (this causes 764 // problematic interactions with mocks when they're no longer working as expected). 765 mWorkerHandler.removeCallbacksAndMessages(null); 766 } 767 simulatePackageSuspendBroadcast(boolean suspend, String pkg, int uid)768 private void simulatePackageSuspendBroadcast(boolean suspend, String pkg, 769 int uid) { 770 // mimics receive broadcast that package is (un)suspended 771 // but does not actually (un)suspend the package 772 final Bundle extras = new Bundle(); 773 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, 774 new String[]{pkg}); 775 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, new int[]{uid}); 776 777 final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED 778 : Intent.ACTION_PACKAGES_UNSUSPENDED; 779 final Intent intent = new Intent(action); 780 intent.putExtras(extras); 781 782 mPackageIntentReceiver.onReceive(getContext(), intent); 783 } 784 simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids)785 private void simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids) { 786 // mimics receive broadcast that package is (un)distracting 787 // but does not actually register that info with packagemanager 788 final Bundle extras = new Bundle(); 789 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgs); 790 extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, flag); 791 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uids); 792 793 final Intent intent = new Intent(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED); 794 intent.putExtras(extras); 795 796 mPackageIntentReceiver.onReceive(getContext(), intent); 797 } 798 generateResetComponentValues()799 private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() { 800 ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>(); 801 changed.put(true, new ArrayList<>()); 802 changed.put(false, new ArrayList<>()); 803 return changed; 804 } getApplicationInfo(String pkg, int uid)805 private ApplicationInfo getApplicationInfo(String pkg, int uid) { 806 final ApplicationInfo applicationInfo = new ApplicationInfo(); 807 applicationInfo.uid = uid; 808 switch (pkg) { 809 case PKG_N_MR1: 810 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1; 811 break; 812 case PKG_O: 813 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O; 814 break; 815 case PKG_P: 816 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P; 817 break; 818 default: 819 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; 820 break; 821 } 822 return applicationInfo; 823 } 824 waitForIdle()825 public void waitForIdle() { 826 mTestableLooper.processAllMessages(); 827 } 828 setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled, int pkgPref, boolean channelEnabled)829 private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled, 830 int pkgPref, boolean channelEnabled) { 831 Settings.Secure.putInt(mContext.getContentResolver(), 832 Settings.Secure.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0); 833 mService.mPreferencesHelper.updateBubblesEnabled(); 834 assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled( 835 mock(UserHandle.class))); 836 try { 837 mBinderService.setBubblesAllowed(pkg, uid, pkgPref); 838 } catch (RemoteException e) { 839 e.printStackTrace(); 840 } 841 mTestNotificationChannel.setAllowBubbles(channelEnabled); 842 } 843 generateSbn(String pkg, int uid, long postTime, int userId)844 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) { 845 Notification.Builder nb = new Notification.Builder(mContext, "a") 846 .setContentTitle("foo") 847 .setSmallIcon(android.R.drawable.sym_def_app_icon); 848 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, 849 "tag" + System.currentTimeMillis(), uid, 0, 850 nb.build(), new UserHandle(userId), null, postTime); 851 return sbn; 852 } 853 generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary)854 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, 855 String groupKey, boolean isSummary) { 856 return generateNotificationRecord(channel, id, "tag" + System.currentTimeMillis(), groupKey, 857 isSummary); 858 } 859 generateNotificationRecord(NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary)860 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, 861 String tag, String groupKey, boolean isSummary) { 862 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 863 .setContentTitle("foo") 864 .setSmallIcon(android.R.drawable.sym_def_app_icon) 865 .setGroup(groupKey) 866 .setGroupSummary(isSummary); 867 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, 868 tag, mUid, 0, 869 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 870 return new NotificationRecord(mContext, sbn, channel); 871 } 872 generateNotificationRecord(NotificationChannel channel)873 private NotificationRecord generateNotificationRecord(NotificationChannel channel) { 874 return generateNotificationRecord(channel, null); 875 } 876 generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender)877 private NotificationRecord generateNotificationRecord(NotificationChannel channel, 878 Notification.TvExtender extender) { 879 if (channel == null) { 880 channel = mTestNotificationChannel; 881 } 882 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 883 .setContentTitle("foo") 884 .setSmallIcon(android.R.drawable.sym_def_app_icon) 885 .addAction(new Notification.Action.Builder(null, "test", null).build()); 886 if (extender != null) { 887 nb.extend(extender); 888 } 889 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 890 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 891 return new NotificationRecord(mContext, sbn, channel); 892 } 893 generateNotificationRecord(NotificationChannel channel, int userId)894 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) { 895 return generateNotificationRecord(channel, 1, userId); 896 } 897 generateNotificationRecord(NotificationChannel channel, int id, int userId)898 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, 899 int userId) { 900 if (channel == null) { 901 channel = mTestNotificationChannel; 902 } 903 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 904 .setContentTitle("foo") 905 .setSmallIcon(android.R.drawable.sym_def_app_icon); 906 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0, 907 nb.build(), new UserHandle(userId), null, 0); 908 return new NotificationRecord(mContext, sbn, channel); 909 } 910 generateMessageBubbleNotifRecord(NotificationChannel channel, String tag)911 private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel, 912 String tag) { 913 return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false); 914 } 915 generateMessageBubbleNotifRecord(boolean addMetadata, NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary)916 private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata, 917 NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) { 918 if (channel == null) { 919 channel = mTestNotificationChannel; 920 } 921 if (tag == null) { 922 tag = "tag"; 923 } 924 Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary); 925 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, 926 tag, mUid, 0, 927 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 928 return new NotificationRecord(mContext, sbn, channel); 929 } 930 getSignalExtractorSideEffects()931 private Map<String, Answer> getSignalExtractorSideEffects() { 932 Map<String, Answer> answers = new ArrayMap<>(); 933 934 answers.put("override group key", invocationOnMock -> { 935 ((NotificationRecord) invocationOnMock.getArguments()[0]) 936 .setOverrideGroupKey("bananas"); 937 return null; 938 }); 939 answers.put("override people", invocationOnMock -> { 940 ((NotificationRecord) invocationOnMock.getArguments()[0]) 941 .setPeopleOverride(new ArrayList<>()); 942 return null; 943 }); 944 answers.put("snooze criteria", invocationOnMock -> { 945 ((NotificationRecord) invocationOnMock.getArguments()[0]) 946 .setSnoozeCriteria(new ArrayList<>()); 947 return null; 948 }); 949 answers.put("notification channel", invocationOnMock -> { 950 ((NotificationRecord) invocationOnMock.getArguments()[0]) 951 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW)); 952 return null; 953 }); 954 answers.put("badging", invocationOnMock -> { 955 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0]; 956 r.setShowBadge(!r.canShowBadge()); 957 return null; 958 }); 959 answers.put("bubbles", invocationOnMock -> { 960 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0]; 961 r.setAllowBubble(!r.canBubble()); 962 return null; 963 }); 964 answers.put("package visibility", invocationOnMock -> { 965 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride( 966 Notification.VISIBILITY_SECRET); 967 return null; 968 }); 969 970 return answers; 971 } 972 clearDeviceConfig()973 private void clearDeviceConfig() { 974 DeviceConfig.resetToDefaults( 975 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI); 976 } 977 setDefaultAssistantInDeviceConfig(String componentName)978 private void setDefaultAssistantInDeviceConfig(String componentName) { 979 DeviceConfig.setProperty( 980 DeviceConfig.NAMESPACE_SYSTEMUI, 981 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE, 982 componentName, 983 false); 984 } 985 getMessageStyleNotifBuilder(boolean addBubbleMetadata, String groupKey, boolean isSummary)986 private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata, 987 String groupKey, boolean isSummary) { 988 // Give it a person 989 Person person = new Person.Builder() 990 .setName("bubblebot") 991 .build(); 992 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); 993 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, 994 new Intent().setPackage(mContext.getPackageName()), 995 PendingIntent.FLAG_MUTABLE); 996 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); 997 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", 998 inputIntent).addRemoteInput(remoteInput) 999 .build(); 1000 // Make it messaging style 1001 Notification.Builder nb = new Notification.Builder(mContext, 1002 mTestNotificationChannel.getId()) 1003 .setContentTitle("foo") 1004 .setStyle(new Notification.MessagingStyle(person) 1005 .setConversationTitle("Bubble Chat") 1006 .addMessage("Hello?", 1007 SystemClock.currentThreadTimeMillis() - 300000, person) 1008 .addMessage("Is it me you're looking for?", 1009 SystemClock.currentThreadTimeMillis(), person) 1010 ) 1011 .setActions(replyAction) 1012 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1013 .setShortcutId(VALID_CONVO_SHORTCUT_ID) 1014 .setGroupSummary(isSummary); 1015 if (groupKey != null) { 1016 nb.setGroup(groupKey); 1017 } 1018 if (addBubbleMetadata) { 1019 nb.setBubbleMetadata(getBubbleMetadata()); 1020 } 1021 return nb; 1022 } 1023 getBubbleMetadata()1024 private Notification.BubbleMetadata getBubbleMetadata() { 1025 PendingIntent pendingIntent = mock(PendingIntent.class); 1026 Intent intent = mock(Intent.class); 1027 when(pendingIntent.getIntent()).thenReturn(intent); 1028 when(pendingIntent.getTarget()).thenReturn(pi1); 1029 1030 ActivityInfo info = new ActivityInfo(); 1031 info.resizeMode = RESIZE_MODE_RESIZEABLE; 1032 when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info); 1033 1034 return new Notification.BubbleMetadata.Builder( 1035 pendingIntent, 1036 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon)) 1037 .build(); 1038 } 1039 addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)1040 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel) 1041 throws RemoteException { 1042 1043 String groupKey = "BUBBLE_GROUP"; 1044 1045 // Notification that has bubble metadata 1046 NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */, 1047 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */); 1048 1049 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.getSbn().getTag(), 1050 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(), 1051 nrBubble.getSbn().getUserId()); 1052 waitForIdle(); 1053 1054 // Make sure we are a bubble 1055 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 1056 assertEquals(1, notifsAfter.length); 1057 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0); 1058 1059 // Notification without bubble metadata 1060 NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */, 1061 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */); 1062 1063 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.getSbn().getTag(), 1064 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(), 1065 nrPlain.getSbn().getUserId()); 1066 waitForIdle(); 1067 1068 notifsAfter = mBinderService.getActiveNotifications(PKG); 1069 assertEquals(2, notifsAfter.length); 1070 1071 // Summary notification for both of those 1072 NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */, 1073 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */); 1074 1075 if (summaryAutoCancel) { 1076 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL; 1077 } 1078 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.getSbn().getTag(), 1079 nrSummary.getSbn().getId(), nrSummary.getSbn().getNotification(), 1080 nrSummary.getSbn().getUserId()); 1081 waitForIdle(); 1082 1083 notifsAfter = mBinderService.getActiveNotifications(PKG); 1084 assertEquals(3, notifsAfter.length); 1085 1086 return nrSummary; 1087 } 1088 1089 @Test testLimitTimeOutBroadcast()1090 public void testLimitTimeOutBroadcast() { 1091 NotificationChannel channel = new NotificationChannel("id", "name", 1092 NotificationManager.IMPORTANCE_HIGH); 1093 Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) 1094 .setContentTitle("foo") 1095 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1096 .setTimeoutAfter(1); 1097 1098 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 1099 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 1100 NotificationRecord r = new NotificationRecord(mContext, sbn, channel); 1101 1102 mService.scheduleTimeoutLocked(r); 1103 ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class); 1104 verify(mAlarmManager).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture()); 1105 assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME, 1106 captor.getValue().getIntent().getPackage()); 1107 } 1108 1109 @Test testDefaultAssistant_overrideDefault()1110 public void testDefaultAssistant_overrideDefault() { 1111 final int userId = mContext.getUserId(); 1112 final String testComponent = "package/class"; 1113 final List<UserInfo> userInfos = new ArrayList<>(); 1114 userInfos.add(new UserInfo(userId, "", 0)); 1115 final ArraySet<ComponentName> validAssistants = new ArraySet<>(); 1116 validAssistants.add(ComponentName.unflattenFromString(testComponent)); 1117 when(mActivityManager.isLowRamDevice()).thenReturn(false); 1118 when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt())) 1119 .thenReturn(validAssistants); 1120 when(mAssistants.getDefaultComponents()).thenReturn(validAssistants); 1121 when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos); 1122 1123 mService.setDefaultAssistantForUser(userId); 1124 1125 verify(mAssistants).setPackageOrComponentEnabled( 1126 eq(testComponent), eq(userId), eq(true), eq(true), eq(false)); 1127 } 1128 1129 @Test testCreateNotificationChannels_SingleChannel()1130 public void testCreateNotificationChannels_SingleChannel() throws Exception { 1131 final NotificationChannel channel = 1132 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1133 mBinderService.createNotificationChannels(PKG, 1134 new ParceledListSlice(Arrays.asList(channel))); 1135 final NotificationChannel createdChannel = 1136 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 1137 assertTrue(createdChannel != null); 1138 } 1139 1140 @Test testCreateNotificationChannels_NullChannelThrowsException()1141 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception { 1142 try { 1143 mBinderService.createNotificationChannels(PKG, 1144 new ParceledListSlice(Arrays.asList((Object[])null))); 1145 fail("Exception should be thrown immediately."); 1146 } catch (NullPointerException e) { 1147 // pass 1148 } 1149 } 1150 1151 @Test testCreateNotificationChannels_FirstChannelWithFgndTaskStartsPermDialog()1152 public void testCreateNotificationChannels_FirstChannelWithFgndTaskStartsPermDialog() 1153 throws Exception { 1154 when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID); 1155 final NotificationChannel channel = 1156 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1157 mBinderService.createNotificationChannels(PKG_NO_CHANNELS, 1158 new ParceledListSlice(Arrays.asList(channel))); 1159 verify(mWorkerHandler).post(eq(new NotificationManagerService 1160 .ShowNotificationPermissionPromptRunnable(PKG_NO_CHANNELS, 1161 mUserId, TEST_TASK_ID, mPermissionPolicyInternal))); 1162 } 1163 1164 @Test testCreateNotificationChannels_SecondChannelWithFgndTaskDoesntStartPermDialog()1165 public void testCreateNotificationChannels_SecondChannelWithFgndTaskDoesntStartPermDialog() 1166 throws Exception { 1167 when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID); 1168 assertTrue(mBinderService.getNumNotificationChannelsForPackage(PKG, mUid, true) > 0); 1169 1170 final NotificationChannel channel = 1171 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1172 mBinderService.createNotificationChannels(PKG, 1173 new ParceledListSlice(Arrays.asList(channel))); 1174 verify(mWorkerHandler, never()).post(any( 1175 NotificationManagerService.ShowNotificationPermissionPromptRunnable.class)); 1176 } 1177 1178 @Test testCreateNotificationChannels_FirstChannelWithBgndTaskDoesntStartPermDialog()1179 public void testCreateNotificationChannels_FirstChannelWithBgndTaskDoesntStartPermDialog() 1180 throws Exception { 1181 reset(mPermissionPolicyInternal); 1182 when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID); 1183 1184 final NotificationChannel channel = 1185 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1186 mBinderService.createNotificationChannels(PKG, 1187 new ParceledListSlice(Arrays.asList(channel))); 1188 1189 verify(mWorkerHandler, never()).post(any( 1190 NotificationManagerService.ShowNotificationPermissionPromptRunnable.class)); 1191 } 1192 1193 @Test testCreateNotificationChannels_TwoChannels()1194 public void testCreateNotificationChannels_TwoChannels() throws Exception { 1195 final NotificationChannel channel1 = 1196 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT); 1197 final NotificationChannel channel2 = 1198 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT); 1199 mBinderService.createNotificationChannels(PKG, 1200 new ParceledListSlice(Arrays.asList(channel1, channel2))); 1201 assertTrue(mBinderService.getNotificationChannel( 1202 PKG, mContext.getUserId(), PKG, "id1") != null); 1203 assertTrue(mBinderService.getNotificationChannel( 1204 PKG, mContext.getUserId(), PKG, "id2") != null); 1205 } 1206 1207 @Test testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()1208 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance() 1209 throws Exception { 1210 final NotificationChannel channel = 1211 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1212 mBinderService.createNotificationChannels(PKG, 1213 new ParceledListSlice(Arrays.asList(channel))); 1214 1215 // Recreating the channel doesn't throw, but ignores importance. 1216 final NotificationChannel dupeChannel = 1217 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 1218 mBinderService.createNotificationChannels(PKG, 1219 new ParceledListSlice(Arrays.asList(dupeChannel))); 1220 final NotificationChannel createdChannel = 1221 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 1222 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); 1223 } 1224 1225 @Test testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()1226 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance() 1227 throws Exception { 1228 final NotificationChannel channel = 1229 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1230 mBinderService.createNotificationChannels(PKG, 1231 new ParceledListSlice(Arrays.asList(channel))); 1232 1233 // Recreating with a lower importance is allowed to modify the channel. 1234 final NotificationChannel dupeChannel = 1235 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); 1236 mBinderService.createNotificationChannels(PKG, 1237 new ParceledListSlice(Arrays.asList(dupeChannel))); 1238 final NotificationChannel createdChannel = 1239 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 1240 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance()); 1241 } 1242 1243 @Test testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()1244 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated() 1245 throws Exception { 1246 final NotificationChannel channel = 1247 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1248 mBinderService.createNotificationChannels(PKG, 1249 new ParceledListSlice(Arrays.asList(channel))); 1250 1251 // The user modifies importance directly, can no longer be changed by the app. 1252 final NotificationChannel updatedChannel = 1253 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 1254 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel); 1255 1256 // Recreating with a lower importance leaves channel unchanged. 1257 final NotificationChannel dupeChannel = 1258 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); 1259 mBinderService.createNotificationChannels(PKG, 1260 new ParceledListSlice(Arrays.asList(dupeChannel))); 1261 final NotificationChannel createdChannel = 1262 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 1263 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance()); 1264 } 1265 1266 @Test testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()1267 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond() 1268 throws Exception { 1269 final NotificationChannel channel1 = 1270 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); 1271 final NotificationChannel channel2 = 1272 new NotificationChannel("id", "name", IMPORTANCE_HIGH); 1273 mBinderService.createNotificationChannels(PKG, 1274 new ParceledListSlice(Arrays.asList(channel1, channel2))); 1275 final NotificationChannel createdChannel = 1276 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); 1277 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); 1278 } 1279 1280 @Test testBlockedNotifications_suspended()1281 public void testBlockedNotifications_suspended() throws Exception { 1282 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true); 1283 1284 NotificationChannel channel = new NotificationChannel("id", "name", 1285 IMPORTANCE_HIGH); 1286 NotificationRecord r = generateNotificationRecord(channel); 1287 1288 // isBlocked is only used for user blocking, not app suspension 1289 assertFalse(mService.isRecordBlockedLocked(r)); 1290 } 1291 1292 @Test testBlockedNotifications_blockedChannel()1293 public void testBlockedNotifications_blockedChannel() throws Exception { 1294 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1295 1296 NotificationChannel channel = new NotificationChannel("id", "name", 1297 NotificationManager.IMPORTANCE_NONE); 1298 NotificationRecord r = generateNotificationRecord(channel); 1299 assertTrue(mService.isRecordBlockedLocked(r)); 1300 1301 mBinderService.createNotificationChannels( 1302 PKG, new ParceledListSlice(Arrays.asList(channel))); 1303 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn(); 1304 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1305 "testBlockedNotifications_blockedChannel", 1306 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1307 waitForIdle(); 1308 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1309 } 1310 1311 @Test testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()1312 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService() 1313 throws Exception { 1314 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1315 when(mAmi.applyForegroundServiceNotification( 1316 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY); 1317 1318 NotificationChannel channel = new NotificationChannel("blocked", "name", 1319 NotificationManager.IMPORTANCE_NONE); 1320 mBinderService.createNotificationChannels( 1321 PKG, new ParceledListSlice(Arrays.asList(channel))); 1322 1323 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn(); 1324 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1325 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 1326 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1327 waitForIdle(); 1328 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1329 assertEquals(IMPORTANCE_LOW, 1330 mService.getNotificationRecord(sbn.getKey()).getImportance()); 1331 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel( 1332 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1333 } 1334 1335 @Test testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()1336 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService() 1337 throws Exception { 1338 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1339 when(mAmi.applyForegroundServiceNotification( 1340 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY); 1341 1342 NotificationChannel channel = 1343 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH); 1344 mBinderService.createNotificationChannels( 1345 PKG, new ParceledListSlice(Arrays.asList(channel))); 1346 1347 NotificationChannel update = 1348 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); 1349 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); 1350 waitForIdle(); 1351 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 1352 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1353 1354 StatusBarNotification sbn = generateNotificationRecord(channel).getSbn(); 1355 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1356 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 1357 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1358 waitForIdle(); 1359 // The first time a foreground service notification is shown, we allow the channel 1360 // to be updated to allow it to be seen. 1361 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1362 assertEquals(IMPORTANCE_LOW, 1363 mService.getNotificationRecord(sbn.getKey()).getImportance()); 1364 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel( 1365 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1366 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); 1367 waitForIdle(); 1368 1369 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); 1370 update.setUserVisibleTaskShown(true); 1371 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); 1372 waitForIdle(); 1373 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 1374 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1375 1376 sbn = generateNotificationRecord(channel).getSbn(); 1377 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1378 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1379 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService", 1380 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1381 waitForIdle(); 1382 // The second time it is shown, we keep the user's preference. 1383 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1384 assertNull(mService.getNotificationRecord(sbn.getKey())); 1385 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( 1386 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); 1387 } 1388 1389 @Test testBlockedNotifications_blockedChannelGroup()1390 public void testBlockedNotifications_blockedChannelGroup() throws Exception { 1391 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1392 mService.setPreferencesHelper(mPreferencesHelper); 1393 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())). 1394 thenReturn(true); 1395 1396 NotificationChannel channel = new NotificationChannel("id", "name", 1397 NotificationManager.IMPORTANCE_HIGH); 1398 channel.setGroup("something"); 1399 NotificationRecord r = generateNotificationRecord(channel); 1400 assertTrue(mService.isRecordBlockedLocked(r)); 1401 } 1402 1403 @Test testEnqueuedBlockedNotifications_blockedApp()1404 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception { 1405 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1406 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 1407 1408 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1409 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1410 "testEnqueuedBlockedNotifications_blockedApp", 1411 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1412 waitForIdle(); 1413 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1414 } 1415 1416 @Test testEnqueuedBlockedNotifications_blockedAppForegroundService()1417 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception { 1418 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1419 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 1420 when(mAmi.applyForegroundServiceNotification( 1421 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY); 1422 1423 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1424 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 1425 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1426 "testEnqueuedBlockedNotifications_blockedAppForegroundService", 1427 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1428 waitForIdle(); 1429 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 1430 assertNull(mService.getNotificationRecord(sbn.getKey())); 1431 } 1432 1433 /** 1434 * Confirm an application with the SEND_CATEGORY_CAR_NOTIFICATIONS permission on automotive 1435 * devices can use car categories. 1436 */ 1437 @Test testEnqueuedRestrictedNotifications_hasPermission()1438 public void testEnqueuedRestrictedNotifications_hasPermission() throws Exception { 1439 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 1440 .thenReturn(true); 1441 // SEND_CATEGORY_CAR_NOTIFICATIONS is a system-level permission that this test cannot 1442 // obtain. Mocking out enforce permission call to ensure notifications can be created when 1443 // permitted. 1444 doNothing().when(mContext).enforceCallingPermission( 1445 eq("android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"), anyString()); 1446 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 1447 Notification.CATEGORY_CAR_WARNING, 1448 Notification.CATEGORY_CAR_INFORMATION); 1449 int id = 0; 1450 for (String category: categories) { 1451 final StatusBarNotification sbn = 1452 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn(); 1453 sbn.getNotification().category = category; 1454 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1455 "testEnqueuedRestrictedNotifications_asSystem", 1456 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1457 } 1458 waitForIdle(); 1459 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length); 1460 } 1461 1462 1463 /** 1464 * Confirm restricted notification categories only apply to automotive. 1465 */ 1466 @Test testEnqueuedRestrictedNotifications_notAutomotive()1467 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception { 1468 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 1469 .thenReturn(false); 1470 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 1471 Notification.CATEGORY_CAR_WARNING, 1472 Notification.CATEGORY_CAR_INFORMATION); 1473 int id = 0; 1474 for (String category: categories) { 1475 final StatusBarNotification sbn = 1476 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn(); 1477 sbn.getNotification().category = category; 1478 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1479 "testEnqueuedRestrictedNotifications_notAutomotive", 1480 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1481 } 1482 waitForIdle(); 1483 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length); 1484 } 1485 1486 /** 1487 * Confirm if an application tries to use the car categories on a automotive device without the 1488 * SEND_CATEGORY_CAR_NOTIFICATIONS permission that a security exception will be thrown. 1489 */ 1490 @Test testEnqueuedRestrictedNotifications_noPermission()1491 public void testEnqueuedRestrictedNotifications_noPermission() throws Exception { 1492 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) 1493 .thenReturn(true); 1494 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, 1495 Notification.CATEGORY_CAR_WARNING, 1496 Notification.CATEGORY_CAR_INFORMATION); 1497 for (String category: categories) { 1498 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 1499 sbn.getNotification().category = category; 1500 try { 1501 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1502 "testEnqueuedRestrictedNotifications_badUser", 1503 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1504 fail("Calls from non system apps should not allow use of restricted categories"); 1505 } catch (SecurityException e) { 1506 // pass 1507 } 1508 } 1509 waitForIdle(); 1510 assertEquals(0, mBinderService.getActiveNotifications(PKG).length); 1511 } 1512 1513 @Test testSetNotificationsEnabledForPackage_noChange()1514 public void testSetNotificationsEnabledForPackage_noChange() throws Exception { 1515 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 1516 mBinderService.setNotificationsEnabledForPackage(mContext.getPackageName(), mUid, true); 1517 1518 verify(mPermissionHelper, never()).setNotificationPermission( 1519 anyString(), anyInt(), anyBoolean(), anyBoolean()); 1520 } 1521 1522 @Test testSetNotificationsEnabledForPackage()1523 public void testSetNotificationsEnabledForPackage() throws Exception { 1524 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 1525 mBinderService.setNotificationsEnabledForPackage(mContext.getPackageName(), mUid, false); 1526 1527 verify(mPermissionHelper).setNotificationPermission( 1528 mContext.getPackageName(), mUserId, false, true); 1529 1530 verify(mAppOpsManager, never()).setMode(anyInt(), anyInt(), anyString(), anyInt()); 1531 List<NotificationChannelLoggerFake.CallRecord> calls = mLogger.getCalls(); 1532 Assert.assertEquals( 1533 NotificationChannelLogger.NotificationChannelEvent.APP_NOTIFICATIONS_BLOCKED, 1534 calls.get(calls.size() -1).event); 1535 } 1536 1537 @Test testBlockedNotifications_blockedByAssistant()1538 public void testBlockedNotifications_blockedByAssistant() throws Exception { 1539 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1540 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 1541 1542 NotificationChannel channel = new NotificationChannel("id", "name", 1543 NotificationManager.IMPORTANCE_HIGH); 1544 NotificationRecord r = generateNotificationRecord(channel); 1545 mService.addEnqueuedNotification(r); 1546 1547 Bundle bundle = new Bundle(); 1548 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE); 1549 Adjustment adjustment = new Adjustment( 1550 r.getSbn().getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier()); 1551 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 1552 1553 NotificationManagerService.PostNotificationRunnable runnable = 1554 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 1555 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 1556 runnable.run(); 1557 waitForIdle(); 1558 1559 verify(mUsageStats, never()).registerPostedByApp(any()); 1560 } 1561 1562 @Test testBlockedNotifications_blockedByUser()1563 public void testBlockedNotifications_blockedByUser() throws Exception { 1564 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 1565 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 1566 1567 NotificationChannel channel = new NotificationChannel("id", "name", 1568 NotificationManager.IMPORTANCE_HIGH); 1569 NotificationRecord r = generateNotificationRecord(channel); 1570 mService.addEnqueuedNotification(r); 1571 1572 when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false); 1573 1574 NotificationManagerService.PostNotificationRunnable runnable = 1575 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 1576 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 1577 runnable.run(); 1578 waitForIdle(); 1579 1580 verify(mUsageStats).registerBlocked(any()); 1581 verify(mUsageStats, never()).registerPostedByApp(any()); 1582 } 1583 1584 @Test testEnqueueNotificationInternal_noChannel()1585 public void testEnqueueNotificationInternal_noChannel() throws Exception { 1586 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 1587 NotificationRecord nr = generateNotificationRecord( 1588 new NotificationChannel("did not create", "", IMPORTANCE_DEFAULT)); 1589 1590 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 1591 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 1592 waitForIdle(); 1593 1594 verify(mPermissionHelper).hasPermission(mUid); 1595 verify(mPermissionHelper, never()).hasPermission(Process.SYSTEM_UID); 1596 1597 reset(mPermissionHelper); 1598 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 1599 1600 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 1601 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 1602 waitForIdle(); 1603 1604 verify(mPermissionHelper).hasPermission(mUid); 1605 assertThat(mService.mChannelToastsSent).contains(mUid); 1606 } 1607 1608 @Test testEnqueueNotification_appBlocked()1609 public void testEnqueueNotification_appBlocked() throws Exception { 1610 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 1611 1612 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1613 "testEnqueueNotification_appBlocked", 0, 1614 generateNotificationRecord(null).getNotification(), 0); 1615 waitForIdle(); 1616 verify(mWorkerHandler, never()).post( 1617 any(NotificationManagerService.EnqueueNotificationRunnable.class)); 1618 } 1619 1620 @Test testEnqueueNotificationWithTag_PopulatesGetActiveNotifications()1621 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception { 1622 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1623 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1624 generateNotificationRecord(null).getNotification(), 0); 1625 waitForIdle(); 1626 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 1627 assertEquals(1, notifs.length); 1628 assertEquals(1, mService.getNotificationRecordCount()); 1629 } 1630 1631 @Test testEnqueueNotificationWithTag_WritesExpectedLogs()1632 public void testEnqueueNotificationWithTag_WritesExpectedLogs() throws Exception { 1633 final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog"; 1634 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1635 generateNotificationRecord(null).getNotification(), 0); 1636 waitForIdle(); 1637 assertEquals(1, mNotificationRecordLogger.numCalls()); 1638 1639 NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0); 1640 assertTrue(call.wasLogged); 1641 assertEquals(NOTIFICATION_POSTED, call.event); 1642 assertNotNull(call.r); 1643 assertNull(call.old); 1644 assertEquals(0, call.position); 1645 assertEquals(0, call.buzzBeepBlink); 1646 assertEquals(PKG, call.r.getSbn().getPackageName()); 1647 assertEquals(0, call.r.getSbn().getId()); 1648 assertEquals(tag, call.r.getSbn().getTag()); 1649 assertEquals(1, call.getInstanceId()); // Fake instance IDs are assigned in order 1650 assertThat(call.postDurationMillisLogged).isGreaterThan(0); 1651 } 1652 1653 @Test testEnqueueNotificationWithTag_LogsOnMajorUpdates()1654 public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception { 1655 final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates"; 1656 Notification original = new Notification.Builder(mContext, 1657 mTestNotificationChannel.getId()) 1658 .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); 1659 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0); 1660 Notification update = new Notification.Builder(mContext, 1661 mTestNotificationChannel.getId()) 1662 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1663 .setCategory(Notification.CATEGORY_ALARM).build(); 1664 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0); 1665 waitForIdle(); 1666 assertEquals(2, mNotificationRecordLogger.numCalls()); 1667 1668 assertTrue(mNotificationRecordLogger.get(0).wasLogged); 1669 assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0)); 1670 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 1671 assertThat(mNotificationRecordLogger.get(0).postDurationMillisLogged).isGreaterThan(0); 1672 1673 assertTrue(mNotificationRecordLogger.get(1).wasLogged); 1674 assertEquals(NOTIFICATION_UPDATED, mNotificationRecordLogger.event(1)); 1675 // Instance ID doesn't change on update of an active notification 1676 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); 1677 assertThat(mNotificationRecordLogger.get(1).postDurationMillisLogged).isGreaterThan(0); 1678 } 1679 1680 @Test testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate()1681 public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate() throws Exception { 1682 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate"; 1683 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1684 generateNotificationRecord(null).getNotification(), 0); 1685 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1686 generateNotificationRecord(null).getNotification(), 0); 1687 waitForIdle(); 1688 assertEquals(2, mNotificationRecordLogger.numCalls()); 1689 assertTrue(mNotificationRecordLogger.get(0).wasLogged); 1690 assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0)); 1691 assertFalse(mNotificationRecordLogger.get(1).wasLogged); 1692 assertNull(mNotificationRecordLogger.event(1)); 1693 } 1694 1695 @Test testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate()1696 public void testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate() throws Exception { 1697 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate"; 1698 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, 1699 generateNotificationRecord(null).getNotification(), 1700 0); 1701 final Notification notif = generateNotificationRecord(null).getNotification(); 1702 notif.extras.putString(Notification.EXTRA_TITLE, "Changed title"); 1703 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notif, 0); 1704 waitForIdle(); 1705 assertEquals(2, mNotificationRecordLogger.numCalls()); 1706 assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0)); 1707 assertNull(mNotificationRecordLogger.event(1)); 1708 } 1709 1710 @Test testEnqueueNotificationWithTag_LogsAgainAfterCancel()1711 public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception { 1712 final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel"; 1713 Notification notification = new Notification.Builder(mContext, 1714 mTestNotificationChannel.getId()) 1715 .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); 1716 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0); 1717 waitForIdle(); 1718 mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0); 1719 waitForIdle(); 1720 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0); 1721 waitForIdle(); 1722 assertEquals(3, mNotificationRecordLogger.numCalls()); 1723 1724 assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0)); 1725 assertTrue(mNotificationRecordLogger.get(0).wasLogged); 1726 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 1727 assertThat(mNotificationRecordLogger.get(0).postDurationMillisLogged).isGreaterThan(0); 1728 1729 assertEquals( 1730 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL, 1731 mNotificationRecordLogger.event(1)); 1732 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); 1733 // Cancel is not post, so no logged post_duration_millis. 1734 assertThat(mNotificationRecordLogger.get(1).postDurationMillisLogged).isNull(); 1735 1736 assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(2)); 1737 assertTrue(mNotificationRecordLogger.get(2).wasLogged); 1738 // New instance ID because notification was canceled before re-post 1739 assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId()); 1740 assertThat(mNotificationRecordLogger.get(2).postDurationMillisLogged).isGreaterThan(0); 1741 } 1742 1743 @Test testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed()1744 public void testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed() throws Exception { 1745 when(mAmi.applyForegroundServiceNotification( 1746 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY); 1747 mContext.getTestablePermissions().setPermission( 1748 android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_GRANTED); 1749 1750 final String tag = "testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed"; 1751 1752 Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId()) 1753 .setContentTitle("foo") 1754 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1755 .setFlag(FLAG_FOREGROUND_SERVICE, true) 1756 .build(); 1757 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, tag, mUid, 0, 1758 n, UserHandle.getUserHandleForUid(mUid), null, 0); 1759 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 1760 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 1761 waitForIdle(); 1762 1763 StatusBarNotification[] notifs = 1764 mBinderService.getActiveNotifications(PKG); 1765 assertThat(notifs[0].getNotification().flags).isEqualTo( 1766 FLAG_FOREGROUND_SERVICE | FLAG_CAN_COLORIZE | FLAG_NO_CLEAR); 1767 } 1768 1769 @Test testEnqueueNotificationWithTag_nullAction_fixed()1770 public void testEnqueueNotificationWithTag_nullAction_fixed() throws Exception { 1771 Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId()) 1772 .setContentTitle("foo") 1773 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1774 .addAction(new Notification.Action.Builder(null, "one", null).build()) 1775 .addAction(new Notification.Action.Builder(null, "two", null).build()) 1776 .addAction(new Notification.Action.Builder(null, "three", null).build()) 1777 .build(); 1778 n.actions[1] = null; 1779 1780 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, 0); 1781 waitForIdle(); 1782 1783 StatusBarNotification[] posted = mBinderService.getActiveNotifications(PKG); 1784 assertThat(posted).hasLength(1); 1785 assertThat(posted[0].getNotification().actions).hasLength(2); 1786 assertThat(posted[0].getNotification().actions[0].title.toString()).isEqualTo("one"); 1787 assertThat(posted[0].getNotification().actions[1].title.toString()).isEqualTo("three"); 1788 } 1789 1790 @Test testEnqueueNotificationWithTag_allNullActions_fixed()1791 public void testEnqueueNotificationWithTag_allNullActions_fixed() throws Exception { 1792 Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId()) 1793 .setContentTitle("foo") 1794 .setSmallIcon(android.R.drawable.sym_def_app_icon) 1795 .addAction(new Notification.Action.Builder(null, "one", null).build()) 1796 .addAction(new Notification.Action.Builder(null, "two", null).build()) 1797 .build(); 1798 n.actions[0] = null; 1799 n.actions[1] = null; 1800 1801 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, 0); 1802 waitForIdle(); 1803 1804 StatusBarNotification[] posted = mBinderService.getActiveNotifications(PKG); 1805 assertThat(posted).hasLength(1); 1806 assertThat(posted[0].getNotification().actions).isNull(); 1807 } 1808 1809 @Test enqueueNotificationWithTag_usesAndFinishesTracker()1810 public void enqueueNotificationWithTag_usesAndFinishesTracker() throws Exception { 1811 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1812 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1813 generateNotificationRecord(null).getNotification(), 0); 1814 1815 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1); 1816 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isTrue(); 1817 1818 waitForIdle(); 1819 1820 assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(1); 1821 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1); 1822 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse(); 1823 } 1824 1825 @Test enqueueNotificationWithTag_throws_usesAndCancelsTracker()1826 public void enqueueNotificationWithTag_throws_usesAndCancelsTracker() throws Exception { 1827 // Simulate not enqueued due to rejected inputs. 1828 assertThrows(Exception.class, 1829 () -> mBinderService.enqueueNotificationWithTag(PKG, PKG, 1830 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1831 /* notification= */ null, 0)); 1832 1833 waitForIdle(); 1834 1835 assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0); 1836 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1); 1837 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse(); 1838 } 1839 1840 @Test enqueueNotificationWithTag_notEnqueued_usesAndCancelsTracker()1841 public void enqueueNotificationWithTag_notEnqueued_usesAndCancelsTracker() throws Exception { 1842 // Simulate not enqueued due to snoozing inputs. 1843 when(mSnoozeHelper.getSnoozeContextForUnpostedNotification(anyInt(), any(), any())) 1844 .thenReturn("zzzzzzz"); 1845 1846 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1847 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1848 generateNotificationRecord(null).getNotification(), 0); 1849 waitForIdle(); 1850 1851 assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0); 1852 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1); 1853 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse(); 1854 } 1855 1856 @Test enqueueNotificationWithTag_notPosted_usesAndCancelsTracker()1857 public void enqueueNotificationWithTag_notPosted_usesAndCancelsTracker() throws Exception { 1858 // Simulate not posted due to blocked app. 1859 when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false); 1860 1861 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1862 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, 1863 generateNotificationRecord(null).getNotification(), 0); 1864 waitForIdle(); 1865 1866 assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0); 1867 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1); 1868 assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse(); 1869 } 1870 1871 @Test enqueueNotification_acquiresAndReleasesWakeLock()1872 public void enqueueNotification_acquiresAndReleasesWakeLock() throws Exception { 1873 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1874 "enqueueNotification_acquiresAndReleasesWakeLock", 0, 1875 generateNotificationRecord(null).getNotification(), 0); 1876 1877 verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString()); 1878 assertThat(mAcquiredWakeLocks).hasSize(1); 1879 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue(); 1880 1881 waitForIdle(); 1882 1883 assertThat(mAcquiredWakeLocks).hasSize(1); 1884 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse(); 1885 } 1886 1887 @Test enqueueNotification_throws_acquiresAndReleasesWakeLock()1888 public void enqueueNotification_throws_acquiresAndReleasesWakeLock() throws Exception { 1889 // Simulate not enqueued due to rejected inputs. 1890 assertThrows(Exception.class, 1891 () -> mBinderService.enqueueNotificationWithTag(PKG, PKG, 1892 "enqueueNotification_throws_acquiresAndReleasesWakeLock", 0, 1893 /* notification= */ null, 0)); 1894 1895 verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString()); 1896 assertThat(mAcquiredWakeLocks).hasSize(1); 1897 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse(); 1898 } 1899 1900 @Test enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock()1901 public void enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock() throws Exception { 1902 // Simulate not enqueued due to snoozing inputs. 1903 when(mSnoozeHelper.getSnoozeContextForUnpostedNotification(anyInt(), any(), any())) 1904 .thenReturn("zzzzzzz"); 1905 1906 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1907 "enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock", 0, 1908 generateNotificationRecord(null).getNotification(), 0); 1909 1910 verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString()); 1911 assertThat(mAcquiredWakeLocks).hasSize(1); 1912 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue(); 1913 1914 waitForIdle(); 1915 1916 assertThat(mAcquiredWakeLocks).hasSize(1); 1917 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse(); 1918 } 1919 1920 @Test enqueueNotification_notPosted_acquiresAndReleasesWakeLock()1921 public void enqueueNotification_notPosted_acquiresAndReleasesWakeLock() throws Exception { 1922 // Simulate enqueued but not posted due to missing small icon. 1923 Notification notif = new Notification.Builder(mContext, mTestNotificationChannel.getId()) 1924 .setContentTitle("foo") 1925 .build(); 1926 1927 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1928 "enqueueNotification_notPosted_acquiresAndReleasesWakeLock", 0, 1929 notif, 0); 1930 1931 verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString()); 1932 assertThat(mAcquiredWakeLocks).hasSize(1); 1933 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue(); 1934 1935 waitForIdle(); 1936 1937 // NLSes were not called. 1938 verify(mListeners, never()).prepareNotifyPostedLocked(any(), any(), anyBoolean()); 1939 1940 assertThat(mAcquiredWakeLocks).hasSize(1); 1941 assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse(); 1942 } 1943 1944 @Test enqueueNotification_setsWakeLockWorkSource()1945 public void enqueueNotification_setsWakeLockWorkSource() throws Exception { 1946 // Use a "full" mock for the PowerManager (instead of the one that delegates to the real 1947 // service) so we can return a mocked WakeLock that we can verify() on. 1948 reset(mPowerManager); 1949 WakeLock wakeLock = mock(WakeLock.class); 1950 when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(wakeLock); 1951 1952 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1953 "enqueueNotification_setsWakeLockWorkSource", 0, 1954 generateNotificationRecord(null).getNotification(), 0); 1955 waitForIdle(); 1956 1957 InOrder inOrder = inOrder(mPowerManager, wakeLock); 1958 inOrder.verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString()); 1959 inOrder.verify(wakeLock).setWorkSource(eq(new WorkSource(mUid, PKG))); 1960 inOrder.verify(wakeLock).acquire(anyLong()); 1961 inOrder.verify(wakeLock).release(); 1962 inOrder.verifyNoMoreInteractions(); 1963 } 1964 1965 @Test enqueueNotification_wakeLockSystemPropertyOff_noWakeLock()1966 public void enqueueNotification_wakeLockSystemPropertyOff_noWakeLock() throws Exception { 1967 mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, false); 1968 DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, 1969 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "true", false); 1970 1971 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1972 "enqueueNotification_setsWakeLockWorkSource", 0, 1973 generateNotificationRecord(null).getNotification(), 0); 1974 waitForIdle(); 1975 1976 verifyZeroInteractions(mPowerManager); 1977 } 1978 1979 @Test enqueueNotification_wakeLockDeviceConfigOff_noWakeLock()1980 public void enqueueNotification_wakeLockDeviceConfigOff_noWakeLock() throws Exception { 1981 mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true); 1982 DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, 1983 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "false", false); 1984 1985 mBinderService.enqueueNotificationWithTag(PKG, PKG, 1986 "enqueueNotification_setsWakeLockWorkSource", 0, 1987 generateNotificationRecord(null).getNotification(), 0); 1988 waitForIdle(); 1989 1990 verifyZeroInteractions(mPowerManager); 1991 } 1992 1993 @Test testCancelNonexistentNotification()1994 public void testCancelNonexistentNotification() throws Exception { 1995 mBinderService.cancelNotificationWithTag(PKG, PKG, 1996 "testCancelNonexistentNotification", 0, 0); 1997 waitForIdle(); 1998 // The notification record logger doesn't even get called when a nonexistent notification 1999 // is cancelled, because that happens very frequently and is not interesting. 2000 assertEquals(0, mNotificationRecordLogger.numCalls()); 2001 } 2002 2003 @Test testCancelNotificationImmediatelyAfterEnqueue()2004 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception { 2005 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2006 "testCancelNotificationImmediatelyAfterEnqueue", 0, 2007 generateNotificationRecord(null).getNotification(), 0); 2008 mBinderService.cancelNotificationWithTag(PKG, PKG, 2009 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0); 2010 waitForIdle(); 2011 StatusBarNotification[] notifs = 2012 mBinderService.getActiveNotifications(PKG); 2013 assertEquals(0, notifs.length); 2014 assertEquals(0, mService.getNotificationRecordCount()); 2015 } 2016 2017 @Test testPostCancelPostNotifiesListeners()2018 public void testPostCancelPostNotifiesListeners() throws Exception { 2019 // WHEN a notification is posted 2020 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2021 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), 2022 sbn.getNotification(), sbn.getUserId()); 2023 mTestableLooper.moveTimeForward(1); 2024 // THEN it is canceled 2025 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); 2026 mTestableLooper.moveTimeForward(1); 2027 // THEN it is posted again (before the cancel has a chance to finish) 2028 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), 2029 sbn.getNotification(), sbn.getUserId()); 2030 // THEN the later enqueue isn't swallowed by the cancel. I.e., ordering is respected 2031 waitForIdle(); 2032 2033 // The final enqueue made it to the listener instead of being canceled 2034 StatusBarNotification[] notifs = 2035 mBinderService.getActiveNotifications(PKG); 2036 assertEquals(1, notifs.length); 2037 assertEquals(1, mService.getNotificationRecordCount()); 2038 } 2039 2040 @Test testCancelNotificationWhilePostedAndEnqueued()2041 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception { 2042 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2043 "testCancelNotificationWhilePostedAndEnqueued", 0, 2044 generateNotificationRecord(null).getNotification(), 0); 2045 waitForIdle(); 2046 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2047 "testCancelNotificationWhilePostedAndEnqueued", 0, 2048 generateNotificationRecord(null).getNotification(), 0); 2049 mBinderService.cancelNotificationWithTag(PKG, PKG, 2050 "testCancelNotificationWhilePostedAndEnqueued", 0, 0); 2051 waitForIdle(); 2052 StatusBarNotification[] notifs = 2053 mBinderService.getActiveNotifications(PKG); 2054 assertEquals(0, notifs.length); 2055 assertEquals(0, mService.getNotificationRecordCount()); 2056 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 2057 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture()); 2058 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface()); 2059 } 2060 2061 @Test testCancelNotificationsFromListenerImmediatelyAfterEnqueue()2062 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception { 2063 NotificationRecord r = generateNotificationRecord(null); 2064 final StatusBarNotification sbn = r.getSbn(); 2065 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2066 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue", 2067 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2068 mBinderService.cancelNotificationsFromListener(null, null); 2069 waitForIdle(); 2070 StatusBarNotification[] notifs = 2071 mBinderService.getActiveNotifications(sbn.getPackageName()); 2072 assertEquals(0, notifs.length); 2073 assertEquals(0, mService.getNotificationRecordCount()); 2074 } 2075 2076 @Test testCancelAllNotificationsImmediatelyAfterEnqueue()2077 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception { 2078 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2079 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2080 "testCancelAllNotificationsImmediatelyAfterEnqueue", 2081 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2082 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2083 waitForIdle(); 2084 StatusBarNotification[] notifs = 2085 mBinderService.getActiveNotifications(sbn.getPackageName()); 2086 assertEquals(0, notifs.length); 2087 assertEquals(0, mService.getNotificationRecordCount()); 2088 } 2089 2090 @Test testUserInitiatedClearAll_noLeak()2091 public void testUserInitiatedClearAll_noLeak() throws Exception { 2092 final NotificationRecord n = generateNotificationRecord( 2093 mTestNotificationChannel, 1, "group", true); 2094 2095 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2096 "testUserInitiatedClearAll_noLeak", 2097 n.getSbn().getId(), n.getSbn().getNotification(), n.getSbn().getUserId()); 2098 waitForIdle(); 2099 2100 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 2101 n.getUserId()); 2102 waitForIdle(); 2103 StatusBarNotification[] notifs = 2104 mBinderService.getActiveNotifications(n.getSbn().getPackageName()); 2105 assertEquals(0, notifs.length); 2106 assertEquals(0, mService.getNotificationRecordCount()); 2107 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 2108 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture()); 2109 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface()); 2110 } 2111 2112 @Test testCancelAllNotificationsCancelsChildren()2113 public void testCancelAllNotificationsCancelsChildren() throws Exception { 2114 final NotificationRecord parent = generateNotificationRecord( 2115 mTestNotificationChannel, 1, "group1", true); 2116 final NotificationRecord child = generateNotificationRecord( 2117 mTestNotificationChannel, 2, "group1", false); 2118 2119 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2120 "testCancelAllNotificationsCancelsChildren", 2121 parent.getSbn().getId(), parent.getSbn().getNotification(), 2122 parent.getSbn().getUserId()); 2123 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2124 "testCancelAllNotificationsCancelsChildren", 2125 child.getSbn().getId(), child.getSbn().getNotification(), 2126 child.getSbn().getUserId()); 2127 waitForIdle(); 2128 2129 mBinderService.cancelAllNotifications(PKG, parent.getSbn().getUserId()); 2130 waitForIdle(); 2131 assertEquals(0, mService.getNotificationRecordCount()); 2132 } 2133 2134 @Test testCancelAllNotificationsMultipleEnqueuedDoesNotCrash()2135 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception { 2136 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2137 for (int i = 0; i < 10; i++) { 2138 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2139 "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash", 2140 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2141 } 2142 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2143 waitForIdle(); 2144 2145 assertEquals(0, mService.getNotificationRecordCount()); 2146 } 2147 2148 @Test testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash()2149 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception { 2150 final NotificationRecord parent = generateNotificationRecord( 2151 mTestNotificationChannel, 1, "group1", true); 2152 final NotificationRecord parentAsChild = generateNotificationRecord( 2153 mTestNotificationChannel, 1, "group1", false); 2154 final NotificationRecord child = generateNotificationRecord( 2155 mTestNotificationChannel, 2, "group1", false); 2156 2157 // fully post parent notification 2158 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2159 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", 2160 parent.getSbn().getId(), parent.getSbn().getNotification(), 2161 parent.getSbn().getUserId()); 2162 waitForIdle(); 2163 2164 // enqueue the child several times 2165 for (int i = 0; i < 10; i++) { 2166 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2167 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", 2168 child.getSbn().getId(), child.getSbn().getNotification(), 2169 child.getSbn().getUserId()); 2170 } 2171 // make the parent a child, which will cancel the child notification 2172 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2173 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", 2174 parentAsChild.getSbn().getId(), parentAsChild.getSbn().getNotification(), 2175 parentAsChild.getSbn().getUserId()); 2176 waitForIdle(); 2177 2178 assertEquals(0, mService.getNotificationRecordCount()); 2179 } 2180 2181 @Test testAutobundledSummary_notificationAdded()2182 public void testAutobundledSummary_notificationAdded() { 2183 NotificationRecord summary = 2184 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true); 2185 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY; 2186 mService.addNotification(summary); 2187 mService.mSummaryByGroupKey.put("pkg", summary); 2188 mService.mAutobundledSummaries.put(0, new ArrayMap<>()); 2189 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey()); 2190 2191 mService.updateAutobundledSummaryFlags( 2192 0, "pkg", GroupHelper.BASE_FLAGS | FLAG_ONGOING_EVENT, false); 2193 waitForIdle(); 2194 2195 assertTrue(summary.getSbn().isOngoing()); 2196 } 2197 2198 @Test testAutobundledSummary_notificationRemoved()2199 public void testAutobundledSummary_notificationRemoved() { 2200 NotificationRecord summary = 2201 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true); 2202 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY; 2203 summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 2204 mService.addNotification(summary); 2205 mService.mAutobundledSummaries.put(0, new ArrayMap<>()); 2206 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey()); 2207 mService.mSummaryByGroupKey.put("pkg", summary); 2208 2209 mService.updateAutobundledSummaryFlags(0, "pkg", GroupHelper.BASE_FLAGS, false); 2210 waitForIdle(); 2211 2212 assertFalse(summary.getSbn().isOngoing()); 2213 } 2214 2215 @Test testCancelAllNotifications_IgnoreForegroundService()2216 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception { 2217 when(mAmi.applyForegroundServiceNotification( 2218 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY); 2219 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2220 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2221 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2222 "testCancelAllNotifications_IgnoreForegroundService", 2223 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2224 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2225 waitForIdle(); 2226 StatusBarNotification[] notifs = 2227 mBinderService.getActiveNotifications(sbn.getPackageName()); 2228 assertEquals(1, notifs.length); 2229 assertEquals(1, mService.getNotificationRecordCount()); 2230 } 2231 2232 @Test testCancelAllNotifications_FgsFlag_NoFgs_Allowed()2233 public void testCancelAllNotifications_FgsFlag_NoFgs_Allowed() throws Exception { 2234 when(mAmi.applyForegroundServiceNotification( 2235 any(), anyString(), anyInt(), anyString(), anyInt())) 2236 .thenReturn(NOT_FOREGROUND_SERVICE); 2237 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2238 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2239 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2240 "testCancelAllNotifications_IgnoreForegroundService", 2241 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2242 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2243 waitForIdle(); 2244 StatusBarNotification[] notifs = 2245 mBinderService.getActiveNotifications(sbn.getPackageName()); 2246 assertEquals(0, notifs.length); 2247 } 2248 2249 @Test testCancelAllNotifications_IgnoreOtherPackages()2250 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception { 2251 when(mAmi.applyForegroundServiceNotification( 2252 any(), anyString(), anyInt(), anyString(), anyInt())) 2253 .thenReturn(SHOW_IMMEDIATELY); 2254 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2255 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2256 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2257 "testCancelAllNotifications_IgnoreOtherPackages", 2258 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2259 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId()); 2260 waitForIdle(); 2261 StatusBarNotification[] notifs = 2262 mBinderService.getActiveNotifications(sbn.getPackageName()); 2263 assertEquals(1, notifs.length); 2264 assertEquals(1, mService.getNotificationRecordCount()); 2265 } 2266 2267 @Test testCancelAllNotifications_NullPkgRemovesAll()2268 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception { 2269 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2270 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2271 "testCancelAllNotifications_NullPkgRemovesAll", 2272 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2273 mBinderService.cancelAllNotifications(null, sbn.getUserId()); 2274 waitForIdle(); 2275 StatusBarNotification[] notifs = 2276 mBinderService.getActiveNotifications(sbn.getPackageName()); 2277 assertEquals(0, notifs.length); 2278 assertEquals(0, mService.getNotificationRecordCount()); 2279 } 2280 2281 @Test testCancelAllNotifications_NullPkgIgnoresUserAllNotifications()2282 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception { 2283 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2284 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2285 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications", 2286 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL); 2287 // Null pkg is how we signal a user switch. 2288 mBinderService.cancelAllNotifications(null, sbn.getUserId()); 2289 waitForIdle(); 2290 StatusBarNotification[] notifs = 2291 mBinderService.getActiveNotifications(sbn.getPackageName()); 2292 assertEquals(1, notifs.length); 2293 assertEquals(1, mService.getNotificationRecordCount()); 2294 } 2295 2296 @Test testAppInitiatedCancelAllNotifications_CancelsNoClearFlag()2297 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception { 2298 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2299 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR; 2300 mBinderService.enqueueNotificationWithTag(PKG, PKG, 2301 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag", 2302 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2303 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 2304 waitForIdle(); 2305 StatusBarNotification[] notifs = 2306 mBinderService.getActiveNotifications(sbn.getPackageName()); 2307 assertEquals(0, notifs.length); 2308 } 2309 2310 @Test testCancelAllNotifications_CancelsNoClearFlag()2311 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception { 2312 final NotificationRecord notif = generateNotificationRecord( 2313 mTestNotificationChannel, 1, "group", true); 2314 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 2315 mService.addNotification(notif); 2316 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, 2317 notif.getUserId(), REASON_CANCEL); 2318 waitForIdle(); 2319 StatusBarNotification[] notifs = 2320 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 2321 assertEquals(0, notifs.length); 2322 } 2323 2324 @Test testUserInitiatedCancelAllOnClearAll_NoClearFlag()2325 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception { 2326 final NotificationRecord notif = generateNotificationRecord( 2327 mTestNotificationChannel, 1, "group", true); 2328 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 2329 mService.addNotification(notif); 2330 2331 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 2332 notif.getUserId()); 2333 waitForIdle(); 2334 StatusBarNotification[] notifs = 2335 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 2336 assertEquals(1, notifs.length); 2337 } 2338 2339 @Test testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue()2340 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception { 2341 when(mAmi.applyForegroundServiceNotification( 2342 any(), anyString(), anyInt(), anyString(), anyInt())) 2343 .thenReturn(SHOW_IMMEDIATELY); 2344 Notification n = 2345 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 2346 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2347 .build(); 2348 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0, 2349 n, UserHandle.getUserHandleForUid(mUid), null, 0); 2350 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2351 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 2352 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2353 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(), 2354 sbn.getUserId()); 2355 waitForIdle(); 2356 StatusBarNotification[] notifs = 2357 mBinderService.getActiveNotifications(sbn.getPackageName()); 2358 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE); 2359 } 2360 2361 @Test testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag()2362 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception { 2363 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 2364 sbn.getNotification().flags = 2365 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; 2366 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 2367 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2368 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT; 2369 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 2370 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 2371 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), 2372 sbn.getUserId()); 2373 waitForIdle(); 2374 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 2375 assertEquals(0, mService.getNotificationRecordCount()); 2376 } 2377 2378 @Test testCancelNotificationWithTag_fromApp_cannotCancelFgsChild()2379 public void testCancelNotificationWithTag_fromApp_cannotCancelFgsChild() 2380 throws Exception { 2381 when(mAmi.applyForegroundServiceNotification( 2382 any(), anyString(), anyInt(), anyString(), anyInt())) 2383 .thenReturn(SHOW_IMMEDIATELY); 2384 mService.isSystemUid = false; 2385 mService.isSystemAppId = false; 2386 final NotificationRecord parent = generateNotificationRecord( 2387 mTestNotificationChannel, 1, "group", true); 2388 final NotificationRecord child = generateNotificationRecord( 2389 mTestNotificationChannel, 2, "group", false); 2390 final NotificationRecord child2 = generateNotificationRecord( 2391 mTestNotificationChannel, 3, "group", false); 2392 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2393 mService.addNotification(parent); 2394 mService.addNotification(child); 2395 mService.addNotification(child2); 2396 mService.getBinderService().cancelNotificationWithTag( 2397 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 2398 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 2399 waitForIdle(); 2400 StatusBarNotification[] notifs = 2401 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2402 assertEquals(1, notifs.length); 2403 } 2404 2405 @Test testCancelNotificationWithTag_fromApp_cannotCancelFgsParent()2406 public void testCancelNotificationWithTag_fromApp_cannotCancelFgsParent() 2407 throws Exception { 2408 when(mAmi.applyForegroundServiceNotification( 2409 any(), anyString(), anyInt(), anyString(), anyInt())) 2410 .thenReturn(SHOW_IMMEDIATELY); 2411 mService.isSystemUid = false; 2412 mService.isSystemAppId = false; 2413 final NotificationRecord parent = generateNotificationRecord( 2414 mTestNotificationChannel, 1, "group", true); 2415 parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2416 final NotificationRecord child = generateNotificationRecord( 2417 mTestNotificationChannel, 2, "group", false); 2418 final NotificationRecord child2 = generateNotificationRecord( 2419 mTestNotificationChannel, 3, "group", false); 2420 mService.addNotification(parent); 2421 mService.addNotification(child); 2422 mService.addNotification(child2); 2423 mService.getBinderService().cancelNotificationWithTag( 2424 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 2425 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 2426 waitForIdle(); 2427 StatusBarNotification[] notifs = 2428 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2429 assertEquals(3, notifs.length); 2430 } 2431 2432 @Test testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearChild()2433 public void testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearChild() 2434 throws Exception { 2435 mService.isSystemUid = false; 2436 mService.isSystemAppId = false; 2437 final NotificationRecord parent = generateNotificationRecord( 2438 mTestNotificationChannel, 1, "group", true); 2439 final NotificationRecord child = generateNotificationRecord( 2440 mTestNotificationChannel, 2, "group", false); 2441 final NotificationRecord child2 = generateNotificationRecord( 2442 mTestNotificationChannel, 3, "group", false); 2443 child2.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR; 2444 mService.addNotification(parent); 2445 mService.addNotification(child); 2446 mService.addNotification(child2); 2447 mService.getBinderService().cancelNotificationWithTag( 2448 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 2449 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 2450 waitForIdle(); 2451 StatusBarNotification[] notifs = 2452 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2453 assertEquals(0, notifs.length); 2454 } 2455 2456 @Test testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearParent()2457 public void testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearParent() 2458 throws Exception { 2459 mService.isSystemUid = false; 2460 mService.isSystemAppId = false; 2461 final NotificationRecord parent = generateNotificationRecord( 2462 mTestNotificationChannel, 1, "group", true); 2463 parent.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR; 2464 final NotificationRecord child = generateNotificationRecord( 2465 mTestNotificationChannel, 2, "group", false); 2466 final NotificationRecord child2 = generateNotificationRecord( 2467 mTestNotificationChannel, 3, "group", false); 2468 mService.addNotification(parent); 2469 mService.addNotification(child); 2470 mService.addNotification(child2); 2471 mService.getBinderService().cancelNotificationWithTag( 2472 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 2473 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 2474 waitForIdle(); 2475 StatusBarNotification[] notifs = 2476 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2477 assertEquals(0, notifs.length); 2478 } 2479 2480 @Test testCancelAllNotificationsFromApp_cannotCancelFgsChild()2481 public void testCancelAllNotificationsFromApp_cannotCancelFgsChild() 2482 throws Exception { 2483 when(mAmi.applyForegroundServiceNotification( 2484 any(), anyString(), anyInt(), anyString(), anyInt())) 2485 .thenReturn(SHOW_IMMEDIATELY); 2486 mService.isSystemUid = false; 2487 mService.isSystemAppId = false; 2488 final NotificationRecord parent = generateNotificationRecord( 2489 mTestNotificationChannel, 1, "group", true); 2490 final NotificationRecord child = generateNotificationRecord( 2491 mTestNotificationChannel, 2, "group", false); 2492 final NotificationRecord child2 = generateNotificationRecord( 2493 mTestNotificationChannel, 3, "group", false); 2494 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2495 final NotificationRecord newGroup = generateNotificationRecord( 2496 mTestNotificationChannel, 4, "group2", false); 2497 mService.addNotification(parent); 2498 mService.addNotification(child); 2499 mService.addNotification(child2); 2500 mService.addNotification(newGroup); 2501 mService.getBinderService().cancelAllNotifications( 2502 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 2503 waitForIdle(); 2504 StatusBarNotification[] notifs = 2505 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2506 assertEquals(1, notifs.length); 2507 } 2508 2509 @Test testCancelAllNotifications_fromApp_cannotCancelFgsParent()2510 public void testCancelAllNotifications_fromApp_cannotCancelFgsParent() 2511 throws Exception { 2512 when(mAmi.applyForegroundServiceNotification( 2513 any(), anyString(), anyInt(), anyString(), anyInt())) 2514 .thenReturn(SHOW_IMMEDIATELY); 2515 mService.isSystemUid = false; 2516 mService.isSystemAppId = false; 2517 final NotificationRecord parent = generateNotificationRecord( 2518 mTestNotificationChannel, 1, "group", true); 2519 parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2520 final NotificationRecord child = generateNotificationRecord( 2521 mTestNotificationChannel, 2, "group", false); 2522 final NotificationRecord child2 = generateNotificationRecord( 2523 mTestNotificationChannel, 3, "group", false); 2524 final NotificationRecord newGroup = generateNotificationRecord( 2525 mTestNotificationChannel, 4, "group2", false); 2526 mService.addNotification(parent); 2527 mService.addNotification(child); 2528 mService.addNotification(child2); 2529 mService.addNotification(newGroup); 2530 mService.getBinderService().cancelAllNotifications( 2531 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 2532 waitForIdle(); 2533 StatusBarNotification[] notifs = 2534 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2535 assertEquals(1, notifs.length); 2536 } 2537 2538 @Test testCancelAllNotifications_fromApp_canCancelOngoingNoClearChild()2539 public void testCancelAllNotifications_fromApp_canCancelOngoingNoClearChild() 2540 throws Exception { 2541 mService.isSystemUid = false; 2542 mService.isSystemAppId = false; 2543 final NotificationRecord parent = generateNotificationRecord( 2544 mTestNotificationChannel, 1, "group", true); 2545 final NotificationRecord child = generateNotificationRecord( 2546 mTestNotificationChannel, 2, "group", false); 2547 final NotificationRecord child2 = generateNotificationRecord( 2548 mTestNotificationChannel, 3, "group", false); 2549 child2.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR; 2550 final NotificationRecord newGroup = generateNotificationRecord( 2551 mTestNotificationChannel, 4, "group2", false); 2552 mService.addNotification(parent); 2553 mService.addNotification(child); 2554 mService.addNotification(child2); 2555 mService.addNotification(newGroup); 2556 mService.getBinderService().cancelAllNotifications( 2557 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 2558 waitForIdle(); 2559 StatusBarNotification[] notifs = 2560 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2561 assertEquals(0, notifs.length); 2562 } 2563 2564 @Test testCancelAllNotifications_fromApp_canCancelOngoingNoClearParent()2565 public void testCancelAllNotifications_fromApp_canCancelOngoingNoClearParent() 2566 throws Exception { 2567 mService.isSystemUid = false; 2568 mService.isSystemAppId = false; 2569 final NotificationRecord parent = generateNotificationRecord( 2570 mTestNotificationChannel, 1, "group", true); 2571 parent.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR; 2572 final NotificationRecord child = generateNotificationRecord( 2573 mTestNotificationChannel, 2, "group", false); 2574 final NotificationRecord child2 = generateNotificationRecord( 2575 mTestNotificationChannel, 3, "group", false); 2576 final NotificationRecord newGroup = generateNotificationRecord( 2577 mTestNotificationChannel, 4, "group2", false); 2578 mService.addNotification(parent); 2579 mService.addNotification(child); 2580 mService.addNotification(child2); 2581 mService.addNotification(newGroup); 2582 mService.getBinderService().cancelAllNotifications( 2583 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 2584 waitForIdle(); 2585 StatusBarNotification[] notifs = 2586 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2587 assertEquals(0, notifs.length); 2588 } 2589 2590 @Test testCancelNotificationsFromListener_clearAll_GroupWithOngoingParent()2591 public void testCancelNotificationsFromListener_clearAll_GroupWithOngoingParent() 2592 throws Exception { 2593 final NotificationRecord parent = generateNotificationRecord( 2594 mTestNotificationChannel, 1, "group", true); 2595 parent.getNotification().flags |= FLAG_ONGOING_EVENT; 2596 final NotificationRecord child = generateNotificationRecord( 2597 mTestNotificationChannel, 2, "group", false); 2598 final NotificationRecord child2 = generateNotificationRecord( 2599 mTestNotificationChannel, 3, "group", false); 2600 final NotificationRecord newGroup = generateNotificationRecord( 2601 mTestNotificationChannel, 4, "group2", false); 2602 mService.addNotification(parent); 2603 mService.addNotification(child); 2604 mService.addNotification(child2); 2605 mService.addNotification(newGroup); 2606 mService.getBinderService().cancelNotificationsFromListener(null, null); 2607 waitForIdle(); 2608 StatusBarNotification[] notifs = 2609 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2610 assertEquals(1, notifs.length); 2611 } 2612 2613 @Test testCancelNotificationsFromListener_clearAll_GroupWithOngoingChild()2614 public void testCancelNotificationsFromListener_clearAll_GroupWithOngoingChild() 2615 throws Exception { 2616 final NotificationRecord parent = generateNotificationRecord( 2617 mTestNotificationChannel, 1, "group", true); 2618 final NotificationRecord child = generateNotificationRecord( 2619 mTestNotificationChannel, 2, "group", false); 2620 final NotificationRecord child2 = generateNotificationRecord( 2621 mTestNotificationChannel, 3, "group", false); 2622 child2.getNotification().flags |= FLAG_ONGOING_EVENT; 2623 final NotificationRecord newGroup = generateNotificationRecord( 2624 mTestNotificationChannel, 4, "group2", false); 2625 mService.addNotification(parent); 2626 mService.addNotification(child); 2627 mService.addNotification(child2); 2628 mService.addNotification(newGroup); 2629 mService.getBinderService().cancelNotificationsFromListener(null, null); 2630 waitForIdle(); 2631 StatusBarNotification[] notifs = 2632 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2633 assertEquals(1, notifs.length); 2634 } 2635 2636 @Test testCancelNotificationsFromListener_clearAll_GroupWithFgsParent()2637 public void testCancelNotificationsFromListener_clearAll_GroupWithFgsParent() 2638 throws Exception { 2639 when(mAmi.applyForegroundServiceNotification( 2640 any(), anyString(), anyInt(), anyString(), anyInt())) 2641 .thenReturn(SHOW_IMMEDIATELY); 2642 final NotificationRecord parent = generateNotificationRecord( 2643 mTestNotificationChannel, 1, "group", true); 2644 parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2645 final NotificationRecord child = generateNotificationRecord( 2646 mTestNotificationChannel, 2, "group", false); 2647 final NotificationRecord child2 = generateNotificationRecord( 2648 mTestNotificationChannel, 3, "group", false); 2649 final NotificationRecord newGroup = generateNotificationRecord( 2650 mTestNotificationChannel, 4, "group2", false); 2651 mService.addNotification(parent); 2652 mService.addNotification(child); 2653 mService.addNotification(child2); 2654 mService.addNotification(newGroup); 2655 mService.getBinderService().cancelNotificationsFromListener(null, null); 2656 waitForIdle(); 2657 StatusBarNotification[] notifs = 2658 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2659 assertEquals(0, notifs.length); 2660 } 2661 2662 @Test testCancelNotificationsFromListener_clearAll_GroupWithFgsChild()2663 public void testCancelNotificationsFromListener_clearAll_GroupWithFgsChild() 2664 throws Exception { 2665 when(mAmi.applyForegroundServiceNotification( 2666 any(), anyString(), anyInt(), anyString(), anyInt())) 2667 .thenReturn(SHOW_IMMEDIATELY); 2668 final NotificationRecord parent = generateNotificationRecord( 2669 mTestNotificationChannel, 1, "group", true); 2670 final NotificationRecord child = generateNotificationRecord( 2671 mTestNotificationChannel, 2, "group", false); 2672 final NotificationRecord child2 = generateNotificationRecord( 2673 mTestNotificationChannel, 3, "group", false); 2674 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2675 final NotificationRecord newGroup = generateNotificationRecord( 2676 mTestNotificationChannel, 4, "group2", false); 2677 mService.addNotification(parent); 2678 mService.addNotification(child); 2679 mService.addNotification(child2); 2680 mService.addNotification(newGroup); 2681 mService.getBinderService().cancelNotificationsFromListener(null, null); 2682 waitForIdle(); 2683 StatusBarNotification[] notifs = 2684 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2685 assertEquals(0, notifs.length); 2686 } 2687 2688 @Test testCancelNotificationsFromListener_clearAll_GroupWithNoClearParent()2689 public void testCancelNotificationsFromListener_clearAll_GroupWithNoClearParent() 2690 throws Exception { 2691 final NotificationRecord parent = generateNotificationRecord( 2692 mTestNotificationChannel, 1, "group", true); 2693 parent.getNotification().flags |= FLAG_NO_CLEAR; 2694 final NotificationRecord child = generateNotificationRecord( 2695 mTestNotificationChannel, 2, "group", false); 2696 final NotificationRecord child2 = generateNotificationRecord( 2697 mTestNotificationChannel, 3, "group", false); 2698 final NotificationRecord newGroup = generateNotificationRecord( 2699 mTestNotificationChannel, 4, "group2", false); 2700 mService.addNotification(parent); 2701 mService.addNotification(child); 2702 mService.addNotification(child2); 2703 mService.addNotification(newGroup); 2704 mService.getBinderService().cancelNotificationsFromListener(null, null); 2705 waitForIdle(); 2706 StatusBarNotification[] notifs = 2707 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2708 assertEquals(1, notifs.length); 2709 } 2710 2711 @Test testCancelNotificationsFromListener_clearAll_GroupWithNoClearChild()2712 public void testCancelNotificationsFromListener_clearAll_GroupWithNoClearChild() 2713 throws Exception { 2714 final NotificationRecord parent = generateNotificationRecord( 2715 mTestNotificationChannel, 1, "group", true); 2716 final NotificationRecord child = generateNotificationRecord( 2717 mTestNotificationChannel, 2, "group", false); 2718 final NotificationRecord child2 = generateNotificationRecord( 2719 mTestNotificationChannel, 3, "group", false); 2720 child2.getNotification().flags |= FLAG_NO_CLEAR; 2721 final NotificationRecord newGroup = generateNotificationRecord( 2722 mTestNotificationChannel, 4, "group2", false); 2723 mService.addNotification(parent); 2724 mService.addNotification(child); 2725 mService.addNotification(child2); 2726 mService.addNotification(newGroup); 2727 mService.getBinderService().cancelNotificationsFromListener(null, null); 2728 waitForIdle(); 2729 StatusBarNotification[] notifs = 2730 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2731 assertEquals(1, notifs.length); 2732 } 2733 2734 @Test testCancelNotificationsFromListener_clearAll_Ongoing()2735 public void testCancelNotificationsFromListener_clearAll_Ongoing() 2736 throws Exception { 2737 final NotificationRecord child2 = generateNotificationRecord( 2738 mTestNotificationChannel, 3, null, false); 2739 child2.getNotification().flags |= FLAG_ONGOING_EVENT; 2740 mService.addNotification(child2); 2741 String[] keys = {child2.getSbn().getKey()}; 2742 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2743 waitForIdle(); 2744 StatusBarNotification[] notifs = 2745 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2746 assertEquals(1, notifs.length); 2747 } 2748 2749 @Test testCancelNotificationsFromListener_clearAll_NoClear()2750 public void testCancelNotificationsFromListener_clearAll_NoClear() 2751 throws Exception { 2752 final NotificationRecord child2 = generateNotificationRecord( 2753 mTestNotificationChannel, 3, null, false); 2754 child2.getNotification().flags |= FLAG_NO_CLEAR; 2755 mService.addNotification(child2); 2756 mService.getBinderService().cancelNotificationsFromListener(null, null); 2757 waitForIdle(); 2758 StatusBarNotification[] notifs = 2759 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2760 assertEquals(1, notifs.length); 2761 } 2762 2763 @Test testCancelNotificationsFromListener_clearAll_Fgs()2764 public void testCancelNotificationsFromListener_clearAll_Fgs() 2765 throws Exception { 2766 when(mAmi.applyForegroundServiceNotification( 2767 any(), anyString(), anyInt(), anyString(), anyInt())) 2768 .thenReturn(SHOW_IMMEDIATELY); 2769 final NotificationRecord child2 = generateNotificationRecord( 2770 mTestNotificationChannel, 3, null, false); 2771 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2772 mService.addNotification(child2); 2773 mService.getBinderService().cancelNotificationsFromListener(null, null); 2774 waitForIdle(); 2775 StatusBarNotification[] notifs = 2776 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2777 assertEquals(0, notifs.length); 2778 } 2779 2780 @Test testCancelNotificationsFromListener_byKey_GroupWithOngoingParent()2781 public void testCancelNotificationsFromListener_byKey_GroupWithOngoingParent() 2782 throws Exception { 2783 final NotificationRecord parent = generateNotificationRecord( 2784 mTestNotificationChannel, 1, "group", true); 2785 parent.getNotification().flags |= FLAG_ONGOING_EVENT; 2786 final NotificationRecord child = generateNotificationRecord( 2787 mTestNotificationChannel, 2, "group", false); 2788 final NotificationRecord child2 = generateNotificationRecord( 2789 mTestNotificationChannel, 3, "group", false); 2790 final NotificationRecord newGroup = generateNotificationRecord( 2791 mTestNotificationChannel, 4, "group2", false); 2792 mService.addNotification(parent); 2793 mService.addNotification(child); 2794 mService.addNotification(child2); 2795 mService.addNotification(newGroup); 2796 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2797 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2798 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2799 waitForIdle(); 2800 StatusBarNotification[] notifs = 2801 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2802 assertEquals(1, notifs.length); 2803 } 2804 2805 @Test testCancelNotificationsFromListener_byKey_GroupWithOngoingChild()2806 public void testCancelNotificationsFromListener_byKey_GroupWithOngoingChild() 2807 throws Exception { 2808 final NotificationRecord parent = generateNotificationRecord( 2809 mTestNotificationChannel, 1, "group", true); 2810 final NotificationRecord child = generateNotificationRecord( 2811 mTestNotificationChannel, 2, "group", false); 2812 final NotificationRecord child2 = generateNotificationRecord( 2813 mTestNotificationChannel, 3, "group", false); 2814 child2.getNotification().flags |= FLAG_ONGOING_EVENT; 2815 final NotificationRecord newGroup = generateNotificationRecord( 2816 mTestNotificationChannel, 4, "group2", false); 2817 mService.addNotification(parent); 2818 mService.addNotification(child); 2819 mService.addNotification(child2); 2820 mService.addNotification(newGroup); 2821 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2822 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2823 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2824 waitForIdle(); 2825 StatusBarNotification[] notifs = 2826 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2827 assertEquals(1, notifs.length); 2828 } 2829 2830 @Test testCancelNotificationsFromListener_byKey_GroupWithFgsParent()2831 public void testCancelNotificationsFromListener_byKey_GroupWithFgsParent() 2832 throws Exception { 2833 when(mAmi.applyForegroundServiceNotification( 2834 any(), anyString(), anyInt(), anyString(), anyInt())) 2835 .thenReturn(SHOW_IMMEDIATELY); 2836 final NotificationRecord parent = generateNotificationRecord( 2837 mTestNotificationChannel, 1, "group", true); 2838 parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2839 final NotificationRecord child = generateNotificationRecord( 2840 mTestNotificationChannel, 2, "group", false); 2841 final NotificationRecord child2 = generateNotificationRecord( 2842 mTestNotificationChannel, 3, "group", false); 2843 final NotificationRecord newGroup = generateNotificationRecord( 2844 mTestNotificationChannel, 4, "group2", false); 2845 mService.addNotification(parent); 2846 mService.addNotification(child); 2847 mService.addNotification(child2); 2848 mService.addNotification(newGroup); 2849 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2850 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2851 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2852 waitForIdle(); 2853 StatusBarNotification[] notifs = 2854 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2855 assertEquals(0, notifs.length); 2856 } 2857 2858 @Test testCancelNotificationsFromListener_byKey_GroupWithFgsChild()2859 public void testCancelNotificationsFromListener_byKey_GroupWithFgsChild() 2860 throws Exception { 2861 when(mAmi.applyForegroundServiceNotification( 2862 any(), anyString(), anyInt(), anyString(), anyInt())) 2863 .thenReturn(SHOW_IMMEDIATELY); 2864 final NotificationRecord parent = generateNotificationRecord( 2865 mTestNotificationChannel, 1, "group", true); 2866 final NotificationRecord child = generateNotificationRecord( 2867 mTestNotificationChannel, 2, "group", false); 2868 final NotificationRecord child2 = generateNotificationRecord( 2869 mTestNotificationChannel, 3, "group", false); 2870 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2871 final NotificationRecord newGroup = generateNotificationRecord( 2872 mTestNotificationChannel, 4, "group2", false); 2873 mService.addNotification(parent); 2874 mService.addNotification(child); 2875 mService.addNotification(child2); 2876 mService.addNotification(newGroup); 2877 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2878 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2879 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2880 waitForIdle(); 2881 StatusBarNotification[] notifs = 2882 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2883 assertEquals(0, notifs.length); 2884 } 2885 2886 @Test testCancelNotificationsFromListener_byKey_GroupWithNoClearParent()2887 public void testCancelNotificationsFromListener_byKey_GroupWithNoClearParent() 2888 throws Exception { 2889 final NotificationRecord parent = generateNotificationRecord( 2890 mTestNotificationChannel, 1, "group", true); 2891 parent.getNotification().flags |= FLAG_NO_CLEAR; 2892 final NotificationRecord child = generateNotificationRecord( 2893 mTestNotificationChannel, 2, "group", false); 2894 final NotificationRecord child2 = generateNotificationRecord( 2895 mTestNotificationChannel, 3, "group", false); 2896 final NotificationRecord newGroup = generateNotificationRecord( 2897 mTestNotificationChannel, 4, "group2", false); 2898 mService.addNotification(parent); 2899 mService.addNotification(child); 2900 mService.addNotification(child2); 2901 mService.addNotification(newGroup); 2902 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2903 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2904 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2905 waitForIdle(); 2906 StatusBarNotification[] notifs = 2907 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2908 assertEquals(0, notifs.length); 2909 } 2910 2911 @Test testCancelNotificationsFromListener_byKey_GroupWithNoClearChild()2912 public void testCancelNotificationsFromListener_byKey_GroupWithNoClearChild() 2913 throws Exception { 2914 final NotificationRecord parent = generateNotificationRecord( 2915 mTestNotificationChannel, 1, "group", true); 2916 final NotificationRecord child = generateNotificationRecord( 2917 mTestNotificationChannel, 2, "group", false); 2918 final NotificationRecord child2 = generateNotificationRecord( 2919 mTestNotificationChannel, 3, "group", false); 2920 child2.getNotification().flags |= FLAG_NO_CLEAR; 2921 final NotificationRecord newGroup = generateNotificationRecord( 2922 mTestNotificationChannel, 4, "group2", false); 2923 mService.addNotification(parent); 2924 mService.addNotification(child); 2925 mService.addNotification(child2); 2926 mService.addNotification(newGroup); 2927 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 2928 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 2929 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2930 waitForIdle(); 2931 StatusBarNotification[] notifs = 2932 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 2933 assertEquals(0, notifs.length); 2934 } 2935 2936 @Test testCancelNotificationsFromListener_byKey_Ongoing()2937 public void testCancelNotificationsFromListener_byKey_Ongoing() 2938 throws Exception { 2939 final NotificationRecord child2 = generateNotificationRecord( 2940 mTestNotificationChannel, 3, null, false); 2941 child2.getNotification().flags |= FLAG_ONGOING_EVENT; 2942 mService.addNotification(child2); 2943 String[] keys = {child2.getSbn().getKey()}; 2944 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2945 waitForIdle(); 2946 StatusBarNotification[] notifs = 2947 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2948 assertEquals(1, notifs.length); 2949 } 2950 2951 @Test testCancelNotificationsFromListener_byKey_NoClear()2952 public void testCancelNotificationsFromListener_byKey_NoClear() 2953 throws Exception { 2954 final NotificationRecord child2 = generateNotificationRecord( 2955 mTestNotificationChannel, 3, null, false); 2956 child2.getNotification().flags |= FLAG_NO_CLEAR; 2957 mService.addNotification(child2); 2958 String[] keys = {child2.getSbn().getKey()}; 2959 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2960 waitForIdle(); 2961 StatusBarNotification[] notifs = 2962 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2963 assertEquals(0, notifs.length); 2964 } 2965 2966 @Test testCancelNotificationsFromListener_byKey_Fgs()2967 public void testCancelNotificationsFromListener_byKey_Fgs() 2968 throws Exception { 2969 when(mAmi.applyForegroundServiceNotification( 2970 any(), anyString(), anyInt(), anyString(), anyInt())) 2971 .thenReturn(SHOW_IMMEDIATELY); 2972 final NotificationRecord child2 = generateNotificationRecord( 2973 mTestNotificationChannel, 3, null, false); 2974 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 2975 mService.addNotification(child2); 2976 String[] keys = {child2.getSbn().getKey()}; 2977 mService.getBinderService().cancelNotificationsFromListener(null, keys); 2978 waitForIdle(); 2979 StatusBarNotification[] notifs = 2980 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 2981 assertEquals(0, notifs.length); 2982 } 2983 2984 @Test testGroupInstanceIds()2985 public void testGroupInstanceIds() throws Exception { 2986 final NotificationRecord group1 = generateNotificationRecord( 2987 mTestNotificationChannel, 1, "group1", true); 2988 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testGroupInstanceIds", 2989 group1.getSbn().getId(), group1.getSbn().getNotification(), 2990 group1.getSbn().getUserId()); 2991 waitForIdle(); 2992 2993 // same group, child, should be returned 2994 final NotificationRecord group1Child = generateNotificationRecord( 2995 mTestNotificationChannel, 2, "group1", false); 2996 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testGroupInstanceIds", 2997 group1Child.getSbn().getId(), 2998 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId()); 2999 waitForIdle(); 3000 3001 assertEquals(2, mNotificationRecordLogger.numCalls()); 3002 assertEquals(mNotificationRecordLogger.get(0).getInstanceId(), 3003 mNotificationRecordLogger.get(1).groupInstanceId.getId()); 3004 } 3005 3006 @Test testFindGroupNotificationsLocked()3007 public void testFindGroupNotificationsLocked() throws Exception { 3008 // make sure the same notification can be found in both lists and returned 3009 final NotificationRecord group1 = generateNotificationRecord( 3010 mTestNotificationChannel, 1, "group1", true); 3011 mService.addEnqueuedNotification(group1); 3012 mService.addNotification(group1); 3013 3014 // should not be returned 3015 final NotificationRecord group2 = generateNotificationRecord( 3016 mTestNotificationChannel, 2, "group2", true); 3017 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 3018 group2.getSbn().getId(), group2.getSbn().getNotification(), 3019 group2.getSbn().getUserId()); 3020 waitForIdle(); 3021 3022 // should not be returned 3023 final NotificationRecord nonGroup = generateNotificationRecord( 3024 mTestNotificationChannel, 3, null, false); 3025 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 3026 nonGroup.getSbn().getId(), nonGroup.getSbn().getNotification(), 3027 nonGroup.getSbn().getUserId()); 3028 waitForIdle(); 3029 3030 // same group, child, should be returned 3031 final NotificationRecord group1Child = generateNotificationRecord( 3032 mTestNotificationChannel, 4, "group1", false); 3033 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", 3034 group1Child.getSbn().getId(), 3035 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId()); 3036 waitForIdle(); 3037 3038 List<NotificationRecord> inGroup1 = 3039 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(), 3040 group1.getSbn().getUserId()); 3041 assertEquals(3, inGroup1.size()); 3042 for (NotificationRecord record : inGroup1) { 3043 assertTrue(record.getGroupKey().equals(group1.getGroupKey())); 3044 assertTrue(record.getSbn().getId() == 1 || record.getSbn().getId() == 4); 3045 } 3046 } 3047 3048 @Test testCancelAllNotificationsInt_CancelsNoClearFlagOnGoing()3049 public void testCancelAllNotificationsInt_CancelsNoClearFlagOnGoing() throws Exception { 3050 final NotificationRecord notif = generateNotificationRecord( 3051 mTestNotificationChannel, 1, "group", true); 3052 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; 3053 mService.addNotification(notif); 3054 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 3055 Notification.FLAG_ONGOING_EVENT, notif.getUserId(), REASON_CANCEL); 3056 waitForIdle(); 3057 StatusBarNotification[] notifs = 3058 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 3059 assertEquals(0, notifs.length); 3060 } 3061 3062 @Test testAppInitiatedCancelAllNotifications_CancelsOngoingFlag()3063 public void testAppInitiatedCancelAllNotifications_CancelsOngoingFlag() throws Exception { 3064 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 3065 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 3066 mBinderService.enqueueNotificationWithTag(PKG, PKG, 3067 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag", 3068 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 3069 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 3070 waitForIdle(); 3071 StatusBarNotification[] notifs = 3072 mBinderService.getActiveNotifications(sbn.getPackageName()); 3073 assertEquals(0, notifs.length); 3074 } 3075 3076 @Test testCancelAllNotificationsInt_CancelsOngoingFlag()3077 public void testCancelAllNotificationsInt_CancelsOngoingFlag() throws Exception { 3078 final NotificationRecord notif = generateNotificationRecord( 3079 mTestNotificationChannel, 1, "group", true); 3080 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 3081 mService.addNotification(notif); 3082 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, 3083 notif.getUserId(), REASON_CANCEL); 3084 waitForIdle(); 3085 StatusBarNotification[] notifs = 3086 mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); 3087 assertEquals(0, notifs.length); 3088 } 3089 3090 @Test testUserInitiatedCancelAllWithGroup_OngoingFlag()3091 public void testUserInitiatedCancelAllWithGroup_OngoingFlag() throws Exception { 3092 final NotificationRecord parent = generateNotificationRecord( 3093 mTestNotificationChannel, 1, "group", true); 3094 final NotificationRecord child = generateNotificationRecord( 3095 mTestNotificationChannel, 2, "group", false); 3096 final NotificationRecord child2 = generateNotificationRecord( 3097 mTestNotificationChannel, 3, "group", false); 3098 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; 3099 final NotificationRecord newGroup = generateNotificationRecord( 3100 mTestNotificationChannel, 4, "group2", false); 3101 mService.addNotification(parent); 3102 mService.addNotification(child); 3103 mService.addNotification(child2); 3104 mService.addNotification(newGroup); 3105 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 3106 parent.getUserId()); 3107 waitForIdle(); 3108 StatusBarNotification[] notifs = 3109 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 3110 assertEquals(1, notifs.length); 3111 } 3112 3113 @Test testUserInitiatedCancelAllWithGroup_NoClearFlag()3114 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception { 3115 final NotificationRecord parent = generateNotificationRecord( 3116 mTestNotificationChannel, 1, "group", true); 3117 final NotificationRecord child = generateNotificationRecord( 3118 mTestNotificationChannel, 2, "group", false); 3119 final NotificationRecord child2 = generateNotificationRecord( 3120 mTestNotificationChannel, 3, "group", false); 3121 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; 3122 final NotificationRecord newGroup = generateNotificationRecord( 3123 mTestNotificationChannel, 4, "group2", false); 3124 mService.addNotification(parent); 3125 mService.addNotification(child); 3126 mService.addNotification(child2); 3127 mService.addNotification(newGroup); 3128 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 3129 parent.getUserId()); 3130 waitForIdle(); 3131 StatusBarNotification[] notifs = 3132 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 3133 assertEquals(1, notifs.length); 3134 } 3135 3136 @Test testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag()3137 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception { 3138 when(mAmi.applyForegroundServiceNotification( 3139 any(), anyString(), anyInt(), anyString(), anyInt())) 3140 .thenReturn(SHOW_IMMEDIATELY); 3141 final NotificationRecord parent = generateNotificationRecord( 3142 mTestNotificationChannel, 1, "group", true); 3143 final NotificationRecord child = generateNotificationRecord( 3144 mTestNotificationChannel, 2, "group", false); 3145 final NotificationRecord child2 = generateNotificationRecord( 3146 mTestNotificationChannel, 3, "group", false); 3147 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 3148 final NotificationRecord newGroup = generateNotificationRecord( 3149 mTestNotificationChannel, 4, "group2", false); 3150 mService.addNotification(parent); 3151 mService.addNotification(child); 3152 mService.addNotification(child2); 3153 mService.addNotification(newGroup); 3154 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 3155 parent.getUserId()); 3156 waitForIdle(); 3157 StatusBarNotification[] notifs = 3158 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 3159 assertEquals(0, notifs.length); 3160 } 3161 3162 @Test testDefaultChannelUpdatesApp_postMigrationToPermissions()3163 public void testDefaultChannelUpdatesApp_postMigrationToPermissions() throws Exception { 3164 final NotificationChannel defaultChannel = mBinderService.getNotificationChannel( 3165 PKG_N_MR1, ActivityManager.getCurrentUser(), PKG_N_MR1, 3166 NotificationChannel.DEFAULT_CHANNEL_ID); 3167 defaultChannel.setImportance(IMPORTANCE_NONE); 3168 3169 mBinderService.updateNotificationChannelForPackage(PKG_N_MR1, mUid, defaultChannel); 3170 3171 verify(mPermissionHelper).setNotificationPermission( 3172 PKG_N_MR1, ActivityManager.getCurrentUser(), false, true); 3173 } 3174 3175 @Test testPostNotification_appPermissionFixed()3176 public void testPostNotification_appPermissionFixed() throws Exception { 3177 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 3178 when(mPermissionHelper.isPermissionFixed(PKG, 0)).thenReturn(true); 3179 3180 NotificationRecord temp = generateNotificationRecord(mTestNotificationChannel); 3181 mBinderService.enqueueNotificationWithTag(PKG, PKG, 3182 "testPostNotification_appPermissionFixed", 0, 3183 temp.getNotification(), 0); 3184 waitForIdle(); 3185 assertThat(mService.getNotificationRecordCount()).isEqualTo(1); 3186 StatusBarNotification[] notifs = 3187 mBinderService.getActiveNotifications(PKG); 3188 assertThat(mService.getNotificationRecord(notifs[0].getKey()).isImportanceFixed()).isTrue(); 3189 } 3190 3191 @Test testSummaryNotification_appPermissionFixed()3192 public void testSummaryNotification_appPermissionFixed() { 3193 NotificationRecord temp = generateNotificationRecord(mTestNotificationChannel); 3194 mService.addNotification(temp); 3195 3196 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 3197 when(mPermissionHelper.isPermissionFixed(PKG, temp.getUserId())).thenReturn(true); 3198 3199 NotificationRecord r = mService.createAutoGroupSummary( 3200 temp.getUserId(), temp.getSbn().getPackageName(), temp.getKey(), 0); 3201 3202 assertThat(r.isImportanceFixed()).isTrue(); 3203 } 3204 3205 @Test testTvExtenderChannelOverride_onTv()3206 public void testTvExtenderChannelOverride_onTv() throws Exception { 3207 mService.setIsTelevision(true); 3208 mService.setPreferencesHelper(mPreferencesHelper); 3209 when(mPreferencesHelper.getNotificationChannel( 3210 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn( 3211 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH)); 3212 3213 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); 3214 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0, 3215 generateNotificationRecord(null, tv).getNotification(), 0); 3216 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel( 3217 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean()); 3218 } 3219 3220 @Test testTvExtenderChannelOverride_notOnTv()3221 public void testTvExtenderChannelOverride_notOnTv() throws Exception { 3222 mService.setIsTelevision(false); 3223 mService.setPreferencesHelper(mPreferencesHelper); 3224 when(mPreferencesHelper.getNotificationChannel( 3225 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn( 3226 mTestNotificationChannel); 3227 3228 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); 3229 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv", 3230 0, generateNotificationRecord(null, tv).getNotification(), 0); 3231 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel( 3232 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null), 3233 anyBoolean(), anyBoolean()); 3234 } 3235 3236 @Test onOpChanged_permissionRevoked_cancelsAllNotificationsFromPackage()3237 public void onOpChanged_permissionRevoked_cancelsAllNotificationsFromPackage() 3238 throws RemoteException { 3239 // Have preexisting posted notifications from revoked package and other packages. 3240 mService.addNotification(new NotificationRecord(mContext, 3241 generateSbn("revoked", 1001, 1, 0), mTestNotificationChannel)); 3242 mService.addNotification(new NotificationRecord(mContext, 3243 generateSbn("other", 1002, 2, 0), mTestNotificationChannel)); 3244 // Have preexisting enqueued notifications from revoked package and other packages. 3245 mService.addEnqueuedNotification(new NotificationRecord(mContext, 3246 generateSbn("revoked", 1001, 3, 0), mTestNotificationChannel)); 3247 mService.addEnqueuedNotification(new NotificationRecord(mContext, 3248 generateSbn("other", 1002, 4, 0), mTestNotificationChannel)); 3249 assertThat(mService.mNotificationList).hasSize(2); 3250 assertThat(mService.mEnqueuedNotifications).hasSize(2); 3251 3252 when(mPackageManagerInternal.getPackageUid("revoked", 0, 0)).thenReturn(1001); 3253 when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(false); 3254 3255 mOnPermissionChangeListener.onOpChanged( 3256 AppOpsManager.OPSTR_POST_NOTIFICATION, "revoked", 0); 3257 waitForIdle(); 3258 3259 assertThat(mService.mNotificationList).hasSize(1); 3260 assertThat(mService.mNotificationList.get(0).getSbn().getPackageName()).isEqualTo("other"); 3261 assertThat(mService.mEnqueuedNotifications).hasSize(1); 3262 assertThat(mService.mEnqueuedNotifications.get(0).getSbn().getPackageName()).isEqualTo( 3263 "other"); 3264 } 3265 3266 @Test onOpChanged_permissionStillGranted_notificationsAreNotAffected()3267 public void onOpChanged_permissionStillGranted_notificationsAreNotAffected() 3268 throws RemoteException { 3269 // NOTE: This combination (receiving the onOpChanged broadcast for a package, the permission 3270 // being now granted, AND having previously posted notifications from said package) should 3271 // never happen (if we trust the broadcasts are correct). So this test is for a what-if 3272 // scenario, to verify we still handle it reasonably. 3273 3274 // Have preexisting posted notifications from specific package and other packages. 3275 mService.addNotification(new NotificationRecord(mContext, 3276 generateSbn("granted", 1001, 1, 0), mTestNotificationChannel)); 3277 mService.addNotification(new NotificationRecord(mContext, 3278 generateSbn("other", 1002, 2, 0), mTestNotificationChannel)); 3279 // Have preexisting enqueued notifications from specific package and other packages. 3280 mService.addEnqueuedNotification(new NotificationRecord(mContext, 3281 generateSbn("granted", 1001, 3, 0), mTestNotificationChannel)); 3282 mService.addEnqueuedNotification(new NotificationRecord(mContext, 3283 generateSbn("other", 1002, 4, 0), mTestNotificationChannel)); 3284 assertThat(mService.mNotificationList).hasSize(2); 3285 assertThat(mService.mEnqueuedNotifications).hasSize(2); 3286 3287 when(mPackageManagerInternal.getPackageUid("granted", 0, 0)).thenReturn(1001); 3288 when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(true); 3289 3290 mOnPermissionChangeListener.onOpChanged( 3291 AppOpsManager.OPSTR_POST_NOTIFICATION, "granted", 0); 3292 waitForIdle(); 3293 3294 assertThat(mService.mNotificationList).hasSize(2); 3295 assertThat(mService.mEnqueuedNotifications).hasSize(2); 3296 } 3297 3298 @Test onOpChanged_notInitializedUser_ignored()3299 public void onOpChanged_notInitializedUser_ignored() throws RemoteException { 3300 when(mUmInternal.isUserInitialized(eq(0))).thenReturn(false); 3301 3302 mOnPermissionChangeListener.onOpChanged( 3303 AppOpsManager.OPSTR_POST_NOTIFICATION, "package", 0); 3304 waitForIdle(); 3305 3306 // We early-exited and didn't even query PM for package details. 3307 verify(mPackageManagerInternal, never()).getPackageUid(any(), anyLong(), anyInt()); 3308 } 3309 3310 @Test setNotificationsEnabledForPackage_disabling_clearsNotifications()3311 public void setNotificationsEnabledForPackage_disabling_clearsNotifications() throws Exception { 3312 mService.addNotification(new NotificationRecord(mContext, 3313 generateSbn("package", 1001, 1, 0), mTestNotificationChannel)); 3314 assertThat(mService.mNotificationList).hasSize(1); 3315 when(mPackageManagerInternal.getPackageUid("package", 0, 0)).thenReturn(1001); 3316 when(mPermissionHelper.hasRequestedPermission(any(), eq("package"), anyInt())).thenReturn( 3317 true); 3318 3319 // Start with granted permission and simulate effect of revoking it. 3320 when(mPermissionHelper.hasPermission(1001)).thenReturn(true); 3321 doAnswer(invocation -> { 3322 when(mPermissionHelper.hasPermission(1001)).thenReturn(false); 3323 mOnPermissionChangeListener.onOpChanged( 3324 AppOpsManager.OPSTR_POST_NOTIFICATION, "package", 0); 3325 return null; 3326 }).when(mPermissionHelper).setNotificationPermission("package", 0, false, true); 3327 3328 mBinderService.setNotificationsEnabledForPackage("package", 1001, false); 3329 waitForIdle(); 3330 3331 assertThat(mService.mNotificationList).hasSize(0); 3332 3333 mTestableLooper.moveTimeForward(500); 3334 waitForIdle(); 3335 verify(mContext).sendBroadcastAsUser(any(), eq(UserHandle.of(0)), eq(null)); 3336 } 3337 3338 @Test testUpdateAppNotifyCreatorBlock()3339 public void testUpdateAppNotifyCreatorBlock() throws Exception { 3340 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 3341 3342 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); 3343 Thread.sleep(500); 3344 waitForIdle(); 3345 3346 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3347 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3348 3349 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED, 3350 captor.getValue().getAction()); 3351 assertEquals(PKG, captor.getValue().getPackage()); 3352 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true)); 3353 } 3354 3355 @Test testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting()3356 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception { 3357 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 3358 3359 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false); 3360 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 3361 } 3362 3363 @Test testUpdateAppNotifyCreatorUnblock()3364 public void testUpdateAppNotifyCreatorUnblock() throws Exception { 3365 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 3366 3367 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, true); 3368 Thread.sleep(500); 3369 waitForIdle(); 3370 3371 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3372 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3373 3374 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED, 3375 captor.getValue().getAction()); 3376 assertEquals(PKG, captor.getValue().getPackage()); 3377 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true)); 3378 } 3379 3380 @Test testUpdateChannelNotifyCreatorBlock()3381 public void testUpdateChannelNotifyCreatorBlock() throws Exception { 3382 mService.setPreferencesHelper(mPreferencesHelper); 3383 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3384 eq(mTestNotificationChannel.getId()), anyBoolean())) 3385 .thenReturn(mTestNotificationChannel); 3386 3387 NotificationChannel updatedChannel = 3388 new NotificationChannel(mTestNotificationChannel.getId(), 3389 mTestNotificationChannel.getName(), IMPORTANCE_NONE); 3390 3391 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel); 3392 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3393 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3394 3395 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, 3396 captor.getValue().getAction()); 3397 assertEquals(PKG, captor.getValue().getPackage()); 3398 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra( 3399 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID)); 3400 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 3401 } 3402 3403 @Test testUpdateChannelNotifyCreatorUnblock()3404 public void testUpdateChannelNotifyCreatorUnblock() throws Exception { 3405 NotificationChannel existingChannel = 3406 new NotificationChannel(mTestNotificationChannel.getId(), 3407 mTestNotificationChannel.getName(), IMPORTANCE_NONE); 3408 mService.setPreferencesHelper(mPreferencesHelper); 3409 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3410 eq(mTestNotificationChannel.getId()), anyBoolean())) 3411 .thenReturn(existingChannel); 3412 3413 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 3414 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3415 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3416 3417 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, 3418 captor.getValue().getAction()); 3419 assertEquals(PKG, captor.getValue().getPackage()); 3420 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra( 3421 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID)); 3422 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 3423 } 3424 3425 @Test testUpdateChannelNoNotifyCreatorOtherChanges()3426 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception { 3427 NotificationChannel existingChannel = 3428 new NotificationChannel(mTestNotificationChannel.getId(), 3429 mTestNotificationChannel.getName(), IMPORTANCE_MAX); 3430 mService.setPreferencesHelper(mPreferencesHelper); 3431 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3432 eq(mTestNotificationChannel.getId()), anyBoolean())) 3433 .thenReturn(existingChannel); 3434 3435 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); 3436 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 3437 } 3438 3439 @Test testUpdateGroupNotifyCreatorBlock()3440 public void testUpdateGroupNotifyCreatorBlock() throws Exception { 3441 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 3442 mService.setPreferencesHelper(mPreferencesHelper); 3443 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), 3444 eq(PKG), anyInt())) 3445 .thenReturn(existing); 3446 3447 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name"); 3448 updated.setBlocked(true); 3449 3450 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated); 3451 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3452 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3453 3454 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED, 3455 captor.getValue().getAction()); 3456 assertEquals(PKG, captor.getValue().getPackage()); 3457 assertEquals(existing.getId(), captor.getValue().getStringExtra( 3458 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID)); 3459 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 3460 } 3461 3462 @Test testUpdateGroupNotifyCreatorUnblock()3463 public void testUpdateGroupNotifyCreatorUnblock() throws Exception { 3464 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 3465 existing.setBlocked(true); 3466 mService.setPreferencesHelper(mPreferencesHelper); 3467 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), 3468 eq(PKG), anyInt())) 3469 .thenReturn(existing); 3470 3471 mBinderService.updateNotificationChannelGroupForPackage( 3472 PKG, 0, new NotificationChannelGroup("id", "name")); 3473 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 3474 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null)); 3475 3476 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED, 3477 captor.getValue().getAction()); 3478 assertEquals(PKG, captor.getValue().getPackage()); 3479 assertEquals(existing.getId(), captor.getValue().getStringExtra( 3480 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID)); 3481 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)); 3482 } 3483 3484 @Test testUpdateGroupNoNotifyCreatorOtherChanges()3485 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception { 3486 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name"); 3487 mService.setPreferencesHelper(mPreferencesHelper); 3488 when(mPreferencesHelper.getNotificationChannelGroup( 3489 eq(existing.getId()), eq(PKG), anyInt())) 3490 .thenReturn(existing); 3491 3492 mBinderService.updateNotificationChannelGroupForPackage( 3493 PKG, 0, new NotificationChannelGroup("id", "new name")); 3494 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null)); 3495 } 3496 3497 @Test testCreateChannelNotifyListener()3498 public void testCreateChannelNotifyListener() throws Exception { 3499 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3500 .thenReturn(singletonList(mock(AssociationInfo.class))); 3501 mService.setPreferencesHelper(mPreferencesHelper); 3502 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3503 eq(mTestNotificationChannel.getId()), anyBoolean())) 3504 .thenReturn(mTestNotificationChannel); 3505 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW); 3506 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3507 eq(channel2.getId()), anyBoolean())) 3508 .thenReturn(channel2); 3509 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(), 3510 eq(channel2), anyBoolean(), anyBoolean(), anyInt(), anyBoolean())) 3511 .thenReturn(true); 3512 3513 reset(mListeners); 3514 mBinderService.createNotificationChannels(PKG, 3515 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2))); 3516 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 3517 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3518 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 3519 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 3520 eq(Process.myUserHandle()), eq(channel2), 3521 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 3522 } 3523 3524 @Test testCreateChannelGroupNotifyListener()3525 public void testCreateChannelGroupNotifyListener() throws Exception { 3526 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3527 .thenReturn(singletonList(mock(AssociationInfo.class))); 3528 mService.setPreferencesHelper(mPreferencesHelper); 3529 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b"); 3530 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m"); 3531 3532 reset(mListeners); 3533 mBinderService.createNotificationChannelGroups(PKG, 3534 new ParceledListSlice(Arrays.asList(group1, group2))); 3535 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 3536 eq(Process.myUserHandle()), eq(group1), 3537 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 3538 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 3539 eq(Process.myUserHandle()), eq(group2), 3540 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); 3541 } 3542 3543 @Test testUpdateChannelNotifyListener()3544 public void testUpdateChannelNotifyListener() throws Exception { 3545 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3546 .thenReturn(singletonList(mock(AssociationInfo.class))); 3547 mService.setPreferencesHelper(mPreferencesHelper); 3548 mTestNotificationChannel.setLightColor(Color.CYAN); 3549 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3550 eq(mTestNotificationChannel.getId()), anyBoolean())) 3551 .thenReturn(mTestNotificationChannel); 3552 3553 reset(mListeners); 3554 mBinderService.updateNotificationChannelForPackage(PKG, mUid, mTestNotificationChannel); 3555 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 3556 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3557 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 3558 } 3559 3560 @Test testDeleteChannelNotifyListener()3561 public void testDeleteChannelNotifyListener() throws Exception { 3562 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3563 .thenReturn(singletonList(mock(AssociationInfo.class))); 3564 mService.setPreferencesHelper(mPreferencesHelper); 3565 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3566 eq(mTestNotificationChannel.getId()), anyBoolean())) 3567 .thenReturn(mTestNotificationChannel); 3568 when(mPreferencesHelper.deleteNotificationChannel(eq(PKG), anyInt(), 3569 eq(mTestNotificationChannel.getId()), anyInt(), anyBoolean())).thenReturn(true); 3570 reset(mListeners); 3571 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId()); 3572 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), 3573 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3574 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); 3575 } 3576 3577 @Test testDeleteChannelOnlyDoExtraWorkIfExisted()3578 public void testDeleteChannelOnlyDoExtraWorkIfExisted() throws Exception { 3579 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3580 .thenReturn(singletonList(mock(AssociationInfo.class))); 3581 mService.setPreferencesHelper(mPreferencesHelper); 3582 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3583 eq(mTestNotificationChannel.getId()), anyBoolean())) 3584 .thenReturn(null); 3585 reset(mListeners); 3586 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId()); 3587 verifyNoMoreInteractions(mListeners); 3588 verifyNoMoreInteractions(mHistoryManager); 3589 } 3590 3591 @Test testDeleteChannelGroupNotifyListener()3592 public void testDeleteChannelGroupNotifyListener() throws Exception { 3593 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3594 .thenReturn(singletonList(mock(AssociationInfo.class))); 3595 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c"); 3596 mService.setPreferencesHelper(mPreferencesHelper); 3597 when(mPreferencesHelper.getNotificationChannelGroupWithChannels( 3598 eq(PKG), anyInt(), eq(ncg.getId()), anyBoolean())) 3599 .thenReturn(ncg); 3600 reset(mListeners); 3601 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId()); 3602 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), 3603 eq(Process.myUserHandle()), eq(ncg), 3604 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); 3605 } 3606 3607 @Test testDeleteChannelGroupChecksForFgses()3608 public void testDeleteChannelGroupChecksForFgses() throws Exception { 3609 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3610 .thenReturn(singletonList(mock(AssociationInfo.class))); 3611 CountDownLatch latch = new CountDownLatch(2); 3612 mService.createNotificationChannelGroup( 3613 PKG, mUid, new NotificationChannelGroup("group", "group"), true, false); 3614 new Thread(() -> { 3615 NotificationChannel notificationChannel = new NotificationChannel("id", "id", 3616 NotificationManager.IMPORTANCE_HIGH); 3617 notificationChannel.setGroup("group"); 3618 ParceledListSlice<NotificationChannel> pls = 3619 new ParceledListSlice(ImmutableList.of(notificationChannel)); 3620 try { 3621 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); 3622 } catch (RemoteException e) { 3623 throw new RuntimeException(e); 3624 } 3625 latch.countDown(); 3626 }).start(); 3627 new Thread(() -> { 3628 try { 3629 synchronized (this) { 3630 wait(5000); 3631 } 3632 mService.createNotificationChannelGroup(PKG, mUid, 3633 new NotificationChannelGroup("new", "new group"), true, false); 3634 NotificationChannel notificationChannel = 3635 new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH); 3636 notificationChannel.setGroup("new"); 3637 ParceledListSlice<NotificationChannel> pls = 3638 new ParceledListSlice(ImmutableList.of(notificationChannel)); 3639 try { 3640 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); 3641 mBinderService.deleteNotificationChannelGroup(PKG, "group"); 3642 } catch (RemoteException e) { 3643 throw new RuntimeException(e); 3644 } 3645 } catch (Exception e) { 3646 e.printStackTrace(); 3647 } 3648 latch.countDown(); 3649 }).start(); 3650 3651 latch.await(); 3652 verify(mAmi).hasForegroundServiceNotification(anyString(), anyInt(), anyString()); 3653 } 3654 3655 @Test testUpdateNotificationChannelFromPrivilegedListener_success()3656 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception { 3657 mService.setPreferencesHelper(mPreferencesHelper); 3658 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3659 .thenReturn(singletonList(mock(AssociationInfo.class))); 3660 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), 3661 eq(mTestNotificationChannel.getId()), anyBoolean())) 3662 .thenReturn(mTestNotificationChannel); 3663 3664 mBinderService.updateNotificationChannelFromPrivilegedListener( 3665 null, PKG, Process.myUserHandle(), mTestNotificationChannel); 3666 3667 verify(mPreferencesHelper, times(1)).updateNotificationChannel( 3668 anyString(), anyInt(), any(), anyBoolean(), anyInt(), anyBoolean()); 3669 3670 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 3671 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3672 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 3673 } 3674 3675 @Test testUpdateNotificationChannelFromPrivilegedListener_noAccess()3676 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception { 3677 mService.setPreferencesHelper(mPreferencesHelper); 3678 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3679 .thenReturn(emptyList()); 3680 3681 try { 3682 mBinderService.updateNotificationChannelFromPrivilegedListener( 3683 null, PKG, Process.myUserHandle(), mTestNotificationChannel); 3684 fail("listeners that don't have a companion device shouldn't be able to call this"); 3685 } catch (SecurityException e) { 3686 // pass 3687 } 3688 3689 verify(mPreferencesHelper, never()).updateNotificationChannel( 3690 anyString(), anyInt(), any(), anyBoolean(), anyInt(), anyBoolean()); 3691 3692 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 3693 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3694 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 3695 } 3696 3697 @Test testUpdateNotificationChannelFromPrivilegedListener_badUser()3698 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception { 3699 mService.setPreferencesHelper(mPreferencesHelper); 3700 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3701 .thenReturn(singletonList(mock(AssociationInfo.class))); 3702 mListener = mock(ManagedServices.ManagedServiceInfo.class); 3703 mListener.component = new ComponentName(PKG, PKG); 3704 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 3705 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 3706 3707 try { 3708 mBinderService.updateNotificationChannelFromPrivilegedListener( 3709 null, PKG, UserHandle.ALL, mTestNotificationChannel); 3710 fail("incorrectly allowed a change to a user listener cannot see"); 3711 } catch (SecurityException e) { 3712 // pass 3713 } 3714 3715 verify(mPreferencesHelper, never()).updateNotificationChannel( 3716 anyString(), anyInt(), any(), anyBoolean(), anyInt(), anyBoolean()); 3717 3718 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), 3719 eq(Process.myUserHandle()), eq(mTestNotificationChannel), 3720 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); 3721 } 3722 3723 @Test testGetNotificationChannelFromPrivilegedListener_cdm_success()3724 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception { 3725 mService.setPreferencesHelper(mPreferencesHelper); 3726 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3727 .thenReturn(singletonList(mock(AssociationInfo.class))); 3728 3729 mBinderService.getNotificationChannelsFromPrivilegedListener( 3730 null, PKG, Process.myUserHandle()); 3731 3732 verify(mPreferencesHelper, times(1)).getNotificationChannels( 3733 anyString(), anyInt(), anyBoolean()); 3734 } 3735 3736 @Test testGetNotificationChannelFromPrivilegedListener_cdm_noAccess()3737 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception { 3738 mService.setPreferencesHelper(mPreferencesHelper); 3739 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3740 .thenReturn(emptyList()); 3741 3742 try { 3743 mBinderService.getNotificationChannelsFromPrivilegedListener( 3744 null, PKG, Process.myUserHandle()); 3745 fail("listeners that don't have a companion device shouldn't be able to call this"); 3746 } catch (SecurityException e) { 3747 // pass 3748 } 3749 3750 verify(mPreferencesHelper, never()).getNotificationChannels( 3751 anyString(), anyInt(), anyBoolean()); 3752 } 3753 3754 @Test testGetNotificationChannelFromPrivilegedListener_assistant_success()3755 public void testGetNotificationChannelFromPrivilegedListener_assistant_success() 3756 throws Exception { 3757 mService.setPreferencesHelper(mPreferencesHelper); 3758 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3759 .thenReturn(emptyList()); 3760 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); 3761 3762 mBinderService.getNotificationChannelsFromPrivilegedListener( 3763 null, PKG, Process.myUserHandle()); 3764 3765 verify(mPreferencesHelper, times(1)).getNotificationChannels( 3766 anyString(), anyInt(), anyBoolean()); 3767 } 3768 3769 @Test testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()3770 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess() 3771 throws Exception { 3772 mService.setPreferencesHelper(mPreferencesHelper); 3773 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3774 .thenReturn(emptyList()); 3775 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false); 3776 3777 try { 3778 mBinderService.getNotificationChannelsFromPrivilegedListener( 3779 null, PKG, Process.myUserHandle()); 3780 fail("listeners that don't have a companion device shouldn't be able to call this"); 3781 } catch (SecurityException e) { 3782 // pass 3783 } 3784 3785 verify(mPreferencesHelper, never()).getNotificationChannels( 3786 anyString(), anyInt(), anyBoolean()); 3787 } 3788 3789 @Test testGetNotificationChannelFromPrivilegedListener_badUser()3790 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception { 3791 mService.setPreferencesHelper(mPreferencesHelper); 3792 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3793 .thenReturn(singletonList(mock(AssociationInfo.class))); 3794 mListener = mock(ManagedServices.ManagedServiceInfo.class); 3795 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 3796 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 3797 3798 try { 3799 mBinderService.getNotificationChannelsFromPrivilegedListener( 3800 null, PKG, Process.myUserHandle()); 3801 fail("listener getting channels from a user they cannot see"); 3802 } catch (SecurityException e) { 3803 // pass 3804 } 3805 3806 verify(mPreferencesHelper, never()).getNotificationChannels( 3807 anyString(), anyInt(), anyBoolean()); 3808 } 3809 3810 @Test testGetNotificationChannelGroupsFromPrivilegedListener_success()3811 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception { 3812 mService.setPreferencesHelper(mPreferencesHelper); 3813 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3814 .thenReturn(singletonList(mock(AssociationInfo.class))); 3815 3816 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 3817 null, PKG, Process.myUserHandle()); 3818 3819 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt()); 3820 } 3821 3822 @Test testGetNotificationChannelGroupsFromPrivilegedListener_noAccess()3823 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception { 3824 mService.setPreferencesHelper(mPreferencesHelper); 3825 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3826 .thenReturn(emptyList()); 3827 3828 try { 3829 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 3830 null, PKG, Process.myUserHandle()); 3831 fail("listeners that don't have a companion device shouldn't be able to call this"); 3832 } catch (SecurityException e) { 3833 // pass 3834 } 3835 3836 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); 3837 } 3838 3839 @Test testGetNotificationChannelGroupsFromPrivilegedListener_badUser()3840 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception { 3841 mService.setPreferencesHelper(mPreferencesHelper); 3842 when(mCompanionMgr.getAssociations(PKG, mUserId)) 3843 .thenReturn(emptyList()); 3844 mListener = mock(ManagedServices.ManagedServiceInfo.class); 3845 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 3846 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 3847 try { 3848 mBinderService.getNotificationChannelGroupsFromPrivilegedListener( 3849 null, PKG, Process.myUserHandle()); 3850 fail("listeners that don't have a companion device shouldn't be able to call this"); 3851 } catch (SecurityException e) { 3852 // pass 3853 } 3854 3855 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); 3856 } 3857 3858 @Test testHasCompanionDevice_failure()3859 public void testHasCompanionDevice_failure() throws Exception { 3860 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow( 3861 new IllegalArgumentException()); 3862 mService.hasCompanionDevice(mListener); 3863 } 3864 3865 @Test testHasCompanionDevice_noService()3866 public void testHasCompanionDevice_noService() { 3867 NotificationManagerService noManService = 3868 new TestableNotificationManagerService(mContext, mNotificationRecordLogger, 3869 mNotificationInstanceIdSequence); 3870 3871 assertFalse(noManService.hasCompanionDevice(mListener)); 3872 } 3873 3874 @Test testCrossUserSnooze()3875 public void testCrossUserSnooze() { 3876 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10); 3877 mService.addNotification(r); 3878 NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0); 3879 mService.addNotification(r2); 3880 3881 mListener = mock(ManagedServices.ManagedServiceInfo.class); 3882 mListener.component = new ComponentName(PKG, PKG); 3883 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); 3884 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 3885 3886 mService.snoozeNotificationInt(r.getKey(), 1000, null, mListener); 3887 3888 verify(mWorkerHandler, never()).post( 3889 any(NotificationManagerService.SnoozeNotificationRunnable.class)); 3890 } 3891 3892 @Test testSameUserSnooze()3893 public void testSameUserSnooze() { 3894 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10); 3895 mService.addNotification(r); 3896 NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0); 3897 mService.addNotification(r2); 3898 3899 mListener = mock(ManagedServices.ManagedServiceInfo.class); 3900 mListener.component = new ComponentName(PKG, PKG); 3901 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(true); 3902 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); 3903 3904 mService.snoozeNotificationInt(r2.getKey(), 1000, null, mListener); 3905 3906 verify(mWorkerHandler).post( 3907 any(NotificationManagerService.SnoozeNotificationRunnable.class)); 3908 } 3909 3910 @Test testSnoozeRunnable_tooManySnoozed_singleNotification()3911 public void testSnoozeRunnable_tooManySnoozed_singleNotification() { 3912 final NotificationRecord notification = generateNotificationRecord( 3913 mTestNotificationChannel, 1, null, true); 3914 mService.addNotification(notification); 3915 3916 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 3917 when(mSnoozeHelper.canSnooze(1)).thenReturn(false); 3918 3919 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 3920 mService.new SnoozeNotificationRunnable( 3921 notification.getKey(), 100, null); 3922 snoozeNotificationRunnable.run(); 3923 3924 verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong()); 3925 assertThat(mService.getNotificationRecordCount()).isEqualTo(1); 3926 } 3927 3928 @Test testSnoozeRunnable_tooManySnoozed_singleGroupChildNotification()3929 public void testSnoozeRunnable_tooManySnoozed_singleGroupChildNotification() { 3930 final NotificationRecord notification = generateNotificationRecord( 3931 mTestNotificationChannel, 1, "group", true); 3932 final NotificationRecord notificationChild = generateNotificationRecord( 3933 mTestNotificationChannel, 1, "group", false); 3934 mService.addNotification(notification); 3935 mService.addNotification(notificationChild); 3936 3937 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 3938 when(mSnoozeHelper.canSnooze(2)).thenReturn(false); 3939 3940 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 3941 mService.new SnoozeNotificationRunnable( 3942 notificationChild.getKey(), 100, null); 3943 snoozeNotificationRunnable.run(); 3944 3945 verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong()); 3946 assertThat(mService.getNotificationRecordCount()).isEqualTo(2); 3947 } 3948 3949 @Test testSnoozeRunnable_tooManySnoozed_summaryNotification()3950 public void testSnoozeRunnable_tooManySnoozed_summaryNotification() { 3951 final NotificationRecord notification = generateNotificationRecord( 3952 mTestNotificationChannel, 1, "group", true); 3953 final NotificationRecord notificationChild = generateNotificationRecord( 3954 mTestNotificationChannel, 12, "group", false); 3955 final NotificationRecord notificationChild2 = generateNotificationRecord( 3956 mTestNotificationChannel, 13, "group", false); 3957 mService.addNotification(notification); 3958 mService.addNotification(notificationChild); 3959 mService.addNotification(notificationChild2); 3960 3961 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 3962 when(mSnoozeHelper.canSnooze(3)).thenReturn(false); 3963 3964 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 3965 mService.new SnoozeNotificationRunnable( 3966 notification.getKey(), 100, null); 3967 snoozeNotificationRunnable.run(); 3968 3969 verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong()); 3970 assertThat(mService.getNotificationRecordCount()).isEqualTo(3); 3971 } 3972 3973 @Test testSnoozeRunnable_reSnoozeASingleSnoozedNotification()3974 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() { 3975 final NotificationRecord notification = generateNotificationRecord( 3976 mTestNotificationChannel, 1, null, true); 3977 mService.addNotification(notification); 3978 when(mSnoozeHelper.getNotification(any())).thenReturn(notification); 3979 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 3980 3981 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 3982 mService.new SnoozeNotificationRunnable( 3983 notification.getKey(), 100, null); 3984 snoozeNotificationRunnable.run(); 3985 snoozeNotificationRunnable.run(); 3986 3987 // snooze twice 3988 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 3989 } 3990 3991 @Test testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey()3992 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() { 3993 final NotificationRecord notification = generateNotificationRecord( 3994 mTestNotificationChannel, 1, "group", true); 3995 mService.addNotification(notification); 3996 when(mSnoozeHelper.getNotification(any())).thenReturn(notification); 3997 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 3998 3999 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4000 mService.new SnoozeNotificationRunnable( 4001 notification.getKey(), 100, null); 4002 snoozeNotificationRunnable.run(); 4003 snoozeNotificationRunnable.run(); 4004 4005 // snooze twice 4006 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 4007 } 4008 4009 @Test testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey()4010 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception { 4011 final NotificationRecord notification = generateNotificationRecord( 4012 mTestNotificationChannel, 1, "group", true); 4013 final NotificationRecord notification2 = generateNotificationRecord( 4014 mTestNotificationChannel, 2, "group", true); 4015 mService.addNotification(notification); 4016 mService.addNotification(notification2); 4017 when(mSnoozeHelper.getNotification(any())).thenReturn(notification); 4018 when(mSnoozeHelper.getNotifications( 4019 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>()); 4020 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4021 4022 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4023 mService.new SnoozeNotificationRunnable( 4024 notification.getKey(), 100, null); 4025 snoozeNotificationRunnable.run(); 4026 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt())) 4027 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2))); 4028 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 = 4029 mService.new SnoozeNotificationRunnable( 4030 notification2.getKey(), 100, null); 4031 snoozeNotificationRunnable2.run(); 4032 4033 // snooze twice 4034 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong()); 4035 } 4036 4037 @Test testSnoozeRunnable_snoozeNonGrouped()4038 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception { 4039 final NotificationRecord nonGrouped = generateNotificationRecord( 4040 mTestNotificationChannel, 1, null, false); 4041 final NotificationRecord grouped = generateNotificationRecord( 4042 mTestNotificationChannel, 2, "group", false); 4043 mService.addNotification(grouped); 4044 mService.addNotification(nonGrouped); 4045 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4046 4047 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4048 mService.new SnoozeNotificationRunnable( 4049 nonGrouped.getKey(), 100, null); 4050 snoozeNotificationRunnable.run(); 4051 4052 // only snooze the one notification 4053 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 4054 assertTrue(nonGrouped.getStats().hasSnoozed()); 4055 4056 assertEquals(2, mNotificationRecordLogger.numCalls()); 4057 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4058 mNotificationRecordLogger.event(0)); 4059 assertEquals( 4060 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 4061 mNotificationRecordLogger.event(1)); 4062 } 4063 4064 @Test testSnoozeRunnable_snoozeSummary_withChildren()4065 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception { 4066 final NotificationRecord parent = generateNotificationRecord( 4067 mTestNotificationChannel, 1, "group", true); 4068 final NotificationRecord child = generateNotificationRecord( 4069 mTestNotificationChannel, 2, "group", false); 4070 final NotificationRecord child2 = generateNotificationRecord( 4071 mTestNotificationChannel, 3, "group", false); 4072 mService.addNotification(parent); 4073 mService.addNotification(child); 4074 mService.addNotification(child2); 4075 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4076 4077 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4078 mService.new SnoozeNotificationRunnable( 4079 parent.getKey(), 100, null); 4080 snoozeNotificationRunnable.run(); 4081 4082 // snooze parent and children 4083 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong()); 4084 } 4085 4086 @Test testSnoozeRunnable_snoozeGroupChild_fellowChildren()4087 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception { 4088 final NotificationRecord parent = generateNotificationRecord( 4089 mTestNotificationChannel, 1, "group", true); 4090 final NotificationRecord child = generateNotificationRecord( 4091 mTestNotificationChannel, 2, "group", false); 4092 final NotificationRecord child2 = generateNotificationRecord( 4093 mTestNotificationChannel, 3, "group", false); 4094 mService.addNotification(parent); 4095 mService.addNotification(child); 4096 mService.addNotification(child2); 4097 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4098 4099 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4100 mService.new SnoozeNotificationRunnable( 4101 child2.getKey(), 100, null); 4102 snoozeNotificationRunnable.run(); 4103 4104 // only snooze the one child 4105 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 4106 4107 assertEquals(2, mNotificationRecordLogger.numCalls()); 4108 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4109 mNotificationRecordLogger.event(0)); 4110 assertEquals(NotificationRecordLogger.NotificationCancelledEvent 4111 .NOTIFICATION_CANCEL_SNOOZED, mNotificationRecordLogger.event(1)); 4112 } 4113 4114 @Test testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary()4115 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception { 4116 final NotificationRecord parent = generateNotificationRecord( 4117 mTestNotificationChannel, 1, "group", true); 4118 assertTrue(parent.getSbn().getNotification().isGroupSummary()); 4119 final NotificationRecord child = generateNotificationRecord( 4120 mTestNotificationChannel, 2, "group", false); 4121 mService.addNotification(parent); 4122 mService.addNotification(child); 4123 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4124 4125 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4126 mService.new SnoozeNotificationRunnable( 4127 child.getKey(), 100, null); 4128 snoozeNotificationRunnable.run(); 4129 4130 // snooze child and summary 4131 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); 4132 4133 assertEquals(4, mNotificationRecordLogger.numCalls()); 4134 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4135 mNotificationRecordLogger.event(0)); 4136 assertEquals( 4137 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 4138 mNotificationRecordLogger.event(1)); 4139 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4140 mNotificationRecordLogger.event(2)); 4141 assertEquals( 4142 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 4143 mNotificationRecordLogger.event(3)); 4144 } 4145 4146 @Test testSnoozeRunnable_snoozeGroupChild_noOthersInGroup()4147 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception { 4148 final NotificationRecord child = generateNotificationRecord( 4149 mTestNotificationChannel, 2, "group", false); 4150 mService.addNotification(child); 4151 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4152 4153 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4154 mService.new SnoozeNotificationRunnable( 4155 child.getKey(), 100, null); 4156 snoozeNotificationRunnable.run(); 4157 4158 // snooze child only 4159 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 4160 4161 assertEquals(2, mNotificationRecordLogger.numCalls()); 4162 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4163 mNotificationRecordLogger.event(0)); 4164 assertEquals( 4165 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 4166 mNotificationRecordLogger.event(1)); 4167 } 4168 4169 @Test testSnoozeRunnable_snoozeAutoGroupChild_summaryNotSnoozed()4170 public void testSnoozeRunnable_snoozeAutoGroupChild_summaryNotSnoozed() throws Exception { 4171 final NotificationRecord parent = generateNotificationRecord( 4172 mTestNotificationChannel, 1, GroupHelper.AUTOGROUP_KEY, true); 4173 final NotificationRecord child = generateNotificationRecord( 4174 mTestNotificationChannel, 2, GroupHelper.AUTOGROUP_KEY, false); 4175 mService.addNotification(parent); 4176 mService.addNotification(child); 4177 when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true); 4178 4179 // snooze child only 4180 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4181 mService.new SnoozeNotificationRunnable( 4182 child.getKey(), 100, null); 4183 snoozeNotificationRunnable.run(); 4184 4185 // only child should be snoozed 4186 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); 4187 4188 // both group summary and child should be cancelled 4189 assertNull(mService.getNotificationRecord(parent.getKey())); 4190 assertNull(mService.getNotificationRecord(child.getKey())); 4191 4192 assertEquals(4, mNotificationRecordLogger.numCalls()); 4193 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED, 4194 mNotificationRecordLogger.event(0)); 4195 assertEquals( 4196 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED, 4197 mNotificationRecordLogger.event(1)); 4198 } 4199 4200 @Test testPostGroupChild_unsnoozeParent()4201 public void testPostGroupChild_unsnoozeParent() throws Exception { 4202 final NotificationRecord child = generateNotificationRecord( 4203 mTestNotificationChannel, 2, "group", false); 4204 4205 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing", 4206 child.getSbn().getId(), child.getSbn().getNotification(), 4207 child.getSbn().getUserId()); 4208 waitForIdle(); 4209 4210 verify(mSnoozeHelper, times(1)).repostGroupSummary( 4211 anyString(), anyInt(), eq(child.getGroupKey())); 4212 } 4213 4214 @Test testPostNonGroup_noUnsnoozing()4215 public void testPostNonGroup_noUnsnoozing() throws Exception { 4216 final NotificationRecord record = generateNotificationRecord( 4217 mTestNotificationChannel, 2, null, false); 4218 4219 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing", 4220 record.getSbn().getId(), record.getSbn().getNotification(), 4221 record.getSbn().getUserId()); 4222 waitForIdle(); 4223 4224 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); 4225 } 4226 4227 @Test testPostGroupSummary_noUnsnoozing()4228 public void testPostGroupSummary_noUnsnoozing() throws Exception { 4229 final NotificationRecord parent = generateNotificationRecord( 4230 mTestNotificationChannel, 2, "group", true); 4231 4232 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing", 4233 parent.getSbn().getId(), parent.getSbn().getNotification(), 4234 parent.getSbn().getUserId()); 4235 waitForIdle(); 4236 4237 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); 4238 } 4239 4240 @Test testSystemNotificationListenerCanUnsnooze()4241 public void testSystemNotificationListenerCanUnsnooze() throws Exception { 4242 final NotificationRecord nr = generateNotificationRecord( 4243 mTestNotificationChannel, 2, "group", false); 4244 4245 mBinderService.enqueueNotificationWithTag(PKG, PKG, 4246 "testSystemNotificationListenerCanUnsnooze", 4247 nr.getSbn().getId(), nr.getSbn().getNotification(), 4248 nr.getSbn().getUserId()); 4249 waitForIdle(); 4250 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = 4251 mService.new SnoozeNotificationRunnable( 4252 nr.getKey(), 100, null); 4253 snoozeNotificationRunnable.run(); 4254 4255 ManagedServices.ManagedServiceInfo listener = mListeners.new ManagedServiceInfo( 4256 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0, 234); 4257 listener.isSystem = true; 4258 when(mListeners.checkServiceTokenLocked(any())).thenReturn(listener); 4259 4260 mBinderService.unsnoozeNotificationFromSystemListener(null, nr.getKey()); 4261 waitForIdle(); 4262 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 4263 assertEquals(1, notifs.length); 4264 assertNotNull(notifs[0].getKey());//mService.getNotificationRecord(nr.getSbn().getKey())); 4265 } 4266 4267 @Test testSetListenerAccessForUser()4268 public void testSetListenerAccessForUser() throws Exception { 4269 UserHandle user = UserHandle.of(mContext.getUserId() + 10); 4270 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4271 mBinderService.setNotificationListenerAccessGrantedForUser( 4272 c, user.getIdentifier(), true, true); 4273 4274 4275 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 4276 verify(mListeners, times(1)).setPackageOrComponentEnabled( 4277 c.flattenToString(), user.getIdentifier(), true, true, true); 4278 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4279 c.flattenToString(), user.getIdentifier(), false, true, true); 4280 verify(mAssistants, never()).setPackageOrComponentEnabled( 4281 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4282 } 4283 4284 @Test testSetListenerAccessForUser_grantWithNameTooLong_throws()4285 public void testSetListenerAccessForUser_grantWithNameTooLong_throws() { 4286 UserHandle user = UserHandle.of(mContext.getUserId() + 10); 4287 ComponentName c = new ComponentName("com.example.package", 4288 com.google.common.base.Strings.repeat("Blah", 150)); 4289 4290 assertThrows(IllegalArgumentException.class, 4291 () -> mBinderService.setNotificationListenerAccessGrantedForUser( 4292 c, user.getIdentifier(), /* enabled= */ true, true)); 4293 } 4294 4295 @Test testSetListenerAccessForUser_revokeWithNameTooLong_okay()4296 public void testSetListenerAccessForUser_revokeWithNameTooLong_okay() throws Exception { 4297 UserHandle user = UserHandle.of(mContext.getUserId() + 10); 4298 ComponentName c = new ComponentName("com.example.package", 4299 com.google.common.base.Strings.repeat("Blah", 150)); 4300 4301 mBinderService.setNotificationListenerAccessGrantedForUser( 4302 c, user.getIdentifier(), /* enabled= */ false, true); 4303 4304 verify(mListeners).setPackageOrComponentEnabled( 4305 c.flattenToString(), user.getIdentifier(), true, /* enabled= */ false, true); 4306 } 4307 4308 @Test testSetAssistantAccessForUser()4309 public void testSetAssistantAccessForUser() throws Exception { 4310 UserInfo ui = new UserInfo(); 4311 ui.id = mContext.getUserId() + 10; 4312 UserHandle user = UserHandle.of(ui.id); 4313 List<UserInfo> uis = new ArrayList<>(); 4314 uis.add(ui); 4315 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4316 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4317 4318 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true); 4319 4320 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 4321 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4322 c.flattenToString(), user.getIdentifier(), true, true, true); 4323 verify(mAssistants).setUserSet(ui.id, true); 4324 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4325 c.flattenToString(), user.getIdentifier(), false, true); 4326 verify(mListeners, never()).setPackageOrComponentEnabled( 4327 any(), anyInt(), anyBoolean(), anyBoolean()); 4328 } 4329 4330 @Test testGetAssistantAllowedForUser()4331 public void testGetAssistantAllowedForUser() throws Exception { 4332 UserHandle user = UserHandle.of(mContext.getUserId() + 10); 4333 try { 4334 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier()); 4335 } catch (IllegalStateException e) { 4336 if (!e.getMessage().contains("At most one NotificationAssistant")) { 4337 throw e; 4338 } 4339 } 4340 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier()); 4341 } 4342 4343 @Test testGetAssistantAllowed()4344 public void testGetAssistantAllowed() throws Exception { 4345 try { 4346 mBinderService.getAllowedNotificationAssistant(); 4347 } catch (IllegalStateException e) { 4348 if (!e.getMessage().contains("At most one NotificationAssistant")) { 4349 throw e; 4350 } 4351 } 4352 verify(mAssistants, times(1)).getAllowedComponents(mContext.getUserId()); 4353 } 4354 4355 @Test testSetNASMigrationDoneAndResetDefault_enableNAS()4356 public void testSetNASMigrationDoneAndResetDefault_enableNAS() throws Exception { 4357 int userId = 10; 4358 setNASMigrationDone(false, userId); 4359 when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId}); 4360 4361 mBinderService.setNASMigrationDoneAndResetDefault(userId, true); 4362 4363 assertTrue(mService.isNASMigrationDone(userId)); 4364 verify(mAssistants, times(1)).resetDefaultFromConfig(); 4365 } 4366 4367 @Test testSetNASMigrationDoneAndResetDefault_disableNAS()4368 public void testSetNASMigrationDoneAndResetDefault_disableNAS() throws Exception { 4369 int userId = 10; 4370 setNASMigrationDone(false, userId); 4371 when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId}); 4372 4373 mBinderService.setNASMigrationDoneAndResetDefault(userId, false); 4374 4375 assertTrue(mService.isNASMigrationDone(userId)); 4376 verify(mAssistants, times(1)).clearDefaults(); 4377 } 4378 4379 @Test testSetNASMigrationDoneAndResetDefault_multiProfile()4380 public void testSetNASMigrationDoneAndResetDefault_multiProfile() throws Exception { 4381 int userId1 = 11; 4382 int userId2 = 12; //work profile 4383 setNASMigrationDone(false, userId1); 4384 setNASMigrationDone(false, userId2); 4385 setUsers(new int[]{userId1, userId2}); 4386 when(mUm.isManagedProfile(userId2)).thenReturn(true); 4387 when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1, userId2}); 4388 4389 mBinderService.setNASMigrationDoneAndResetDefault(userId1, true); 4390 assertTrue(mService.isNASMigrationDone(userId1)); 4391 assertTrue(mService.isNASMigrationDone(userId2)); 4392 } 4393 4394 @Test testSetNASMigrationDoneAndResetDefault_multiUser()4395 public void testSetNASMigrationDoneAndResetDefault_multiUser() throws Exception { 4396 int userId1 = 11; 4397 int userId2 = 12; 4398 setNASMigrationDone(false, userId1); 4399 setNASMigrationDone(false, userId2); 4400 setUsers(new int[]{userId1, userId2}); 4401 when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1}); 4402 when(mUm.getProfileIds(userId2, false)).thenReturn(new int[]{userId2}); 4403 4404 mBinderService.setNASMigrationDoneAndResetDefault(userId1, true); 4405 assertTrue(mService.isNASMigrationDone(userId1)); 4406 assertFalse(mService.isNASMigrationDone(userId2)); 4407 } 4408 4409 @Test testSetDndAccessForUser()4410 public void testSetDndAccessForUser() throws Exception { 4411 UserHandle user = UserHandle.of(mContext.getUserId() + 10); 4412 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4413 mBinderService.setNotificationPolicyAccessGrantedForUser( 4414 c.getPackageName(), user.getIdentifier(), true); 4415 4416 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any()); 4417 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4418 c.getPackageName(), user.getIdentifier(), true, true); 4419 verify(mAssistants, never()).setPackageOrComponentEnabled( 4420 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4421 verify(mListeners, never()).setPackageOrComponentEnabled( 4422 any(), anyInt(), anyBoolean(), anyBoolean()); 4423 } 4424 4425 @Test testSetListenerAccess()4426 public void testSetListenerAccess() throws Exception { 4427 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4428 mBinderService.setNotificationListenerAccessGranted(c, true, true); 4429 4430 verify(mListeners, times(1)).setPackageOrComponentEnabled( 4431 c.flattenToString(), mContext.getUserId(), true, true, true); 4432 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4433 c.flattenToString(), mContext.getUserId(), false, true, true); 4434 verify(mAssistants, never()).setPackageOrComponentEnabled( 4435 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4436 } 4437 4438 @Test testSetAssistantAccess()4439 public void testSetAssistantAccess() throws Exception { 4440 List<UserInfo> uis = new ArrayList<>(); 4441 UserInfo ui = new UserInfo(); 4442 ui.id = mContext.getUserId(); 4443 uis.add(ui); 4444 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4445 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4446 4447 mBinderService.setNotificationAssistantAccessGranted(c, true); 4448 4449 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4450 c.flattenToString(), ui.id, true, true, true); 4451 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4452 c.flattenToString(), ui.id, false, true); 4453 verify(mListeners, never()).setPackageOrComponentEnabled( 4454 any(), anyInt(), anyBoolean(), anyBoolean()); 4455 } 4456 4457 @Test testSetAssistantAccess_multiProfile()4458 public void testSetAssistantAccess_multiProfile() throws Exception { 4459 List<UserInfo> uis = new ArrayList<>(); 4460 UserInfo ui = new UserInfo(); 4461 ui.id = mContext.getUserId(); 4462 uis.add(ui); 4463 UserInfo ui10 = new UserInfo(); 4464 ui10.id = mContext.getUserId() + 10; 4465 uis.add(ui10); 4466 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4467 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4468 4469 mBinderService.setNotificationAssistantAccessGranted(c, true); 4470 4471 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4472 c.flattenToString(), ui.id, true, true, true); 4473 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4474 c.flattenToString(), ui10.id, true, true, true); 4475 4476 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4477 c.flattenToString(), ui.id, false, true); 4478 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4479 c.flattenToString(), ui10.id, false, true); 4480 verify(mListeners, never()).setPackageOrComponentEnabled( 4481 any(), anyInt(), anyBoolean(), anyBoolean()); 4482 } 4483 4484 @Test testSetAssistantAccess_nullWithAllowedAssistant()4485 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception { 4486 ArrayList<ComponentName> componentList = new ArrayList<>(); 4487 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4488 componentList.add(c); 4489 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 4490 List<UserInfo> uis = new ArrayList<>(); 4491 UserInfo ui = new UserInfo(); 4492 ui.id = mContext.getUserId(); 4493 uis.add(ui); 4494 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4495 4496 mBinderService.setNotificationAssistantAccessGranted(null, true); 4497 4498 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4499 c.flattenToString(), ui.id, true, false, true); 4500 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4501 c.flattenToString(), ui.id, false, false); 4502 verify(mListeners, never()).setPackageOrComponentEnabled( 4503 any(), anyInt(), anyBoolean(), anyBoolean()); 4504 } 4505 4506 @Test testSetAssistantAccessForUser_nullWithAllowedAssistant()4507 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception { 4508 List<UserInfo> uis = new ArrayList<>(); 4509 UserInfo ui = new UserInfo(); 4510 ui.id = mContext.getUserId() + 10; 4511 uis.add(ui); 4512 UserHandle user = ui.getUserHandle(); 4513 ArrayList<ComponentName> componentList = new ArrayList<>(); 4514 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4515 componentList.add(c); 4516 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 4517 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4518 4519 mBinderService.setNotificationAssistantAccessGrantedForUser( 4520 null, user.getIdentifier(), true); 4521 4522 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4523 c.flattenToString(), user.getIdentifier(), true, false, true); 4524 verify(mAssistants).setUserSet(ui.id, true); 4525 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4526 c.flattenToString(), user.getIdentifier(), false, false); 4527 verify(mListeners, never()).setPackageOrComponentEnabled( 4528 any(), anyInt(), anyBoolean(), anyBoolean()); 4529 } 4530 4531 @Test testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()4532 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant() 4533 throws Exception { 4534 List<UserInfo> uis = new ArrayList<>(); 4535 UserInfo ui = new UserInfo(); 4536 ui.id = mContext.getUserId(); 4537 uis.add(ui); 4538 UserInfo ui10 = new UserInfo(); 4539 ui10.id = mContext.getUserId() + 10; 4540 uis.add(ui10); 4541 UserHandle user = ui.getUserHandle(); 4542 ArrayList<ComponentName> componentList = new ArrayList<>(); 4543 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4544 componentList.add(c); 4545 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList); 4546 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4547 4548 mBinderService.setNotificationAssistantAccessGrantedForUser( 4549 null, user.getIdentifier(), true); 4550 4551 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4552 c.flattenToString(), user.getIdentifier(), true, false, true); 4553 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4554 c.flattenToString(), ui10.id, true, false, true); 4555 verify(mAssistants).setUserSet(ui.id, true); 4556 verify(mAssistants).setUserSet(ui10.id, true); 4557 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4558 c.flattenToString(), user.getIdentifier(), false, false); 4559 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4560 c.flattenToString(), ui10.id, false, false); 4561 verify(mListeners, never()).setPackageOrComponentEnabled( 4562 any(), anyInt(), anyBoolean(), anyBoolean()); 4563 } 4564 4565 @Test testSetDndAccess()4566 public void testSetDndAccess() throws Exception { 4567 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4568 4569 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 4570 4571 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4572 c.getPackageName(), mContext.getUserId(), true, true); 4573 verify(mAssistants, never()).setPackageOrComponentEnabled( 4574 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4575 verify(mListeners, never()).setPackageOrComponentEnabled( 4576 any(), anyInt(), anyBoolean(), anyBoolean()); 4577 } 4578 4579 @Test testSetListenerAccess_onLowRam()4580 public void testSetListenerAccess_onLowRam() throws Exception { 4581 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4582 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4583 mBinderService.setNotificationListenerAccessGranted(c, true, true); 4584 4585 verify(mListeners).setPackageOrComponentEnabled( 4586 anyString(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4587 verify(mConditionProviders).setPackageOrComponentEnabled( 4588 anyString(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4589 verify(mAssistants).migrateToXml(); 4590 verify(mAssistants).resetDefaultAssistantsIfNecessary(); 4591 } 4592 4593 @Test testSetAssistantAccess_onLowRam()4594 public void testSetAssistantAccess_onLowRam() throws Exception { 4595 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4596 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4597 List<UserInfo> uis = new ArrayList<>(); 4598 UserInfo ui = new UserInfo(); 4599 ui.id = mContext.getUserId(); 4600 uis.add(ui); 4601 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4602 4603 mBinderService.setNotificationAssistantAccessGranted(c, true); 4604 4605 verify(mListeners).migrateToXml(); 4606 verify(mConditionProviders).setPackageOrComponentEnabled( 4607 anyString(), anyInt(), anyBoolean(), anyBoolean()); 4608 verify(mAssistants).migrateToXml(); 4609 verify(mAssistants).resetDefaultAssistantsIfNecessary(); 4610 } 4611 4612 @Test testSetDndAccess_onLowRam()4613 public void testSetDndAccess_onLowRam() throws Exception { 4614 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4615 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4616 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 4617 4618 verify(mListeners).migrateToXml(); 4619 verify(mConditionProviders).setPackageOrComponentEnabled( 4620 anyString(), anyInt(), anyBoolean(), anyBoolean()); 4621 verify(mAssistants).migrateToXml(); 4622 verify(mAssistants).resetDefaultAssistantsIfNecessary(); 4623 } 4624 4625 @Test testSetListenerAccess_doesNothingOnLowRam_exceptWatch()4626 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 4627 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 4628 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4629 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4630 4631 mBinderService.setNotificationListenerAccessGranted(c, true, true); 4632 4633 verify(mListeners, times(1)).setPackageOrComponentEnabled( 4634 c.flattenToString(), mContext.getUserId(), true, true, true); 4635 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4636 c.flattenToString(), mContext.getUserId(), false, true, true); 4637 verify(mAssistants, never()).setPackageOrComponentEnabled( 4638 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4639 } 4640 4641 @Test testSetAssistantAccess_doesNothingOnLowRam_exceptWatch()4642 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 4643 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 4644 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4645 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4646 List<UserInfo> uis = new ArrayList<>(); 4647 UserInfo ui = new UserInfo(); 4648 ui.id = mContext.getUserId(); 4649 uis.add(ui); 4650 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis); 4651 4652 mBinderService.setNotificationAssistantAccessGranted(c, true); 4653 4654 verify(mListeners, never()).setPackageOrComponentEnabled( 4655 anyString(), anyInt(), anyBoolean(), anyBoolean()); 4656 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4657 c.flattenToString(), ui.id, false, true); 4658 verify(mAssistants, times(1)).setPackageOrComponentEnabled( 4659 c.flattenToString(), ui.id, true, true, true); 4660 } 4661 4662 @Test testSetDndAccess_doesNothingOnLowRam_exceptWatch()4663 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception { 4664 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); 4665 when(mActivityManager.isLowRamDevice()).thenReturn(true); 4666 ComponentName c = ComponentName.unflattenFromString("package/Component"); 4667 4668 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); 4669 4670 verify(mListeners, never()).setPackageOrComponentEnabled( 4671 anyString(), anyInt(), anyBoolean(), anyBoolean()); 4672 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 4673 c.getPackageName(), mContext.getUserId(), true, true); 4674 verify(mAssistants, never()).setPackageOrComponentEnabled( 4675 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); 4676 } 4677 4678 @Test testOnlyAutogroupIfNeeded_newNotification_ghUpdate()4679 public void testOnlyAutogroupIfNeeded_newNotification_ghUpdate() { 4680 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 4681 mService.addEnqueuedNotification(r); 4682 NotificationManagerService.PostNotificationRunnable runnable = 4683 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 4684 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 4685 runnable.run(); 4686 waitForIdle(); 4687 4688 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 4689 } 4690 4691 @Test testOnlyAutogroupIfNeeded_groupChanged_ghUpdate()4692 public void testOnlyAutogroupIfNeeded_groupChanged_ghUpdate() { 4693 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, 4694 "testOnlyAutogroupIfNeeded_groupChanged_ghUpdate", "group", false); 4695 mService.addNotification(r); 4696 4697 NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0, 4698 "testOnlyAutogroupIfNeeded_groupChanged_ghUpdate", null, false); 4699 mService.addEnqueuedNotification(update); 4700 NotificationManagerService.PostNotificationRunnable runnable = 4701 mService.new PostNotificationRunnable(update.getKey(), 4702 update.getSbn().getPackageName(), update.getUid(), 4703 mPostNotificationTrackerFactory.newTracker(null)); 4704 runnable.run(); 4705 waitForIdle(); 4706 4707 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 4708 } 4709 4710 @Test testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate()4711 public void testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate() { 4712 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, 4713 "testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate", "group", false); 4714 mService.addNotification(r); 4715 4716 NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0, 4717 "testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate", null, false); 4718 update.getNotification().flags = FLAG_AUTO_CANCEL; 4719 mService.addEnqueuedNotification(update); 4720 NotificationManagerService.PostNotificationRunnable runnable = 4721 mService.new PostNotificationRunnable(update.getKey(), 4722 update.getSbn().getPackageName(), update.getUid(), 4723 mPostNotificationTrackerFactory.newTracker(null)); 4724 runnable.run(); 4725 waitForIdle(); 4726 4727 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); 4728 } 4729 4730 @Test testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate()4731 public void testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate() { 4732 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, 4733 "testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate", null, false); 4734 mService.addNotification(r); 4735 NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0, 4736 "testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate", null, false); 4737 update.getNotification().color = Color.BLACK; 4738 mService.addEnqueuedNotification(update); 4739 4740 NotificationManagerService.PostNotificationRunnable runnable = 4741 mService.new PostNotificationRunnable(update.getKey(), 4742 update.getSbn().getPackageName(), 4743 update.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 4744 runnable.run(); 4745 waitForIdle(); 4746 4747 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean()); 4748 } 4749 4750 @Test testDontAutogroupIfCritical()4751 public void testDontAutogroupIfCritical() throws Exception { 4752 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); 4753 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW); 4754 mService.addEnqueuedNotification(r); 4755 NotificationManagerService.PostNotificationRunnable runnable = 4756 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 4757 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 4758 runnable.run(); 4759 4760 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false); 4761 r.setCriticality(CriticalNotificationExtractor.CRITICAL); 4762 runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 4763 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 4764 mService.addEnqueuedNotification(r); 4765 4766 runnable.run(); 4767 waitForIdle(); 4768 4769 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean()); 4770 } 4771 4772 @Test testNoNotificationDuringSetupPermission()4773 public void testNoNotificationDuringSetupPermission() throws Exception { 4774 mContext.getTestablePermissions().setPermission( 4775 android.Manifest.permission.NOTIFICATION_DURING_SETUP, PERMISSION_GRANTED); 4776 Bundle extras = new Bundle(); 4777 extras.putBoolean(EXTRA_ALLOW_DURING_SETUP, true); 4778 Notification.Builder nb = new Notification.Builder(mContext, 4779 mTestNotificationChannel.getId()) 4780 .setContentTitle("foo") 4781 .addExtras(extras) 4782 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4783 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4784 "testNoNotificationDuringSetupPermission", mUid, 0, 4785 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4786 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4787 4788 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4789 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4790 waitForIdle(); 4791 4792 NotificationRecord posted = mService.findNotificationLocked( 4793 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4794 4795 assertTrue(posted.getNotification().extras.containsKey(EXTRA_ALLOW_DURING_SETUP)); 4796 } 4797 4798 @Test testNoFakeColorizedPermission()4799 public void testNoFakeColorizedPermission() throws Exception { 4800 mContext.getTestablePermissions().setPermission( 4801 android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_DENIED); 4802 Notification.Builder nb = new Notification.Builder(mContext, 4803 mTestNotificationChannel.getId()) 4804 .setContentTitle("foo") 4805 .setColorized(true).setColor(Color.WHITE) 4806 .setFlag(FLAG_CAN_COLORIZE, true) 4807 .setSmallIcon(android.R.drawable.sym_def_app_icon); 4808 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4809 "testNoFakeColorizedPermission", mUid, 0, 4810 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4811 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4812 4813 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4814 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4815 waitForIdle(); 4816 4817 NotificationRecord posted = mService.findNotificationLocked( 4818 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4819 4820 assertFalse(posted.getNotification().isColorized()); 4821 } 4822 4823 @Test testMediaStyleRemote_hasPermission()4824 public void testMediaStyleRemote_hasPermission() throws RemoteException { 4825 String deviceName = "device"; 4826 mContext.getTestablePermissions().setPermission( 4827 android.Manifest.permission.MEDIA_CONTENT_CONTROL, PERMISSION_GRANTED); 4828 Notification.MediaStyle style = new Notification.MediaStyle(); 4829 style.setRemotePlaybackInfo(deviceName, 0, null); 4830 Notification.Builder nb = new Notification.Builder(mContext, 4831 mTestNotificationChannel.getId()) 4832 .setStyle(style); 4833 4834 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4835 "testMediaStyleRemoteHasPermission", mUid, 0, 4836 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4837 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4838 4839 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4840 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4841 waitForIdle(); 4842 4843 NotificationRecord posted = mService.findNotificationLocked( 4844 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4845 Bundle extras = posted.getNotification().extras; 4846 4847 assertTrue(extras.containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); 4848 assertEquals(deviceName, extras.getString(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); 4849 } 4850 4851 @Test testMediaStyleRemote_noPermission()4852 public void testMediaStyleRemote_noPermission() throws RemoteException { 4853 String deviceName = "device"; 4854 mContext.getTestablePermissions().setPermission( 4855 android.Manifest.permission.MEDIA_CONTENT_CONTROL, PERMISSION_DENIED); 4856 Notification.MediaStyle style = new Notification.MediaStyle(); 4857 style.setRemotePlaybackInfo(deviceName, 0, null); 4858 Notification.Builder nb = new Notification.Builder(mContext, 4859 mTestNotificationChannel.getId()) 4860 .setStyle(style); 4861 4862 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4863 "testMediaStyleRemoteNoPermission", mUid, 0, 4864 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4865 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4866 4867 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4868 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4869 waitForIdle(); 4870 4871 NotificationRecord posted = mService.findNotificationLocked( 4872 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4873 4874 assertFalse(posted.getNotification().extras 4875 .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); 4876 assertFalse(posted.getNotification().extras 4877 .containsKey(Notification.EXTRA_MEDIA_REMOTE_ICON)); 4878 assertFalse(posted.getNotification().extras 4879 .containsKey(Notification.EXTRA_MEDIA_REMOTE_INTENT)); 4880 } 4881 4882 @Test testCustomMediaStyleRemote_noPermission()4883 public void testCustomMediaStyleRemote_noPermission() throws RemoteException { 4884 String deviceName = "device"; 4885 when(mPackageManager.checkPermission( 4886 eq(android.Manifest.permission.MEDIA_CONTENT_CONTROL), any(), anyInt())) 4887 .thenReturn(PERMISSION_DENIED); 4888 Notification.DecoratedMediaCustomViewStyle style = 4889 new Notification.DecoratedMediaCustomViewStyle(); 4890 style.setRemotePlaybackInfo(deviceName, 0, null); 4891 Notification.Builder nb = new Notification.Builder(mContext, 4892 mTestNotificationChannel.getId()) 4893 .setStyle(style); 4894 4895 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4896 "testCustomMediaStyleRemoteNoPermission", mUid, 0, 4897 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4898 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4899 4900 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4901 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4902 waitForIdle(); 4903 4904 NotificationRecord posted = mService.findNotificationLocked( 4905 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4906 4907 assertFalse(posted.getNotification().extras 4908 .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); 4909 assertFalse(posted.getNotification().extras 4910 .containsKey(Notification.EXTRA_MEDIA_REMOTE_ICON)); 4911 assertFalse(posted.getNotification().extras 4912 .containsKey(Notification.EXTRA_MEDIA_REMOTE_INTENT)); 4913 } 4914 4915 @Test testSubstituteAppName_hasPermission()4916 public void testSubstituteAppName_hasPermission() throws RemoteException { 4917 String subName = "Substitute Name"; 4918 mContext.getTestablePermissions().setPermission( 4919 android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME, PERMISSION_GRANTED); 4920 Bundle extras = new Bundle(); 4921 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, subName); 4922 Notification.Builder nb = new Notification.Builder(mContext, 4923 mTestNotificationChannel.getId()) 4924 .addExtras(extras); 4925 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4926 "testSubstituteAppNamePermission", mUid, 0, 4927 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4928 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4929 4930 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4931 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4932 waitForIdle(); 4933 NotificationRecord posted = mService.findNotificationLocked( 4934 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4935 4936 assertTrue(posted.getNotification().extras 4937 .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)); 4938 assertEquals(posted.getNotification().extras 4939 .getString(Notification.EXTRA_SUBSTITUTE_APP_NAME), subName); 4940 } 4941 4942 @Test testSubstituteAppName_noPermission()4943 public void testSubstituteAppName_noPermission() throws RemoteException { 4944 mContext.getTestablePermissions().setPermission( 4945 android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME, PERMISSION_DENIED); 4946 Bundle extras = new Bundle(); 4947 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, "Substitute Name"); 4948 Notification.Builder nb = new Notification.Builder(mContext, 4949 mTestNotificationChannel.getId()) 4950 .addExtras(extras); 4951 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 4952 "testSubstituteAppNamePermission", mUid, 0, 4953 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 4954 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4955 4956 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 4957 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 4958 waitForIdle(); 4959 NotificationRecord posted = mService.findNotificationLocked( 4960 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); 4961 4962 assertFalse(posted.getNotification().extras 4963 .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)); 4964 } 4965 4966 @Test testGetNotificationCountLocked()4967 public void testGetNotificationCountLocked() { 4968 String sampleTagToExclude = null; 4969 int sampleIdToExclude = 0; 4970 for (int i = 0; i < 20; i++) { 4971 NotificationRecord r = 4972 generateNotificationRecord(mTestNotificationChannel, i, null, false); 4973 mService.addEnqueuedNotification(r); 4974 4975 } 4976 for (int i = 0; i < 20; i++) { 4977 NotificationRecord r = 4978 generateNotificationRecord(mTestNotificationChannel, i, null, false); 4979 mService.addNotification(r); 4980 sampleTagToExclude = r.getSbn().getTag(); 4981 sampleIdToExclude = i; 4982 } 4983 4984 // another package 4985 Notification n = 4986 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 4987 .setSmallIcon(android.R.drawable.sym_def_app_icon) 4988 .build(); 4989 4990 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0, 4991 n, UserHandle.getUserHandleForUid(mUid), null, 0); 4992 NotificationRecord otherPackage = 4993 new NotificationRecord(mContext, sbn, mTestNotificationChannel); 4994 mService.addEnqueuedNotification(otherPackage); 4995 mService.addNotification(otherPackage); 4996 4997 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match 4998 // anything that's currently enqueued or posted 4999 int userId = mUserId; 5000 assertEquals(40, 5001 mService.getNotificationCount(PKG, userId, 0, null)); 5002 assertEquals(40, 5003 mService.getNotificationCount(PKG, userId, 0, "tag2")); 5004 5005 // return all for package "a" - "banana" tag isn't used 5006 assertEquals(2, 5007 mService.getNotificationCount("a", userId, 0, "banana")); 5008 5009 // exclude a known notification - it's excluded from only the posted list, not enqueued 5010 assertEquals(39, mService.getNotificationCount( 5011 PKG, userId, sampleIdToExclude, sampleTagToExclude)); 5012 } 5013 5014 @Test testAddAutogroup_requestsSort()5015 public void testAddAutogroup_requestsSort() throws Exception { 5016 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5017 mService.addNotification(r); 5018 mService.addAutogroupKeyLocked(r.getKey()); 5019 5020 verify(mRankingHandler, times(1)).requestSort(); 5021 } 5022 5023 @Test testRemoveAutogroup_requestsSort()5024 public void testRemoveAutogroup_requestsSort() throws Exception { 5025 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5026 r.setOverrideGroupKey("TEST"); 5027 mService.addNotification(r); 5028 mService.removeAutogroupKeyLocked(r.getKey()); 5029 5030 verify(mRankingHandler, times(1)).requestSort(); 5031 } 5032 5033 @Test testReaddAutogroup_noSort()5034 public void testReaddAutogroup_noSort() throws Exception { 5035 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5036 r.setOverrideGroupKey("TEST"); 5037 mService.addNotification(r); 5038 mService.addAutogroupKeyLocked(r.getKey()); 5039 5040 verify(mRankingHandler, never()).requestSort(); 5041 } 5042 5043 @Test testHandleRankingSort_sendsUpdateOnSignalExtractorChange()5044 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception { 5045 mService.setPreferencesHelper(mPreferencesHelper); 5046 NotificationManagerService.WorkerHandler handler = mock( 5047 NotificationManagerService.WorkerHandler.class); 5048 mService.setHandler(handler); 5049 5050 Map<String, Answer> answers = getSignalExtractorSideEffects(); 5051 for (String message : answers.keySet()) { 5052 mService.clearNotifications(); 5053 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5054 mService.addNotification(r); 5055 5056 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r); 5057 5058 mService.handleRankingSort(); 5059 } 5060 verify(handler, times(answers.size())).scheduleSendRankingUpdate(); 5061 } 5062 5063 @Test testHandleRankingSort_noUpdateWhenNoSignalChange()5064 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception { 5065 mService.setRankingHelper(mRankingHelper); 5066 NotificationManagerService.WorkerHandler handler = mock( 5067 NotificationManagerService.WorkerHandler.class); 5068 mService.setHandler(handler); 5069 5070 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5071 mService.addNotification(r); 5072 5073 mService.handleRankingSort(); 5074 verify(handler, never()).scheduleSendRankingUpdate(); 5075 } 5076 5077 @Test testReadPolicyXml_readApprovedServicesFromXml()5078 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception { 5079 final String upgradeXml = "<notification-policy version=\"1\">" 5080 + "<ranking></ranking>" 5081 + "<enabled_listeners>" 5082 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 5083 + "</enabled_listeners>" 5084 + "<enabled_assistants>" 5085 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 5086 + "</enabled_assistants>" 5087 + "<dnd_apps>" 5088 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" 5089 + "</dnd_apps>" 5090 + "</notification-policy>"; 5091 mService.readPolicyXml( 5092 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())), 5093 false, 5094 UserHandle.USER_ALL); 5095 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 5096 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 5097 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt()); 5098 5099 // numbers are inflated for setup 5100 verify(mListeners, times(1)).migrateToXml(); 5101 verify(mConditionProviders, times(1)).migrateToXml(); 5102 verify(mAssistants, times(1)).migrateToXml(); 5103 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary(); 5104 } 5105 5106 @Test testReadPolicyXml_readSnoozedNotificationsFromXml()5107 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception { 5108 final String upgradeXml = "<notification-policy version=\"1\">" 5109 + "<snoozed-notifications>></snoozed-notifications>" 5110 + "</notification-policy>"; 5111 mService.readPolicyXml( 5112 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())), 5113 false, 5114 UserHandle.USER_ALL); 5115 verify(mSnoozeHelper, times(1)).readXml(any(TypedXmlPullParser.class), anyLong()); 5116 } 5117 5118 @Test testReadPolicyXml_readApprovedServicesFromSettings()5119 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception { 5120 final String preupgradeXml = "<notification-policy version=\"1\">" 5121 + "<ranking></ranking>" 5122 + "</notification-policy>"; 5123 mService.readPolicyXml( 5124 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), 5125 false, 5126 UserHandle.USER_ALL); 5127 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt()); 5128 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt()); 5129 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt()); 5130 5131 // numbers are inflated for setup 5132 verify(mListeners, times(2)).migrateToXml(); 5133 verify(mConditionProviders, times(2)).migrateToXml(); 5134 verify(mAssistants, times(2)).migrateToXml(); 5135 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary(); 5136 } 5137 5138 @Test testReadPolicyXml_doesNotRestoreManagedServicesForCloneUser()5139 public void testReadPolicyXml_doesNotRestoreManagedServicesForCloneUser() throws Exception { 5140 final String policyXml = "<notification-policy version=\"1\">" 5141 + "<ranking></ranking>" 5142 + "<enabled_listeners>" 5143 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5144 + "</enabled_listeners>" 5145 + "<enabled_assistants>" 5146 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5147 + "</enabled_assistants>" 5148 + "<dnd_apps>" 5149 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5150 + "</dnd_apps>" 5151 + "</notification-policy>"; 5152 UserInfo ui = new UserInfo(); 5153 ui.id = 10; 5154 ui.userType = USER_TYPE_PROFILE_CLONE; 5155 when(mUmInternal.getUserInfo(10)).thenReturn(ui); 5156 mService.readPolicyXml( 5157 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())), 5158 true, 5159 10); 5160 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10)); 5161 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10)); 5162 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10)); 5163 } 5164 5165 @Test testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser()5166 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception { 5167 final String policyXml = "<notification-policy version=\"1\">" 5168 + "<ranking></ranking>" 5169 + "<enabled_listeners>" 5170 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5171 + "</enabled_listeners>" 5172 + "<enabled_assistants>" 5173 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5174 + "</enabled_assistants>" 5175 + "<dnd_apps>" 5176 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5177 + "</dnd_apps>" 5178 + "</notification-policy>"; 5179 UserInfo ui = new UserInfo(); 5180 ui.id = 10; 5181 ui.userType = USER_TYPE_PROFILE_MANAGED; 5182 when(mUmInternal.getUserInfo(10)).thenReturn(ui); 5183 mService.readPolicyXml( 5184 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())), 5185 true, 5186 10); 5187 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10)); 5188 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10)); 5189 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10)); 5190 } 5191 5192 @Test testReadPolicyXml_restoresManagedServicesForNonManagedUser()5193 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception { 5194 final String policyXml = "<notification-policy version=\"1\">" 5195 + "<ranking></ranking>" 5196 + "<enabled_listeners>" 5197 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5198 + "</enabled_listeners>" 5199 + "<enabled_assistants>" 5200 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5201 + "</enabled_assistants>" 5202 + "<dnd_apps>" 5203 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />" 5204 + "</dnd_apps>" 5205 + "</notification-policy>"; 5206 UserInfo ui = new UserInfo(); 5207 ui.id = 10; 5208 ui.userType = USER_TYPE_FULL_SECONDARY; 5209 when(mUmInternal.getUserInfo(10)).thenReturn(ui); 5210 mService.readPolicyXml( 5211 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())), 5212 true, 5213 10); 5214 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10)); 5215 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10)); 5216 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10)); 5217 } 5218 5219 @Test testLocaleChangedCallsUpdateDefaultZenModeRules()5220 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception { 5221 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 5222 mService.mZenModeHelper = mZenModeHelper; 5223 mService.mLocaleChangeReceiver.onReceive(mContext, 5224 new Intent(Intent.ACTION_LOCALE_CHANGED)); 5225 5226 verify(mZenModeHelper, times(1)).updateDefaultZenRules( 5227 anyInt(), anyBoolean()); 5228 } 5229 5230 @Test testBumpFGImportance_channelChangePreOApp()5231 public void testBumpFGImportance_channelChangePreOApp() throws Exception { 5232 String preOPkg = PKG_N_MR1; 5233 final ApplicationInfo legacy = new ApplicationInfo(); 5234 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 5235 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt())) 5236 .thenReturn(legacy); 5237 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt())) 5238 .thenReturn(Binder.getCallingUid()); 5239 getContext().setMockPackageManager(mPackageManagerClient); 5240 5241 Notification.Builder nb = new Notification.Builder(mContext, 5242 NotificationChannel.DEFAULT_CHANNEL_ID) 5243 .setContentTitle("foo") 5244 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5245 .setFlag(FLAG_FOREGROUND_SERVICE, true) 5246 .setPriority(Notification.PRIORITY_MIN); 5247 5248 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, 5249 "testBumpFGImportance_channelChangePreOApp", 5250 Binder.getCallingUid(), 0, nb.build(), 5251 UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0); 5252 5253 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(), 5254 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId()); 5255 waitForIdle(); 5256 5257 assertEquals(IMPORTANCE_LOW, 5258 mService.getNotificationRecord(sbn.getKey()).getImportance()); 5259 assertEquals(IMPORTANCE_DEFAULT, mBinderService.getPackageImportance( 5260 sbn.getPackageName())); 5261 5262 nb = new Notification.Builder(mContext) 5263 .setContentTitle("foo") 5264 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5265 .setFlag(FLAG_FOREGROUND_SERVICE, true) 5266 .setPriority(Notification.PRIORITY_MIN); 5267 5268 sbn = new StatusBarNotification(preOPkg, preOPkg, 9, 5269 "testBumpFGImportance_channelChangePreOApp", Binder.getCallingUid(), 5270 0, nb.build(), UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0); 5271 5272 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, 5273 "testBumpFGImportance_channelChangePreOApp", 5274 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 5275 waitForIdle(); 5276 assertEquals(IMPORTANCE_LOW, 5277 mService.getNotificationRecord(sbn.getKey()).getImportance()); 5278 5279 NotificationChannel defaultChannel = mBinderService.getNotificationChannel( 5280 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID); 5281 assertEquals(IMPORTANCE_LOW, defaultChannel.getImportance()); 5282 } 5283 5284 @Test testStats_updatedOnDirectReply()5285 public void testStats_updatedOnDirectReply() throws Exception { 5286 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5287 mService.addNotification(r); 5288 5289 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey()); 5290 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied()); 5291 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r)); 5292 5293 assertEquals(1, mNotificationRecordLogger.numCalls()); 5294 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DIRECT_REPLIED, 5295 mNotificationRecordLogger.event(0)); 5296 } 5297 5298 @Test testStats_updatedOnUserExpansion()5299 public void testStats_updatedOnUserExpansion() throws Exception { 5300 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5301 mService.addNotification(r); 5302 5303 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true, 5304 NOTIFICATION_LOCATION_UNKNOWN); 5305 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), 5306 eq(FLAG_FILTER_TYPE_ALERTING), eq(true), eq((true))); 5307 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 5308 5309 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false, 5310 NOTIFICATION_LOCATION_UNKNOWN); 5311 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), 5312 eq(FLAG_FILTER_TYPE_ALERTING), eq(true), eq((false))); 5313 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 5314 5315 assertEquals(2, mNotificationRecordLogger.numCalls()); 5316 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_OPEN_USER, 5317 mNotificationRecordLogger.event(0)); 5318 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_CLOSE_USER, 5319 mNotificationRecordLogger.event(1)); 5320 } 5321 5322 @Test testStats_notUpdatedOnAutoExpansion()5323 public void testStats_notUpdatedOnAutoExpansion() throws Exception { 5324 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5325 mService.addNotification(r); 5326 5327 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 5328 NOTIFICATION_LOCATION_UNKNOWN); 5329 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 5330 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), 5331 eq(FLAG_FILTER_TYPE_ALERTING), eq(false), eq((true))); 5332 5333 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false, 5334 NOTIFICATION_LOCATION_UNKNOWN); 5335 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded()); 5336 verify(mAssistants).notifyAssistantExpansionChangedLocked( 5337 eq(r.getSbn()), eq(FLAG_FILTER_TYPE_ALERTING), eq(false), eq((false))); 5338 } 5339 5340 @Test testStats_updatedOnViewSettings()5341 public void testStats_updatedOnViewSettings() throws Exception { 5342 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5343 mService.addNotification(r); 5344 5345 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey()); 5346 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings()); 5347 } 5348 5349 @Test testStats_updatedOnVisibilityChanged()5350 public void testStats_updatedOnVisibilityChanged() throws Exception { 5351 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5352 mService.addNotification(r); 5353 5354 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true); 5355 mService.mNotificationDelegate.onNotificationVisibilityChanged( 5356 new NotificationVisibility[] {nv}, new NotificationVisibility[]{}); 5357 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r), eq(true)); 5358 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen()); 5359 mService.mNotificationDelegate.onNotificationVisibilityChanged( 5360 new NotificationVisibility[] {}, new NotificationVisibility[]{nv}); 5361 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r), eq(false)); 5362 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen()); 5363 } 5364 5365 @Test testStats_dismissalSurface()5366 public void testStats_dismissalSurface() throws Exception { 5367 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5368 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5369 mService.addNotification(r); 5370 5371 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true); 5372 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(), 5373 r.getKey(), NotificationStats.DISMISSAL_AOD, 5374 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv); 5375 waitForIdle(); 5376 5377 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface()); 5378 5379 // Using mService.addNotification() does not generate a NotificationRecordLogger log, 5380 // so we only get the cancel notification. 5381 assertEquals(1, mNotificationRecordLogger.numCalls()); 5382 5383 assertEquals( 5384 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD, 5385 mNotificationRecordLogger.event(0)); 5386 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 5387 } 5388 5389 @Test testStats_dismissalSentiment()5390 public void testStats_dismissalSentiment() throws Exception { 5391 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5392 mService.addNotification(r); 5393 5394 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true); 5395 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(), 5396 r.getKey(), NotificationStats.DISMISSAL_AOD, 5397 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv); 5398 waitForIdle(); 5399 5400 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE, 5401 r.getStats().getDismissalSentiment()); 5402 } 5403 5404 @Test testTextChangedSet_forNewNotifs()5405 public void testTextChangedSet_forNewNotifs() throws Exception { 5406 NotificationRecord original = generateNotificationRecord(mTestNotificationChannel); 5407 mService.addEnqueuedNotification(original); 5408 5409 NotificationManagerService.PostNotificationRunnable runnable = 5410 mService.new PostNotificationRunnable(original.getKey(), 5411 original.getSbn().getPackageName(), 5412 original.getUid(), 5413 mPostNotificationTrackerFactory.newTracker(null)); 5414 runnable.run(); 5415 waitForIdle(); 5416 5417 assertTrue(original.isTextChanged()); 5418 } 5419 5420 @Test testVisuallyInterruptive_notSeen()5421 public void testVisuallyInterruptive_notSeen() throws Exception { 5422 NotificationRecord original = generateNotificationRecord(mTestNotificationChannel); 5423 mService.addNotification(original); 5424 5425 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, original.getSbn().getId(), 5426 original.getSbn().getTag(), mUid, 0, 5427 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 5428 .setContentTitle("new title").build(), 5429 UserHandle.getUserHandleForUid(mUid), null, 0); 5430 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 5431 mService.addEnqueuedNotification(update); 5432 5433 NotificationManagerService.PostNotificationRunnable runnable = 5434 mService.new PostNotificationRunnable(update.getKey(), 5435 update.getSbn().getPackageName(), 5436 update.getUid(), 5437 mPostNotificationTrackerFactory.newTracker(null)); 5438 runnable.run(); 5439 waitForIdle(); 5440 5441 assertFalse(update.isInterruptive()); 5442 } 5443 5444 @Test testApplyAdjustmentMultiUser()5445 public void testApplyAdjustmentMultiUser() throws Exception { 5446 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5447 mService.addNotification(r); 5448 NotificationManagerService.WorkerHandler handler = mock( 5449 NotificationManagerService.WorkerHandler.class); 5450 mService.setHandler(handler); 5451 5452 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false); 5453 5454 Bundle signals = new Bundle(); 5455 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5456 USER_SENTIMENT_NEGATIVE); 5457 Adjustment adjustment = new Adjustment( 5458 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5459 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 5460 5461 waitForIdle(); 5462 5463 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 5464 } 5465 5466 @Test testAssistantBlockingTriggersCancel()5467 public void testAssistantBlockingTriggersCancel() throws Exception { 5468 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5469 mService.addNotification(r); 5470 NotificationManagerService.WorkerHandler handler = mock( 5471 NotificationManagerService.WorkerHandler.class); 5472 mService.setHandler(handler); 5473 5474 Bundle signals = new Bundle(); 5475 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE); 5476 Adjustment adjustment = new Adjustment( 5477 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5478 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 5479 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 5480 5481 waitForIdle(); 5482 5483 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 5484 verify(handler, times(1)).scheduleCancelNotification(any()); 5485 } 5486 5487 @Test testApplyEnqueuedAdjustmentFromAssistant_singleUser()5488 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception { 5489 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5490 mService.addEnqueuedNotification(r); 5491 NotificationManagerService.WorkerHandler handler = mock( 5492 NotificationManagerService.WorkerHandler.class); 5493 mService.setHandler(handler); 5494 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5495 5496 Bundle signals = new Bundle(); 5497 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5498 USER_SENTIMENT_NEGATIVE); 5499 Adjustment adjustment = new Adjustment( 5500 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5501 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5502 5503 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment()); 5504 } 5505 5506 @Test testApplyEnqueuedAdjustmentFromAssistant_importance()5507 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception { 5508 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5509 mService.addEnqueuedNotification(r); 5510 NotificationManagerService.WorkerHandler handler = mock( 5511 NotificationManagerService.WorkerHandler.class); 5512 mService.setHandler(handler); 5513 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5514 5515 Bundle signals = new Bundle(); 5516 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW); 5517 Adjustment adjustment = new Adjustment( 5518 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5519 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5520 5521 assertEquals(IMPORTANCE_LOW, r.getImportance()); 5522 } 5523 5524 @Test testApplyEnqueuedAdjustmentFromAssistant_crossUser()5525 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception { 5526 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5527 mService.addEnqueuedNotification(r); 5528 NotificationManagerService.WorkerHandler handler = mock( 5529 NotificationManagerService.WorkerHandler.class); 5530 mService.setHandler(handler); 5531 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false); 5532 5533 Bundle signals = new Bundle(); 5534 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5535 USER_SENTIMENT_NEGATIVE); 5536 Adjustment adjustment = new Adjustment( 5537 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5538 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5539 5540 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment()); 5541 5542 waitForIdle(); 5543 5544 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate(); 5545 } 5546 5547 @Test testUserSentimentChangeTriggersUpdate()5548 public void testUserSentimentChangeTriggersUpdate() throws Exception { 5549 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5550 mService.addNotification(r); 5551 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5552 5553 Bundle signals = new Bundle(); 5554 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5555 USER_SENTIMENT_NEGATIVE); 5556 Adjustment adjustment = new Adjustment( 5557 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5558 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 5559 5560 waitForIdle(); 5561 5562 verify(mRankingHandler, timeout(300).times(1)).requestSort(); 5563 } 5564 5565 @Test testTooLateAdjustmentTriggersUpdate()5566 public void testTooLateAdjustmentTriggersUpdate() throws Exception { 5567 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5568 mService.addNotification(r); 5569 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5570 5571 Bundle signals = new Bundle(); 5572 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5573 USER_SENTIMENT_NEGATIVE); 5574 Adjustment adjustment = new Adjustment( 5575 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5576 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5577 5578 waitForIdle(); 5579 5580 verify(mRankingHandler, times(1)).requestSort(); 5581 } 5582 5583 @Test testApplyAdjustmentsLogged()5584 public void testApplyAdjustmentsLogged() throws Exception { 5585 NotificationManagerService.WorkerHandler handler = mock( 5586 NotificationManagerService.WorkerHandler.class); 5587 mService.setHandler(handler); 5588 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5589 5590 // Set up notifications that will be adjusted 5591 final NotificationRecord r1 = generateNotificationRecord( 5592 mTestNotificationChannel, 1, null, true); 5593 r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5594 mService.addNotification(r1); 5595 final NotificationRecord r2 = generateNotificationRecord( 5596 mTestNotificationChannel, 2, null, true); 5597 r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5598 mService.addNotification(r2); 5599 5600 // Third notification that's NOT adjusted, just to make sure that doesn't get spuriously 5601 // logged. 5602 final NotificationRecord r3 = generateNotificationRecord( 5603 mTestNotificationChannel, 3, null, true); 5604 r3.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5605 mService.addNotification(r3); 5606 5607 List<Adjustment> adjustments = new ArrayList<>(); 5608 5609 // Test an adjustment that's associated with a ranking change and one that's not 5610 Bundle signals1 = new Bundle(); 5611 signals1.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_HIGH); 5612 Adjustment adjustment1 = new Adjustment( 5613 r1.getSbn().getPackageName(), r1.getKey(), signals1, "", 5614 r1.getUser().getIdentifier()); 5615 adjustments.add(adjustment1); 5616 5617 // This one wouldn't trigger a ranking change, but should still trigger a log. 5618 Bundle signals2 = new Bundle(); 5619 signals2.putFloat(Adjustment.KEY_RANKING_SCORE, -0.5f); 5620 Adjustment adjustment2 = new Adjustment( 5621 r2.getSbn().getPackageName(), r2.getKey(), signals2, "", 5622 r2.getUser().getIdentifier()); 5623 adjustments.add(adjustment2); 5624 5625 mBinderService.applyAdjustmentsFromAssistant(null, adjustments); 5626 verify(mRankingHandler, times(1)).requestSort(); 5627 5628 // Actually apply the adjustments & recalculate importance when run 5629 doAnswer(invocationOnMock -> { 5630 ((NotificationRecord) invocationOnMock.getArguments()[0]) 5631 .applyAdjustments(); 5632 ((NotificationRecord) invocationOnMock.getArguments()[0]) 5633 .calculateImportance(); 5634 return null; 5635 }).when(mRankingHelper).extractSignals(any(NotificationRecord.class)); 5636 5637 // Now make sure that when the sort happens, we actually log the changes. 5638 mService.handleRankingSort(); 5639 5640 // Even though the ranking score change is not meant to trigger a ranking update, 5641 // during this process the package visibility & canShowBadge values are changing 5642 // in all notifications, so all 3 seem to trigger a ranking change. Here we check instead 5643 // that scheduleSendRankingUpdate is sent and that the relevant fields have been changed 5644 // accordingly to confirm the adjustments happened to the 2 relevant notifications. 5645 verify(handler, times(3)).scheduleSendRankingUpdate(); 5646 assertEquals(IMPORTANCE_HIGH, r1.getImportance()); 5647 assertTrue(r2.rankingScoreMatches(-0.5f)); 5648 assertEquals(2, mNotificationRecordLogger.numCalls()); 5649 assertEquals(NOTIFICATION_ADJUSTED, mNotificationRecordLogger.event(0)); 5650 assertEquals(NOTIFICATION_ADJUSTED, mNotificationRecordLogger.event(1)); 5651 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 5652 assertEquals(2, mNotificationRecordLogger.get(1).getInstanceId()); 5653 } 5654 5655 @Test testAdjustmentToImportanceNone_cancelsNotification()5656 public void testAdjustmentToImportanceNone_cancelsNotification() throws Exception { 5657 NotificationManagerService.WorkerHandler handler = mock( 5658 NotificationManagerService.WorkerHandler.class); 5659 mService.setHandler(handler); 5660 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5661 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); 5662 5663 // Set up notifications: r1 is adjusted, r2 is not 5664 final NotificationRecord r1 = generateNotificationRecord( 5665 mTestNotificationChannel, 1, null, true); 5666 r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5667 mService.addNotification(r1); 5668 final NotificationRecord r2 = generateNotificationRecord( 5669 mTestNotificationChannel, 2, null, true); 5670 r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 5671 mService.addNotification(r2); 5672 5673 // Test an adjustment that sets importance to none (meaning it's cancelling) 5674 Bundle signals1 = new Bundle(); 5675 signals1.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_NONE); 5676 Adjustment adjustment1 = new Adjustment( 5677 r1.getSbn().getPackageName(), r1.getKey(), signals1, "", 5678 r1.getUser().getIdentifier()); 5679 5680 mBinderService.applyAdjustmentFromAssistant(null, adjustment1); 5681 5682 // Actually apply the adjustments & recalculate importance when run 5683 doAnswer(invocationOnMock -> { 5684 ((NotificationRecord) invocationOnMock.getArguments()[0]) 5685 .applyAdjustments(); 5686 ((NotificationRecord) invocationOnMock.getArguments()[0]) 5687 .calculateImportance(); 5688 return null; 5689 }).when(mRankingHelper).extractSignals(any(NotificationRecord.class)); 5690 5691 // run the CancelNotificationRunnable when it happens 5692 ArgumentCaptor<NotificationManagerService.CancelNotificationRunnable> captor = 5693 ArgumentCaptor.forClass( 5694 NotificationManagerService.CancelNotificationRunnable.class); 5695 5696 verify(handler, times(1)).scheduleCancelNotification( 5697 captor.capture()); 5698 5699 // Run the runnable given to the cancel notification, and see if it logs properly 5700 NotificationManagerService.CancelNotificationRunnable runnable = captor.getValue(); 5701 runnable.run(); 5702 assertEquals(1, mNotificationRecordLogger.numCalls()); 5703 assertEquals( 5704 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_ASSISTANT, 5705 mNotificationRecordLogger.event(0)); 5706 } 5707 5708 @Test testEnqueuedAdjustmentAppliesAdjustments()5709 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception { 5710 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 5711 mService.addEnqueuedNotification(r); 5712 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5713 5714 Bundle signals = new Bundle(); 5715 signals.putInt(Adjustment.KEY_USER_SENTIMENT, 5716 USER_SENTIMENT_NEGATIVE); 5717 Adjustment adjustment = new Adjustment( 5718 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); 5719 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5720 5721 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment()); 5722 } 5723 5724 @Test testEnqueuedAdjustmentAppliesAdjustments_MultiNotifications()5725 public void testEnqueuedAdjustmentAppliesAdjustments_MultiNotifications() throws Exception { 5726 final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel); 5727 final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel); 5728 mService.addEnqueuedNotification(r1); 5729 mService.addEnqueuedNotification(r2); 5730 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); 5731 5732 Bundle signals = new Bundle(); 5733 signals.putInt(Adjustment.KEY_IMPORTANCE, 5734 IMPORTANCE_HIGH); 5735 Adjustment adjustment = new Adjustment( 5736 r1.getSbn().getPackageName(), r1.getKey(), signals, 5737 "", r1.getUser().getIdentifier()); 5738 5739 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); 5740 5741 assertEquals(IMPORTANCE_HIGH, r1.getImportance()); 5742 assertEquals(IMPORTANCE_HIGH, r2.getImportance()); 5743 } 5744 5745 @Test testRestore()5746 public void testRestore() throws Exception { 5747 int systemChecks = mService.countSystemChecks; 5748 mBinderService.applyRestore(null, USER_SYSTEM); 5749 assertEquals(1, mService.countSystemChecks - systemChecks); 5750 } 5751 5752 @Test testBackupEmptySound()5753 public void testBackupEmptySound() throws Exception { 5754 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); 5755 channel.setSound(Uri.EMPTY, null); 5756 5757 TypedXmlSerializer serializer = Xml.newFastSerializer(); 5758 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 5759 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 5760 channel.writeXmlForBackup(serializer, getContext()); 5761 5762 TypedXmlPullParser parser = Xml.newFastPullParser(); 5763 parser.setInput(new BufferedInputStream( 5764 new ByteArrayInputStream(baos.toByteArray())), null); 5765 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); 5766 restored.populateFromXmlForRestore(parser, true, getContext()); 5767 5768 assertNull(restored.getSound()); 5769 } 5770 5771 @Test testBackup()5772 public void testBackup() throws Exception { 5773 mService.setPreferencesHelper(mPreferencesHelper); 5774 int systemChecks = mService.countSystemChecks; 5775 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt())) 5776 .thenReturn(new ArraySet<>()); 5777 mBinderService.getBackupPayload(1); 5778 assertEquals(1, mService.countSystemChecks - systemChecks); 5779 } 5780 5781 @Test testEmptyVibration_noException()5782 public void testEmptyVibration_noException() throws Exception { 5783 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); 5784 channel.setVibrationPattern(new long[0]); 5785 5786 TypedXmlSerializer serializer = Xml.newFastSerializer(); 5787 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 5788 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 5789 channel.writeXml(serializer); 5790 } 5791 5792 @Test updateUriPermissions_update()5793 public void updateUriPermissions_update() throws Exception { 5794 NotificationChannel c = new NotificationChannel( 5795 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 5796 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT); 5797 Message message1 = new Message("", 0, ""); 5798 message1.setData("", 5799 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1)); 5800 Message message2 = new Message("", 1, ""); 5801 message2.setData("", 5802 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2)); 5803 5804 Notification.Builder nbA = new Notification.Builder(mContext, c.getId()) 5805 .setContentTitle("foo") 5806 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5807 .setStyle(new Notification.MessagingStyle("") 5808 .addMessage(message1) 5809 .addMessage(message2)); 5810 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification( 5811 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid), 5812 null, 0), c); 5813 5814 // First post means we grant access to both 5815 reset(mUgm); 5816 reset(mUgmInternal); 5817 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder()); 5818 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), 5819 USER_SYSTEM); 5820 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 5821 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt()); 5822 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 5823 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt()); 5824 5825 Notification.Builder nbB = new Notification.Builder(mContext, c.getId()) 5826 .setContentTitle("foo") 5827 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5828 .setStyle(new Notification.MessagingStyle("").addMessage(message2)); 5829 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG, 5830 PKG, 0, "tag", mUid, 0, nbB.build(), UserHandle.getUserHandleForUid(mUid), null, 0), 5831 c); 5832 5833 // Update means we drop access to first 5834 reset(mUgmInternal); 5835 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(), 5836 USER_SYSTEM); 5837 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), 5838 eq(message1.getDataUri()), anyInt(), anyInt(), eq(null), eq(-1)); 5839 5840 // Update back means we grant access to first again 5841 reset(mUgm); 5842 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(), 5843 USER_SYSTEM); 5844 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(), 5845 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt()); 5846 5847 // And update to empty means we drop everything 5848 reset(mUgmInternal); 5849 mService.updateUriPermissions(null, recordB, mContext.getPackageName(), 5850 USER_SYSTEM); 5851 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null), 5852 anyInt(), anyInt()); 5853 } 5854 5855 @Test updateUriPermissions_posterDoesNotOwnUri()5856 public void updateUriPermissions_posterDoesNotOwnUri() throws Exception { 5857 NotificationChannel c = new NotificationChannel( 5858 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 5859 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT); 5860 Message message1 = new Message("", 0, ""); 5861 message1.setData("", 5862 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1)); 5863 5864 Notification.Builder nbA = new Notification.Builder(mContext, c.getId()) 5865 .setContentTitle("foo") 5866 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5867 .setStyle(new Notification.MessagingStyle("") 5868 .addMessage(message1)); 5869 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification( 5870 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid), 5871 null, 0), c); 5872 5873 doThrow(new SecurityException("no access")).when(mUgm) 5874 .grantUriPermissionFromOwner( 5875 any(), anyInt(), any(), any(), anyInt(), anyInt(), anyInt()); 5876 5877 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder()); 5878 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), USER_SYSTEM); 5879 5880 // yay, no crash 5881 } 5882 5883 @Test testVisitUris()5884 public void testVisitUris() throws Exception { 5885 final Uri audioContents = Uri.parse("content://com.example/audio"); 5886 final Uri backgroundImage = Uri.parse("content://com.example/background"); 5887 final Icon smallIcon = Icon.createWithContentUri("content://media/small/icon"); 5888 final Icon largeIcon = Icon.createWithContentUri("content://media/large/icon"); 5889 final Icon personIcon1 = Icon.createWithContentUri("content://media/person1"); 5890 final Icon personIcon2 = Icon.createWithContentUri("content://media/person2"); 5891 final Icon personIcon3 = Icon.createWithContentUri("content://media/person3"); 5892 final Person person1 = new Person.Builder() 5893 .setName("Messaging Person") 5894 .setIcon(personIcon1) 5895 .build(); 5896 final Person person2 = new Person.Builder() 5897 .setName("People List Person 1") 5898 .setIcon(personIcon2) 5899 .build(); 5900 final Person person3 = new Person.Builder() 5901 .setName("People List Person 2") 5902 .setIcon(personIcon3) 5903 .build(); 5904 final Uri historyUri1 = Uri.parse("content://com.example/history1"); 5905 final Uri historyUri2 = Uri.parse("content://com.example/history2"); 5906 final RemoteInputHistoryItem historyItem1 = new RemoteInputHistoryItem(null, historyUri1, 5907 "a"); 5908 final RemoteInputHistoryItem historyItem2 = new RemoteInputHistoryItem(null, historyUri2, 5909 "b"); 5910 5911 Bundle extras = new Bundle(); 5912 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents); 5913 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString()); 5914 extras.putParcelable(Notification.EXTRA_MESSAGING_PERSON, person1); 5915 extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, 5916 new ArrayList<>(Arrays.asList(person2, person3))); 5917 extras.putParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS, 5918 new RemoteInputHistoryItem[]{historyItem1, historyItem2}); 5919 5920 Notification n = new Notification.Builder(mContext, "a") 5921 .setContentTitle("notification with uris") 5922 .setSmallIcon(smallIcon) 5923 .setLargeIcon(largeIcon) 5924 .addExtras(extras) 5925 .build(); 5926 5927 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 5928 n.visitUris(visitor); 5929 verify(visitor, times(1)).accept(eq(audioContents)); 5930 verify(visitor, times(1)).accept(eq(backgroundImage)); 5931 verify(visitor, times(1)).accept(eq(smallIcon.getUri())); 5932 verify(visitor, times(1)).accept(eq(largeIcon.getUri())); 5933 verify(visitor, times(1)).accept(eq(personIcon1.getUri())); 5934 verify(visitor, times(1)).accept(eq(personIcon2.getUri())); 5935 verify(visitor, times(1)).accept(eq(personIcon3.getUri())); 5936 verify(visitor, times(1)).accept(eq(historyUri1)); 5937 verify(visitor, times(1)).accept(eq(historyUri2)); 5938 } 5939 5940 @Test testVisitUris_publicVersion()5941 public void testVisitUris_publicVersion() throws Exception { 5942 final Icon smallIconPublic = Icon.createWithContentUri("content://media/small/icon"); 5943 final Icon largeIconPrivate = Icon.createWithContentUri("content://media/large/icon"); 5944 5945 Notification publicVersion = new Notification.Builder(mContext, "a") 5946 .setContentTitle("notification with uris") 5947 .setSmallIcon(smallIconPublic) 5948 .build(); 5949 Notification n = new Notification.Builder(mContext, "a") 5950 .setLargeIcon(largeIconPrivate) 5951 .setPublicVersion(publicVersion) 5952 .build(); 5953 5954 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 5955 n.visitUris(visitor); 5956 verify(visitor, times(1)).accept(eq(smallIconPublic.getUri())); 5957 verify(visitor, times(1)).accept(eq(largeIconPrivate.getUri())); 5958 } 5959 5960 @Test testVisitUris_audioContentsString()5961 public void testVisitUris_audioContentsString() throws Exception { 5962 final Uri audioContents = Uri.parse("content://com.example/audio"); 5963 5964 Bundle extras = new Bundle(); 5965 extras.putString(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents.toString()); 5966 5967 Notification n = new Notification.Builder(mContext, "a") 5968 .setContentTitle("notification with uris") 5969 .setSmallIcon(android.R.drawable.sym_def_app_icon) 5970 .addExtras(extras) 5971 .build(); 5972 5973 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 5974 n.visitUris(visitor); 5975 verify(visitor, times(1)).accept(eq(audioContents)); 5976 } 5977 5978 @Test testVisitUris_messagingStyle()5979 public void testVisitUris_messagingStyle() { 5980 final Icon personIcon1 = Icon.createWithContentUri("content://media/person1"); 5981 final Icon personIcon2 = Icon.createWithContentUri("content://media/person2"); 5982 final Icon personIcon3 = Icon.createWithContentUri("content://media/person3"); 5983 final Person person1 = new Person.Builder() 5984 .setName("Messaging Person 1") 5985 .setIcon(personIcon1) 5986 .build(); 5987 final Person person2 = new Person.Builder() 5988 .setName("Messaging Person 2") 5989 .setIcon(personIcon2) 5990 .build(); 5991 final Person person3 = new Person.Builder() 5992 .setName("Messaging Person 3") 5993 .setIcon(personIcon3) 5994 .build(); 5995 Icon shortcutIcon = Icon.createWithContentUri("content://media/shortcut"); 5996 5997 Notification.Builder builder = new Notification.Builder(mContext, "a") 5998 .setCategory(Notification.CATEGORY_MESSAGE) 5999 .setContentTitle("new message!") 6000 .setContentText("Conversation Notification") 6001 .setSmallIcon(android.R.drawable.sym_def_app_icon); 6002 Notification.MessagingStyle.Message message1 = new Notification.MessagingStyle.Message( 6003 "Marco?", System.currentTimeMillis(), person2); 6004 Notification.MessagingStyle.Message message2 = new Notification.MessagingStyle.Message( 6005 "Polo!", System.currentTimeMillis(), person3); 6006 Notification.MessagingStyle style = new Notification.MessagingStyle(person1) 6007 .addMessage(message1) 6008 .addMessage(message2) 6009 .setShortcutIcon(shortcutIcon); 6010 builder.setStyle(style); 6011 Notification n = builder.build(); 6012 6013 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 6014 n.visitUris(visitor); 6015 6016 verify(visitor, times(1)).accept(eq(shortcutIcon.getUri())); 6017 verify(visitor, times(1)).accept(eq(personIcon1.getUri())); 6018 verify(visitor, times(1)).accept(eq(personIcon2.getUri())); 6019 verify(visitor, times(1)).accept(eq(personIcon3.getUri())); 6020 } 6021 6022 @Test testVisitUris_callStyle()6023 public void testVisitUris_callStyle() { 6024 Icon personIcon = Icon.createWithContentUri("content://media/person"); 6025 Icon verificationIcon = Icon.createWithContentUri("content://media/verification"); 6026 Person callingPerson = new Person.Builder().setName("Someone") 6027 .setIcon(personIcon) 6028 .build(); 6029 PendingIntent hangUpIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 6030 PendingIntent.FLAG_IMMUTABLE); 6031 Notification n = new Notification.Builder(mContext, "a") 6032 .setStyle(Notification.CallStyle.forOngoingCall(callingPerson, hangUpIntent) 6033 .setVerificationIcon(verificationIcon)) 6034 .setContentTitle("Calling...") 6035 .setSmallIcon(android.R.drawable.sym_def_app_icon) 6036 .build(); 6037 6038 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 6039 n.visitUris(visitor); 6040 6041 verify(visitor, times(1)).accept(eq(personIcon.getUri())); 6042 verify(visitor, times(1)).accept(eq(verificationIcon.getUri())); 6043 } 6044 6045 @Test testVisitUris_styleExtrasWithoutStyle()6046 public void testVisitUris_styleExtrasWithoutStyle() { 6047 Notification notification = new Notification.Builder(mContext, "a") 6048 .setSmallIcon(android.R.drawable.sym_def_app_icon) 6049 .build(); 6050 6051 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle( 6052 personWithIcon("content://user")) 6053 .addHistoricMessage(new Notification.MessagingStyle.Message("Heyhey!", 6054 System.currentTimeMillis(), 6055 personWithIcon("content://historicalMessenger"))) 6056 .addMessage(new Notification.MessagingStyle.Message("Are you there", 6057 System.currentTimeMillis(), 6058 personWithIcon("content://messenger"))) 6059 .setShortcutIcon( 6060 Icon.createWithContentUri("content://conversationShortcut")); 6061 messagingStyle.addExtras(notification.extras); // Instead of Builder.setStyle(style). 6062 6063 Notification.CallStyle callStyle = Notification.CallStyle.forOngoingCall( 6064 personWithIcon("content://caller"), 6065 PendingIntent.getActivity(mContext, 0, new Intent(), 6066 PendingIntent.FLAG_IMMUTABLE)) 6067 .setVerificationIcon(Icon.createWithContentUri("content://callVerification")); 6068 callStyle.addExtras(notification.extras); // Same. 6069 6070 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 6071 notification.visitUris(visitor); 6072 6073 verify(visitor).accept(eq(Uri.parse("content://user"))); 6074 verify(visitor).accept(eq(Uri.parse("content://historicalMessenger"))); 6075 verify(visitor).accept(eq(Uri.parse("content://messenger"))); 6076 verify(visitor).accept(eq(Uri.parse("content://conversationShortcut"))); 6077 verify(visitor).accept(eq(Uri.parse("content://caller"))); 6078 verify(visitor).accept(eq(Uri.parse("content://callVerification"))); 6079 } 6080 personWithIcon(String iconUri)6081 private static Person personWithIcon(String iconUri) { 6082 return new Person.Builder() 6083 .setName("Mr " + iconUri) 6084 .setIcon(Icon.createWithContentUri(iconUri)) 6085 .build(); 6086 } 6087 6088 @Test testVisitUris_wearableExtender()6089 public void testVisitUris_wearableExtender() { 6090 Icon actionIcon = Icon.createWithContentUri("content://media/action"); 6091 Icon wearActionIcon = Icon.createWithContentUri("content://media/wearAction"); 6092 PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent(), 6093 PendingIntent.FLAG_IMMUTABLE); 6094 Notification n = new Notification.Builder(mContext, "a") 6095 .setSmallIcon(android.R.drawable.sym_def_app_icon) 6096 .addAction(new Notification.Action.Builder(actionIcon, "Hey!", intent).build()) 6097 .extend(new Notification.WearableExtender().addAction( 6098 new Notification.Action.Builder(wearActionIcon, "Wear!", intent).build())) 6099 .build(); 6100 6101 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 6102 n.visitUris(visitor); 6103 6104 verify(visitor).accept(eq(actionIcon.getUri())); 6105 verify(visitor).accept(eq(wearActionIcon.getUri())); 6106 } 6107 6108 @Test testSetNotificationPolicy_preP_setOldFields()6109 public void testSetNotificationPolicy_preP_setOldFields() { 6110 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6111 mService.mZenModeHelper = mZenModeHelper; 6112 NotificationManager.Policy userPolicy = 6113 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6114 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6115 6116 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6117 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 6118 6119 int expected = SUPPRESSED_EFFECT_BADGE 6120 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 6121 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS 6122 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 6123 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 6124 6125 assertEquals(expected, actual); 6126 } 6127 6128 @Test testSetNotificationPolicy_preP_setNewFields()6129 public void testSetNotificationPolicy_preP_setNewFields() { 6130 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6131 mService.mZenModeHelper = mZenModeHelper; 6132 NotificationManager.Policy userPolicy = 6133 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6134 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6135 6136 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6137 SUPPRESSED_EFFECT_NOTIFICATION_LIST); 6138 6139 int expected = SUPPRESSED_EFFECT_BADGE; 6140 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 6141 6142 assertEquals(expected, actual); 6143 } 6144 6145 @Test testSetNotificationPolicy_preP_setOldNewFields()6146 public void testSetNotificationPolicy_preP_setOldNewFields() { 6147 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6148 mService.mZenModeHelper = mZenModeHelper; 6149 NotificationManager.Policy userPolicy = 6150 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6151 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6152 6153 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6154 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 6155 6156 int expected = 6157 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK; 6158 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1); 6159 6160 assertEquals(expected, actual); 6161 } 6162 6163 @Test testSetNotificationPolicy_P_setOldFields()6164 public void testSetNotificationPolicy_P_setOldFields() { 6165 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6166 mService.mZenModeHelper = mZenModeHelper; 6167 NotificationManager.Policy userPolicy = 6168 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6169 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6170 6171 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6172 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 6173 6174 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 6175 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT 6176 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 6177 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 6178 6179 assertEquals(expected, actual); 6180 } 6181 6182 @Test testSetNotificationPolicy_P_setNewFields()6183 public void testSetNotificationPolicy_P_setNewFields() { 6184 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6185 mService.mZenModeHelper = mZenModeHelper; 6186 NotificationManager.Policy userPolicy = 6187 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6188 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6189 6190 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6191 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT 6192 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 6193 6194 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF 6195 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS 6196 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 6197 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 6198 6199 assertEquals(expected, actual); 6200 } 6201 6202 @Test testSetNotificationPolicy_P_setOldNewFields()6203 public void testSetNotificationPolicy_P_setOldNewFields() { 6204 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); 6205 mService.mZenModeHelper = mZenModeHelper; 6206 NotificationManager.Policy userPolicy = 6207 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE); 6208 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy); 6209 6210 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 6211 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 6212 6213 int expected = SUPPRESSED_EFFECT_STATUS_BAR; 6214 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 6215 6216 assertEquals(expected, actual); 6217 6218 appPolicy = new NotificationManager.Policy(0, 0, 0, 6219 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT 6220 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 6221 6222 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT 6223 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 6224 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P); 6225 6226 assertEquals(expected, actual); 6227 } 6228 6229 @Test testVisualDifference_foreground()6230 public void testVisualDifference_foreground() { 6231 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6232 .setContentTitle("foo"); 6233 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6234 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6235 NotificationRecord r1 = 6236 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6237 6238 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6239 .setFlag(FLAG_FOREGROUND_SERVICE, true) 6240 .setContentTitle("bar"); 6241 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6242 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6243 NotificationRecord r2 = 6244 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6245 6246 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6247 } 6248 6249 @Test testVisualDifference_diffTitle()6250 public void testVisualDifference_diffTitle() { 6251 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6252 .setContentTitle("foo"); 6253 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6254 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6255 NotificationRecord r1 = 6256 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6257 6258 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6259 .setContentTitle("bar"); 6260 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6261 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6262 NotificationRecord r2 = 6263 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6264 6265 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 6266 } 6267 6268 @Test testVisualDifference_inboxStyle()6269 public void testVisualDifference_inboxStyle() { 6270 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6271 .setStyle(new Notification.InboxStyle() 6272 .addLine("line1").addLine("line2")); 6273 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6274 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6275 NotificationRecord r1 = 6276 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6277 6278 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6279 .setStyle(new Notification.InboxStyle() 6280 .addLine("line1").addLine("line2_changed")); 6281 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6282 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6283 NotificationRecord r2 = 6284 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6285 6286 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed 6287 6288 Notification.Builder nb3 = new Notification.Builder(mContext, "") 6289 .setStyle(new Notification.InboxStyle() 6290 .addLine("line1")); 6291 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6292 nb3.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6293 NotificationRecord r3 = 6294 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class)); 6295 6296 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed 6297 6298 Notification.Builder nb4 = new Notification.Builder(mContext, "") 6299 .setStyle(new Notification.InboxStyle() 6300 .addLine("line1").addLine("line2").addLine("line3")); 6301 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6302 nb4.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6303 NotificationRecord r4 = 6304 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class)); 6305 6306 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed 6307 6308 Notification.Builder nb5 = new Notification.Builder(mContext, "") 6309 .setContentText("not an inbox"); 6310 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6311 nb5.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6312 NotificationRecord r5 = 6313 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class)); 6314 6315 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed 6316 } 6317 6318 @Test testVisualDifference_diffText()6319 public void testVisualDifference_diffText() { 6320 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6321 .setContentText("foo"); 6322 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6323 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6324 NotificationRecord r1 = 6325 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6326 6327 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6328 .setContentText("bar"); 6329 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6330 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6331 NotificationRecord r2 = 6332 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6333 6334 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 6335 } 6336 6337 @Test testVisualDifference_sameText()6338 public void testVisualDifference_sameText() { 6339 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6340 .setContentText("foo"); 6341 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6342 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6343 NotificationRecord r1 = 6344 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6345 6346 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6347 .setContentText("foo"); 6348 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6349 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6350 NotificationRecord r2 = 6351 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6352 6353 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6354 } 6355 6356 @Test testVisualDifference_sameTextButStyled()6357 public void testVisualDifference_sameTextButStyled() { 6358 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6359 .setContentText(Html.fromHtml("<b>foo</b>")); 6360 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6361 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6362 NotificationRecord r1 = 6363 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6364 6365 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6366 .setContentText(Html.fromHtml("<b>foo</b>")); 6367 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6368 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6369 NotificationRecord r2 = 6370 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6371 6372 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6373 } 6374 6375 @Test testVisualDifference_diffTextButStyled()6376 public void testVisualDifference_diffTextButStyled() { 6377 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6378 .setContentText(Html.fromHtml("<b>foo</b>")); 6379 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6380 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6381 NotificationRecord r1 = 6382 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6383 6384 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6385 .setContentText(Html.fromHtml("<b>bar</b>")); 6386 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6387 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6388 NotificationRecord r2 = 6389 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6390 6391 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 6392 } 6393 6394 @Test testVisualDifference_diffProgress()6395 public void testVisualDifference_diffProgress() { 6396 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6397 .setProgress(100, 90, false); 6398 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6399 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6400 NotificationRecord r1 = 6401 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6402 6403 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6404 .setProgress(100, 100, false); 6405 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6406 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6407 NotificationRecord r2 = 6408 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6409 6410 assertTrue(mService.isVisuallyInterruptive(r1, r2)); 6411 } 6412 6413 @Test testVisualDifference_diffProgressNotDone()6414 public void testVisualDifference_diffProgressNotDone() { 6415 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6416 .setProgress(100, 90, false); 6417 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6418 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6419 NotificationRecord r1 = 6420 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6421 6422 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6423 .setProgress(100, 91, false); 6424 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6425 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6426 NotificationRecord r2 = 6427 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6428 6429 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6430 } 6431 6432 @Test testVisualDifference_sameProgressStillDone()6433 public void testVisualDifference_sameProgressStillDone() { 6434 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6435 .setProgress(100, 100, false); 6436 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6437 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6438 NotificationRecord r1 = 6439 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6440 6441 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6442 .setProgress(100, 100, false); 6443 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6444 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6445 NotificationRecord r2 = 6446 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6447 6448 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6449 } 6450 6451 @Test testVisualDifference_summary()6452 public void testVisualDifference_summary() { 6453 Notification.Builder nb1 = new Notification.Builder(mContext, "") 6454 .setGroup("bananas") 6455 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 6456 .setContentText("foo"); 6457 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6458 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6459 NotificationRecord r1 = 6460 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class)); 6461 6462 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6463 .setGroup("bananas") 6464 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 6465 .setContentText("bar"); 6466 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6467 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6468 NotificationRecord r2 = 6469 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6470 6471 assertFalse(mService.isVisuallyInterruptive(r1, r2)); 6472 } 6473 6474 @Test testVisualDifference_summaryNewNotification()6475 public void testVisualDifference_summaryNewNotification() { 6476 Notification.Builder nb2 = new Notification.Builder(mContext, "") 6477 .setGroup("bananas") 6478 .setFlag(Notification.FLAG_GROUP_SUMMARY, true) 6479 .setContentText("bar"); 6480 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, 6481 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 6482 NotificationRecord r2 = 6483 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class)); 6484 6485 assertFalse(mService.isVisuallyInterruptive(null, r2)); 6486 } 6487 6488 @Test testVisualDifference_sameImages()6489 public void testVisualDifference_sameImages() { 6490 Icon large = Icon.createWithResource(mContext, 1); 6491 Notification n1 = new Notification.Builder(mContext, "channel") 6492 .setSmallIcon(1).setLargeIcon(large).build(); 6493 Notification n2 = new Notification.Builder(mContext, "channel") 6494 .setSmallIcon(1).setLargeIcon(large).build(); 6495 6496 NotificationRecord r1 = notificationToRecord(n1); 6497 NotificationRecord r2 = notificationToRecord(n2); 6498 6499 assertThat(mService.isVisuallyInterruptive(r1, r2)).isFalse(); 6500 } 6501 6502 @Test testVisualDifference_differentSmallImage()6503 public void testVisualDifference_differentSmallImage() { 6504 Icon large = Icon.createWithResource(mContext, 1); 6505 Notification n1 = new Notification.Builder(mContext, "channel") 6506 .setSmallIcon(1).setLargeIcon(large).build(); 6507 Notification n2 = new Notification.Builder(mContext, "channel") 6508 .setSmallIcon(2).setLargeIcon(large).build(); 6509 6510 NotificationRecord r1 = notificationToRecord(n1); 6511 NotificationRecord r2 = notificationToRecord(n2); 6512 6513 assertThat(mService.isVisuallyInterruptive(r1, r2)).isTrue(); 6514 } 6515 6516 @Test testVisualDifference_differentLargeImage()6517 public void testVisualDifference_differentLargeImage() { 6518 Icon large1 = Icon.createWithResource(mContext, 1); 6519 Icon large2 = Icon.createWithResource(mContext, 2); 6520 Notification n1 = new Notification.Builder(mContext, "channel") 6521 .setSmallIcon(1).setLargeIcon(large1).build(); 6522 Notification n2 = new Notification.Builder(mContext, "channel") 6523 .setSmallIcon(1).setLargeIcon(large2).build(); 6524 6525 NotificationRecord r1 = notificationToRecord(n1); 6526 NotificationRecord r2 = notificationToRecord(n2); 6527 6528 assertThat(mService.isVisuallyInterruptive(r1, r2)).isTrue(); 6529 } 6530 notificationToRecord(Notification n)6531 private NotificationRecord notificationToRecord(Notification n) { 6532 return new NotificationRecord( 6533 mContext, 6534 new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, n, 6535 UserHandle.getUserHandleForUid(mUid), null, 0), 6536 mock(NotificationChannel.class)); 6537 } 6538 6539 @Test testHideAndUnhideNotificationsOnSuspendedPackageBroadcast()6540 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() { 6541 // post 2 notification from this package 6542 final NotificationRecord notif1 = generateNotificationRecord( 6543 mTestNotificationChannel, 1, null, true); 6544 final NotificationRecord notif2 = generateNotificationRecord( 6545 mTestNotificationChannel, 2, null, false); 6546 mService.addNotification(notif1); 6547 mService.addNotification(notif2); 6548 6549 // on broadcast, hide the 2 notifications 6550 simulatePackageSuspendBroadcast(true, PKG, notif1.getUid()); 6551 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class); 6552 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 6553 assertEquals(2, captorHide.getValue().size()); 6554 6555 // on broadcast, unhide the 2 notifications 6556 simulatePackageSuspendBroadcast(false, PKG, notif1.getUid()); 6557 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class); 6558 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 6559 assertEquals(2, captorUnhide.getValue().size()); 6560 } 6561 6562 @Test testNoNotificationsHiddenOnSuspendedPackageBroadcast()6563 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() { 6564 // post 2 notification from this package 6565 final NotificationRecord notif1 = generateNotificationRecord( 6566 mTestNotificationChannel, 1, null, true); 6567 final NotificationRecord notif2 = generateNotificationRecord( 6568 mTestNotificationChannel, 2, null, false); 6569 mService.addNotification(notif1); 6570 mService.addNotification(notif2); 6571 6572 // on broadcast, nothing is hidden since no notifications are of package "test_package" 6573 simulatePackageSuspendBroadcast(true, "test_package", notif1.getUid()); 6574 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 6575 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 6576 assertEquals(0, captor.getValue().size()); 6577 } 6578 6579 @Test testNotificationFromDifferentUserHidden()6580 public void testNotificationFromDifferentUserHidden() { 6581 // post 2 notification from this package 6582 final NotificationRecord notif1 = generateNotificationRecord( 6583 mTestNotificationChannel, 1, null, true); 6584 final NotificationRecord notif2 = generateNotificationRecord( 6585 mTestNotificationChannel, 2, null, false); 6586 mService.addNotification(notif1); 6587 mService.addNotification(notif2); 6588 6589 // on broadcast, nothing is hidden since no notifications are of user 10 with package PKG 6590 simulatePackageSuspendBroadcast(true, PKG, 10); 6591 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 6592 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 6593 assertEquals(0, captor.getValue().size()); 6594 } 6595 6596 @Test testHideAndUnhideNotificationsOnDistractingPackageBroadcast()6597 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() { 6598 // Post 2 notifications from 2 packages 6599 NotificationRecord pkgA = new NotificationRecord(mContext, 6600 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 6601 mService.addNotification(pkgA); 6602 NotificationRecord pkgB = new NotificationRecord(mContext, 6603 generateSbn("b", 1001, 9, 0), mTestNotificationChannel); 6604 mService.addNotification(pkgB); 6605 6606 // on broadcast, hide one of the packages 6607 simulatePackageDistractionBroadcast( 6608 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"}, 6609 new int[] {1000}); 6610 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class); 6611 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 6612 assertEquals(1, captorHide.getValue().size()); 6613 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName()); 6614 6615 // on broadcast, unhide the package 6616 simulatePackageDistractionBroadcast( 6617 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"}, 6618 new int[] {1000}); 6619 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class); 6620 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 6621 assertEquals(1, captorUnhide.getValue().size()); 6622 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName()); 6623 } 6624 6625 @Test testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg()6626 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() { 6627 // Post 2 notifications from 2 packages 6628 NotificationRecord pkgA = new NotificationRecord(mContext, 6629 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 6630 mService.addNotification(pkgA); 6631 NotificationRecord pkgB = new NotificationRecord(mContext, 6632 generateSbn("b", 1001, 9, 0), mTestNotificationChannel); 6633 mService.addNotification(pkgB); 6634 6635 // on broadcast, hide one of the packages 6636 simulatePackageDistractionBroadcast( 6637 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"}, 6638 new int[] {1000, 1001}); 6639 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class); 6640 6641 // should be called only once. 6642 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture()); 6643 assertEquals(2, captorHide.getValue().size()); 6644 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName()); 6645 assertEquals("b", captorHide.getValue().get(1).getSbn().getPackageName()); 6646 6647 // on broadcast, unhide the package 6648 simulatePackageDistractionBroadcast( 6649 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"}, 6650 new int[] {1000, 1001}); 6651 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class); 6652 6653 // should be called only once. 6654 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture()); 6655 assertEquals(2, captorUnhide.getValue().size()); 6656 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName()); 6657 assertEquals("b", captorUnhide.getValue().get(1).getSbn().getPackageName()); 6658 } 6659 6660 @Test testNoNotificationsHiddenOnDistractingPackageBroadcast()6661 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() { 6662 // post notification from this package 6663 final NotificationRecord notif1 = generateNotificationRecord( 6664 mTestNotificationChannel, 1, null, true); 6665 mService.addNotification(notif1); 6666 6667 // on broadcast, nothing is hidden since no notifications are of package "test_package" 6668 simulatePackageDistractionBroadcast( 6669 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"}, 6670 new int[]{notif1.getUid()}); 6671 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class); 6672 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture()); 6673 assertEquals(0, captor.getValue().size()); 6674 } 6675 6676 @Test testCanUseManagedServicesNullPkg()6677 public void testCanUseManagedServicesNullPkg() { 6678 assertEquals(true, mService.canUseManagedServices(null, 0, null)); 6679 } 6680 6681 6682 @Test testCanUseManagedServicesNoValidPkg()6683 public void testCanUseManagedServicesNoValidPkg() { 6684 assertEquals(true, mService.canUseManagedServices("d", 0, null)); 6685 } 6686 6687 @Test testCanUseManagedServices_hasPermission()6688 public void testCanUseManagedServices_hasPermission() throws Exception { 6689 when(mPackageManager.checkPermission("perm", "pkg", 0)) 6690 .thenReturn(PackageManager.PERMISSION_GRANTED); 6691 6692 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm")); 6693 } 6694 6695 @Test testCanUseManagedServices_noPermission()6696 public void testCanUseManagedServices_noPermission() throws Exception { 6697 when(mPackageManager.checkPermission("perm", "pkg", 0)) 6698 .thenReturn(PackageManager.PERMISSION_DENIED); 6699 6700 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm")); 6701 } 6702 6703 @Test testCanUseManagedServices_permDoesNotMatter()6704 public void testCanUseManagedServices_permDoesNotMatter() { 6705 assertEquals(true, mService.canUseManagedServices("pkg", 0, null)); 6706 } 6707 6708 @Test testOnNotificationVisibilityChanged_triggersInterruptionUsageStat()6709 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() { 6710 final NotificationRecord r = generateNotificationRecord( 6711 mTestNotificationChannel, 1, null, true); 6712 r.setTextChanged(true); 6713 mService.addNotification(r); 6714 6715 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[] 6716 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}, 6717 new NotificationVisibility[]{}); 6718 6719 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt()); 6720 } 6721 6722 @Test testOnNotificationVisibilityChanged_triggersVisibilityLog()6723 public void testOnNotificationVisibilityChanged_triggersVisibilityLog() { 6724 final NotificationRecord r = generateNotificationRecord( 6725 mTestNotificationChannel, 1, null, true); 6726 r.setTextChanged(true); 6727 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); 6728 mService.addNotification(r); 6729 6730 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[] 6731 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}, 6732 new NotificationVisibility[]{}); 6733 6734 assertEquals(1, mNotificationRecordLogger.numCalls()); 6735 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN, 6736 mNotificationRecordLogger.event(0)); 6737 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); 6738 6739 mService.mNotificationDelegate.onNotificationVisibilityChanged( 6740 new NotificationVisibility[]{}, 6741 new NotificationVisibility[] 6742 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)} 6743 ); 6744 6745 assertEquals(2, mNotificationRecordLogger.numCalls()); 6746 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE, 6747 mNotificationRecordLogger.event(1)); 6748 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); 6749 } 6750 6751 @Test testSetNotificationsShownFromListener_triggersInterruptionUsageStat()6752 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat() 6753 throws RemoteException { 6754 final NotificationRecord r = generateNotificationRecord( 6755 mTestNotificationChannel, 1, null, true); 6756 r.setTextChanged(true); 6757 mService.addNotification(r); 6758 6759 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()}); 6760 6761 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt()); 6762 } 6763 6764 @Test testSetNotificationsShownFromListener_protectsCrossUserInformation()6765 public void testSetNotificationsShownFromListener_protectsCrossUserInformation() 6766 throws RemoteException { 6767 Notification.Builder nb = new Notification.Builder( 6768 mContext, mTestNotificationChannel.getId()) 6769 .setContentTitle("foo") 6770 .setSmallIcon(android.R.drawable.sym_def_app_icon); 6771 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 6772 "tag" + System.currentTimeMillis(), UserHandle.PER_USER_RANGE, 0, 6773 nb.build(), UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE), 6774 null, 0); 6775 final NotificationRecord r = 6776 new NotificationRecord(mContext, sbn, mTestNotificationChannel); 6777 r.setTextChanged(true); 6778 mService.addNotification(r); 6779 6780 // no security exception! 6781 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()}); 6782 6783 verify(mAppUsageStats, never()).reportInterruptiveNotification( 6784 anyString(), anyString(), anyInt()); 6785 } 6786 6787 @Test testCancelNotificationsFromListener_protectsCrossUserInformation()6788 public void testCancelNotificationsFromListener_protectsCrossUserInformation() 6789 throws RemoteException { 6790 Notification.Builder nb = new Notification.Builder( 6791 mContext, mTestNotificationChannel.getId()) 6792 .setContentTitle("foo") 6793 .setSmallIcon(android.R.drawable.sym_def_app_icon); 6794 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 6795 "tag" + System.currentTimeMillis(), UserHandle.PER_USER_RANGE, 0, 6796 nb.build(), UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE), 6797 null, 0); 6798 final NotificationRecord r = 6799 new NotificationRecord(mContext, sbn, mTestNotificationChannel); 6800 r.setTextChanged(true); 6801 mService.addNotification(r); 6802 6803 // no security exception! 6804 mBinderService.cancelNotificationsFromListener(null, new String[] {r.getKey()}); 6805 6806 waitForIdle(); 6807 assertEquals(1, mService.getNotificationRecordCount()); 6808 } 6809 6810 @Test testMaybeRecordInterruptionLocked_doesNotRecordTwice()6811 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice() 6812 throws RemoteException { 6813 final NotificationRecord r = generateNotificationRecord( 6814 mTestNotificationChannel, 1, null, true); 6815 r.setInterruptive(true); 6816 mService.addNotification(r); 6817 6818 mService.maybeRecordInterruptionLocked(r); 6819 mService.maybeRecordInterruptionLocked(r); 6820 6821 verify(mAppUsageStats, times(1)).reportInterruptiveNotification( 6822 anyString(), anyString(), anyInt()); 6823 verify(mHistoryManager, times(1)).addNotification(any()); 6824 } 6825 6826 @Test testMaybeRecordInterruptionLocked_smallIconsRequiredForHistory()6827 public void testMaybeRecordInterruptionLocked_smallIconsRequiredForHistory() 6828 throws RemoteException { 6829 final NotificationRecord r = generateNotificationRecord( 6830 mTestNotificationChannel, 1, null, true); 6831 r.setInterruptive(true); 6832 r.getSbn().getNotification().setSmallIcon(null); 6833 mService.addNotification(r); 6834 6835 mService.maybeRecordInterruptionLocked(r); 6836 6837 verify(mAppUsageStats, times(1)).reportInterruptiveNotification( 6838 anyString(), anyString(), anyInt()); 6839 verify(mHistoryManager, never()).addNotification(any()); 6840 } 6841 6842 @Test testBubble()6843 public void testBubble() throws Exception { 6844 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE); 6845 assertFalse(mBinderService.areBubblesAllowed(PKG)); 6846 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid), 6847 BUBBLE_PREFERENCE_NONE); 6848 } 6849 6850 @Test testUserApprovedBubblesForPackageSelected()6851 public void testUserApprovedBubblesForPackageSelected() throws Exception { 6852 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_SELECTED); 6853 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid), 6854 BUBBLE_PREFERENCE_SELECTED); 6855 } 6856 6857 @Test testUserApprovedBubblesForPackageAll()6858 public void testUserApprovedBubblesForPackageAll() throws Exception { 6859 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_ALL); 6860 assertTrue(mBinderService.areBubblesAllowed(PKG)); 6861 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid), 6862 BUBBLE_PREFERENCE_ALL); 6863 } 6864 6865 @Test testUserRejectsBubblesForPackage()6866 public void testUserRejectsBubblesForPackage() throws Exception { 6867 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE); 6868 assertFalse(mBinderService.areBubblesAllowed(PKG)); 6869 } 6870 6871 @Test testAreBubblesEnabled()6872 public void testAreBubblesEnabled() throws Exception { 6873 Settings.Secure.putInt(mContext.getContentResolver(), 6874 Settings.Secure.NOTIFICATION_BUBBLES, 1); 6875 mService.mPreferencesHelper.updateBubblesEnabled(); 6876 assertTrue(mBinderService.areBubblesEnabled(UserHandle.getUserHandleForUid(mUid))); 6877 } 6878 6879 @Test testAreBubblesEnabled_false()6880 public void testAreBubblesEnabled_false() throws Exception { 6881 Settings.Secure.putInt(mContext.getContentResolver(), 6882 Settings.Secure.NOTIFICATION_BUBBLES, 0); 6883 mService.mPreferencesHelper.updateBubblesEnabled(); 6884 assertFalse(mBinderService.areBubblesEnabled(UserHandle.getUserHandleForUid(mUid))); 6885 } 6886 6887 @Test testAreBubblesEnabled_exception()6888 public void testAreBubblesEnabled_exception() throws Exception { 6889 try { 6890 assertTrue(mBinderService.areBubblesEnabled( 6891 UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE))); 6892 fail("Cannot call cross user without permission"); 6893 } catch (SecurityException e) { 6894 // pass 6895 } 6896 // cross user, with permission, no problem 6897 enableInteractAcrossUsers(); 6898 assertTrue(mBinderService.areBubblesEnabled( 6899 UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE))); 6900 } 6901 6902 @Test testIsCallerInstantApp_primaryUser()6903 public void testIsCallerInstantApp_primaryUser() throws Exception { 6904 ApplicationInfo info = new ApplicationInfo(); 6905 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 6906 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info); 6907 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 6908 6909 assertTrue(mService.isCallerInstantApp(45770, 0)); 6910 6911 info.privateFlags = 0; 6912 assertFalse(mService.isCallerInstantApp(575370, 0)); 6913 } 6914 6915 @Test testIsCallerInstantApp_secondaryUser()6916 public void testIsCallerInstantApp_secondaryUser() throws Exception { 6917 ApplicationInfo info = new ApplicationInfo(); 6918 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 6919 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(10))).thenReturn(info); 6920 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(null); 6921 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 6922 6923 assertTrue(mService.isCallerInstantApp(68638450, 10)); 6924 } 6925 6926 @Test testIsCallerInstantApp_userAllNotification()6927 public void testIsCallerInstantApp_userAllNotification() throws Exception { 6928 ApplicationInfo info = new ApplicationInfo(); 6929 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; 6930 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(USER_SYSTEM))) 6931 .thenReturn(info); 6932 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"}); 6933 6934 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL)); 6935 6936 info.privateFlags = 0; 6937 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL )); 6938 } 6939 6940 @Test testResolveNotificationUid_sameApp_nonSystemUser()6941 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception { 6942 ApplicationInfo info = new ApplicationInfo(); 6943 info.uid = Binder.getCallingUid(); 6944 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(10))).thenReturn(info); 6945 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(null); 6946 6947 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10); 6948 6949 assertEquals(info.uid, actualUid); 6950 } 6951 6952 @Test testResolveNotificationUid_sameApp()6953 public void testResolveNotificationUid_sameApp() throws Exception { 6954 ApplicationInfo info = new ApplicationInfo(); 6955 info.uid = Binder.getCallingUid(); 6956 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info); 6957 6958 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0); 6959 6960 assertEquals(info.uid, actualUid); 6961 } 6962 6963 @Test testResolveNotificationUid_sameAppDiffPackage()6964 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception { 6965 ApplicationInfo info = new ApplicationInfo(); 6966 info.uid = Binder.getCallingUid(); 6967 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info); 6968 6969 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0); 6970 6971 assertEquals(info.uid, actualUid); 6972 } 6973 6974 @Test testResolveNotificationUid_sameAppWrongUid()6975 public void testResolveNotificationUid_sameAppWrongUid() throws Exception { 6976 ApplicationInfo info = new ApplicationInfo(); 6977 info.uid = 1356347; 6978 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(info); 6979 6980 try { 6981 mService.resolveNotificationUid("caller", "caller", 9, 0); 6982 fail("Incorrect uid didn't throw security exception"); 6983 } catch (SecurityException e) { 6984 // yay 6985 } 6986 } 6987 6988 @Test testResolveNotificationUid_delegateAllowed()6989 public void testResolveNotificationUid_delegateAllowed() throws Exception { 6990 int expectedUid = 123; 6991 6992 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid); 6993 mService.setPreferencesHelper(mPreferencesHelper); 6994 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt())) 6995 .thenReturn(true); 6996 6997 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0)); 6998 } 6999 7000 @Test testResolveNotificationUid_androidAllowed()7001 public void testResolveNotificationUid_androidAllowed() throws Exception { 7002 int expectedUid = 123; 7003 7004 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid); 7005 // no delegate 7006 7007 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0)); 7008 } 7009 7010 @Test testPostFromAndroidForNonExistentPackage()7011 public void testPostFromAndroidForNonExistentPackage() throws Exception { 7012 final String notReal = "NOT REAL"; 7013 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow( 7014 PackageManager.NameNotFoundException.class); 7015 ApplicationInfo ai = new ApplicationInfo(); 7016 ai.uid = -1; 7017 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(ai); 7018 7019 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 7020 try { 7021 mInternalService.enqueueNotification(notReal, "android", 0, 0, 7022 "testPostFromAndroidForNonExistentPackage", 7023 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 7024 fail("can't post notifications for nonexistent packages, even if you exist"); 7025 } catch (SecurityException e) { 7026 // yay 7027 } 7028 } 7029 7030 @Test testCancelFromAndroidForNonExistentPackage()7031 public void testCancelFromAndroidForNonExistentPackage() throws Exception { 7032 final String notReal = "NOT REAL"; 7033 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow( 7034 PackageManager.NameNotFoundException.class); 7035 ApplicationInfo ai = new ApplicationInfo(); 7036 ai.uid = -1; 7037 when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(ai); 7038 7039 // unlike the post case, ignore instead of throwing 7040 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 7041 7042 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag", 7043 sbn.getId(), sbn.getUserId()); 7044 } 7045 7046 @Test testResolveNotificationUid_delegateNotAllowed()7047 public void testResolveNotificationUid_delegateNotAllowed() throws Exception { 7048 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123); 7049 // no delegate 7050 7051 try { 7052 mService.resolveNotificationUid("caller", "target", 9, 0); 7053 fail("Incorrect uid didn't throw security exception"); 7054 } catch (SecurityException e) { 7055 // yay 7056 } 7057 } 7058 7059 @Test testRemoveForegroundServiceFlagFromNotification_enqueued()7060 public void testRemoveForegroundServiceFlagFromNotification_enqueued() { 7061 when(mAmi.applyForegroundServiceNotification( 7062 any(), anyString(), anyInt(), anyString(), anyInt())) 7063 .thenReturn(SHOW_IMMEDIATELY); 7064 Notification n = new Notification.Builder(mContext, "").build(); 7065 n.flags |= FLAG_FOREGROUND_SERVICE; 7066 7067 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 7068 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7069 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7070 7071 mService.addEnqueuedNotification(r); 7072 7073 mInternalService.removeForegroundServiceFlagFromNotification( 7074 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 7075 7076 waitForIdle(); 7077 7078 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any()); 7079 } 7080 7081 @Test testRemoveForegroundServiceFlagFromNotification_posted()7082 public void testRemoveForegroundServiceFlagFromNotification_posted() { 7083 when(mAmi.applyForegroundServiceNotification( 7084 any(), anyString(), anyInt(), anyString(), anyInt())) 7085 .thenReturn(SHOW_IMMEDIATELY); 7086 Notification n = new Notification.Builder(mContext, "").build(); 7087 n.flags |= FLAG_FOREGROUND_SERVICE; 7088 7089 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 7090 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7091 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7092 7093 mService.addNotification(r); 7094 7095 mInternalService.removeForegroundServiceFlagFromNotification( 7096 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 7097 7098 waitForIdle(); 7099 7100 ArgumentCaptor<NotificationRecord> captor = 7101 ArgumentCaptor.forClass(NotificationRecord.class); 7102 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any()); 7103 7104 assertEquals(0, captor.getValue().getNotification().flags); 7105 } 7106 7107 @Test testCannotRemoveForegroundFlagWhenOverLimit_enqueued()7108 public void testCannotRemoveForegroundFlagWhenOverLimit_enqueued() { 7109 when(mAmi.applyForegroundServiceNotification( 7110 any(), anyString(), anyInt(), anyString(), anyInt())) 7111 .thenReturn(SHOW_IMMEDIATELY); 7112 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 7113 Notification n = new Notification.Builder(mContext, "").build(); 7114 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0, 7115 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7116 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7117 mService.addEnqueuedNotification(r); 7118 } 7119 Notification n = new Notification.Builder(mContext, "").build(); 7120 n.flags |= FLAG_FOREGROUND_SERVICE; 7121 7122 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 7123 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0, 7124 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7125 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7126 7127 mService.addEnqueuedNotification(r); 7128 7129 mInternalService.removeForegroundServiceFlagFromNotification( 7130 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 7131 7132 waitForIdle(); 7133 7134 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, 7135 mService.getNotificationRecordCount()); 7136 } 7137 7138 @Test testCannotRemoveForegroundFlagWhenOverLimit_posted()7139 public void testCannotRemoveForegroundFlagWhenOverLimit_posted() { 7140 when(mAmi.applyForegroundServiceNotification( 7141 any(), anyString(), anyInt(), anyString(), anyInt())) 7142 .thenReturn(SHOW_IMMEDIATELY); 7143 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 7144 Notification n = new Notification.Builder(mContext, "").build(); 7145 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0, 7146 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7147 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7148 mService.addNotification(r); 7149 } 7150 Notification n = new Notification.Builder(mContext, "").build(); 7151 n.flags |= FLAG_FOREGROUND_SERVICE; 7152 7153 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 7154 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0, 7155 n, UserHandle.getUserHandleForUid(mUid), null, 0); 7156 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7157 7158 mService.addNotification(r); 7159 7160 mInternalService.removeForegroundServiceFlagFromNotification( 7161 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 7162 7163 waitForIdle(); 7164 7165 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, 7166 mService.getNotificationRecordCount()); 7167 } 7168 7169 @Test testAllowForegroundCustomToasts()7170 public void testAllowForegroundCustomToasts() throws Exception { 7171 final String testPackage = "testPackageName"; 7172 assertEquals(0, mService.mToastQueue.size()); 7173 mService.isSystemUid = false; 7174 mService.isSystemAppId = false; 7175 setToastRateIsWithinQuota(true); 7176 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7177 7178 // package is not suspended 7179 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7180 .thenReturn(false); 7181 7182 // notifications from this package are blocked by the user 7183 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 7184 7185 setAppInForegroundForToasts(mUid, true); 7186 7187 // enqueue toast -> toast should still enqueue 7188 enqueueToast(testPackage, new TestableToastCallback()); 7189 assertEquals(1, mService.mToastQueue.size()); 7190 } 7191 7192 @Test testDisallowBackgroundCustomToasts()7193 public void testDisallowBackgroundCustomToasts() throws Exception { 7194 final String testPackage = "testPackageName"; 7195 assertEquals(0, mService.mToastQueue.size()); 7196 mService.isSystemUid = false; 7197 mService.isSystemAppId = false; 7198 setToastRateIsWithinQuota(true); 7199 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7200 7201 // package is not suspended 7202 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7203 .thenReturn(false); 7204 7205 setAppInForegroundForToasts(mUid, false); 7206 7207 // enqueue toast -> no toasts enqueued 7208 enqueueToast(testPackage, new TestableToastCallback()); 7209 assertEquals(0, mService.mToastQueue.size()); 7210 } 7211 7212 @Test testDontCallShowToastAgainOnTheSameCustomToast()7213 public void testDontCallShowToastAgainOnTheSameCustomToast() throws Exception { 7214 final String testPackage = "testPackageName"; 7215 assertEquals(0, mService.mToastQueue.size()); 7216 mService.isSystemUid = false; 7217 mService.isSystemAppId = false; 7218 setToastRateIsWithinQuota(true); 7219 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7220 7221 // package is not suspended 7222 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7223 .thenReturn(false); 7224 7225 setAppInForegroundForToasts(mUid, true); 7226 7227 Binder token = new Binder(); 7228 ITransientNotification callback = mock(ITransientNotification.class); 7229 INotificationManager nmService = (INotificationManager) mService.mService; 7230 7231 // first time trying to show the toast, showToast gets called 7232 enqueueToast(nmService, testPackage, token, callback); 7233 verify(callback, times(1)).show(any()); 7234 7235 // second time trying to show the same toast, showToast isn't called again (total number of 7236 // invocations stays at one) 7237 enqueueToast(nmService, testPackage, token, callback); 7238 verify(callback, times(1)).show(any()); 7239 } 7240 7241 @Test testToastRateLimiterWontPreventShowCallForCustomToastWhenInForeground()7242 public void testToastRateLimiterWontPreventShowCallForCustomToastWhenInForeground() 7243 throws Exception { 7244 final String testPackage = "testPackageName"; 7245 assertEquals(0, mService.mToastQueue.size()); 7246 mService.isSystemUid = false; 7247 mService.isSystemAppId = false; 7248 setToastRateIsWithinQuota(false); // rate limit reached 7249 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7250 7251 // package is not suspended 7252 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7253 .thenReturn(false); 7254 7255 setAppInForegroundForToasts(mUid, true); 7256 7257 Binder token = new Binder(); 7258 ITransientNotification callback = mock(ITransientNotification.class); 7259 INotificationManager nmService = (INotificationManager) mService.mService; 7260 7261 enqueueToast(nmService, testPackage, token, callback); 7262 verify(callback, times(1)).show(any()); 7263 } 7264 7265 @Test testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground()7266 public void testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground() 7267 throws Exception { 7268 final String testPackage = "testPackageName"; 7269 assertEquals(0, mService.mToastQueue.size()); 7270 mService.isSystemUid = false; 7271 mService.isSystemAppId = false; 7272 setToastRateIsWithinQuota(true); 7273 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7274 7275 // package is not suspended 7276 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7277 .thenReturn(false); 7278 7279 setAppInForegroundForToasts(mUid, true); 7280 7281 Binder token1 = new Binder(); 7282 Binder token2 = new Binder(); 7283 ITransientNotification callback1 = mock(ITransientNotification.class); 7284 ITransientNotification callback2 = mock(ITransientNotification.class); 7285 INotificationManager nmService = (INotificationManager) mService.mService; 7286 7287 enqueueToast(nmService, testPackage, token1, callback1); 7288 enqueueToast(nmService, testPackage, token2, callback2); 7289 7290 assertEquals(2, mService.mToastQueue.size()); // Both toasts enqueued. 7291 verify(callback1, times(1)).show(any()); // First toast shown. 7292 7293 setAppInForegroundForToasts(mUid, false); 7294 7295 mService.cancelToastLocked(0); // Remove the first toast, and show next. 7296 7297 assertEquals(0, mService.mToastQueue.size()); // Both toasts processed. 7298 verify(callback2, never()).show(any()); // Second toast was never shown. 7299 } 7300 7301 @Test testAllowForegroundTextToasts()7302 public void testAllowForegroundTextToasts() throws Exception { 7303 final String testPackage = "testPackageName"; 7304 assertEquals(0, mService.mToastQueue.size()); 7305 mService.isSystemUid = false; 7306 mService.isSystemAppId = false; 7307 setToastRateIsWithinQuota(true); 7308 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7309 7310 // package is not suspended 7311 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7312 .thenReturn(false); 7313 7314 setAppInForegroundForToasts(mUid, true); 7315 7316 // enqueue toast -> toast should still enqueue 7317 enqueueTextToast(testPackage, "Text"); 7318 assertEquals(1, mService.mToastQueue.size()); 7319 } 7320 7321 @Test testAllowBackgroundTextToasts()7322 public void testAllowBackgroundTextToasts() throws Exception { 7323 final String testPackage = "testPackageName"; 7324 assertEquals(0, mService.mToastQueue.size()); 7325 mService.isSystemUid = false; 7326 mService.isSystemAppId = false; 7327 setToastRateIsWithinQuota(true); 7328 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7329 7330 // package is not suspended 7331 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7332 .thenReturn(false); 7333 7334 setAppInForegroundForToasts(mUid, false); 7335 7336 // enqueue toast -> toast should still enqueue 7337 enqueueTextToast(testPackage, "Text"); 7338 assertEquals(1, mService.mToastQueue.size()); 7339 } 7340 7341 @Test testDontCallShowToastAgainOnTheSameTextToast()7342 public void testDontCallShowToastAgainOnTheSameTextToast() throws Exception { 7343 final String testPackage = "testPackageName"; 7344 assertEquals(0, mService.mToastQueue.size()); 7345 mService.isSystemUid = false; 7346 mService.isSystemAppId = false; 7347 setToastRateIsWithinQuota(true); 7348 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7349 7350 // package is not suspended 7351 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7352 .thenReturn(false); 7353 7354 setAppInForegroundForToasts(mUid, true); 7355 7356 Binder token = new Binder(); 7357 INotificationManager nmService = (INotificationManager) mService.mService; 7358 7359 // first time trying to show the toast, showToast gets called 7360 enqueueTextToast(testPackage, "Text"); 7361 verify(mStatusBar, times(1)) 7362 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt()); 7363 7364 // second time trying to show the same toast, showToast isn't called again (total number of 7365 // invocations stays at one) 7366 enqueueTextToast(testPackage, "Text"); 7367 verify(mStatusBar, times(1)) 7368 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt()); 7369 } 7370 7371 @Test testToastRateLimiterCanPreventShowCallForTextToast_whenInBackground()7372 public void testToastRateLimiterCanPreventShowCallForTextToast_whenInBackground() 7373 throws Exception { 7374 final String testPackage = "testPackageName"; 7375 assertEquals(0, mService.mToastQueue.size()); 7376 mService.isSystemUid = false; 7377 mService.isSystemAppId = false; 7378 setToastRateIsWithinQuota(false); // rate limit reached 7379 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7380 setAppInForegroundForToasts(mUid, false); 7381 7382 // package is not suspended 7383 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7384 .thenReturn(false); 7385 7386 Binder token = new Binder(); 7387 INotificationManager nmService = (INotificationManager) mService.mService; 7388 7389 enqueueTextToast(testPackage, "Text"); 7390 verify(mStatusBar, times(0)) 7391 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt()); 7392 } 7393 7394 @Test testToastRateLimiterWontPreventShowCallForTextToast_whenInForeground()7395 public void testToastRateLimiterWontPreventShowCallForTextToast_whenInForeground() 7396 throws Exception { 7397 final String testPackage = "testPackageName"; 7398 assertEquals(0, mService.mToastQueue.size()); 7399 mService.isSystemUid = false; 7400 mService.isSystemAppId = false; 7401 setToastRateIsWithinQuota(false); // rate limit reached 7402 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7403 setAppInForegroundForToasts(mUid, true); 7404 7405 // package is not suspended 7406 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7407 .thenReturn(false); 7408 7409 Binder token = new Binder(); 7410 INotificationManager nmService = (INotificationManager) mService.mService; 7411 7412 enqueueTextToast(testPackage, "Text"); 7413 verify(mStatusBar, times(1)) 7414 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt()); 7415 } 7416 7417 @Test testTextToastRateLimiterAllowsLimitAvoidanceWithPermission()7418 public void testTextToastRateLimiterAllowsLimitAvoidanceWithPermission() throws Exception { 7419 final String testPackage = "testPackageName"; 7420 assertEquals(0, mService.mToastQueue.size()); 7421 mService.isSystemUid = false; 7422 mService.isSystemAppId = false; 7423 setToastRateIsWithinQuota(false); // rate limit reached 7424 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, true); 7425 setAppInForegroundForToasts(mUid, false); 7426 7427 // package is not suspended 7428 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7429 .thenReturn(false); 7430 7431 Binder token = new Binder(); 7432 INotificationManager nmService = (INotificationManager) mService.mService; 7433 7434 enqueueTextToast(testPackage, "Text"); 7435 verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), 7436 anyInt()); 7437 } 7438 7439 @Test testRateLimitedToasts_windowsRemoved()7440 public void testRateLimitedToasts_windowsRemoved() throws Exception { 7441 final String testPackage = "testPackageName"; 7442 assertEquals(0, mService.mToastQueue.size()); 7443 mService.isSystemUid = false; 7444 mService.isSystemAppId = false; 7445 setToastRateIsWithinQuota(false); // rate limit reached 7446 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7447 setAppInForegroundForToasts(mUid, false); 7448 7449 // package is not suspended 7450 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7451 .thenReturn(false); 7452 7453 Binder token = new Binder(); 7454 INotificationManager nmService = (INotificationManager) mService.mService; 7455 7456 enqueueTextToast(testPackage, "Text"); 7457 7458 // window token was added when enqueued 7459 ArgumentCaptor<Binder> binderCaptor = 7460 ArgumentCaptor.forClass(Binder.class); 7461 verify(mWindowManagerInternal).addWindowToken(binderCaptor.capture(), 7462 eq(TYPE_TOAST), anyInt(), eq(null)); 7463 7464 // but never shown 7465 verify(mStatusBar, times(0)) 7466 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt()); 7467 7468 // and removed when rate limited 7469 verify(mWindowManagerInternal) 7470 .removeWindowToken(eq(binderCaptor.getValue()), eq(true), anyInt()); 7471 } 7472 7473 @Test backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast()7474 public void backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast() throws 7475 Exception { 7476 final String testPackage = "testPackageName"; 7477 assertEquals(0, mService.mToastQueue.size()); 7478 mService.isSystemUid = true; 7479 setToastRateIsWithinQuota(true); 7480 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7481 7482 // package is not suspended 7483 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7484 .thenReturn(false); 7485 7486 // notifications from this package are blocked by the user 7487 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 7488 7489 setAppInForegroundForToasts(mUid, false); 7490 7491 // enqueue toast -> toast should still enqueue 7492 enqueueToast(testPackage, new TestableToastCallback()); 7493 assertEquals(1, mService.mToastQueue.size()); 7494 verify(mAm).setProcessImportant(any(), anyInt(), eq(true), any()); 7495 } 7496 7497 @Test foregroundTextToast_callsSetProcessImportantAsNotForegroundForToast()7498 public void foregroundTextToast_callsSetProcessImportantAsNotForegroundForToast() throws 7499 Exception { 7500 final String testPackage = "testPackageName"; 7501 assertEquals(0, mService.mToastQueue.size()); 7502 mService.isSystemUid = false; 7503 mService.isSystemAppId = false; 7504 setToastRateIsWithinQuota(true); 7505 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7506 7507 // package is not suspended 7508 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7509 .thenReturn(false); 7510 7511 setAppInForegroundForToasts(mUid, true); 7512 7513 // enqueue toast -> toast should still enqueue 7514 enqueueTextToast(testPackage, "Text"); 7515 assertEquals(1, mService.mToastQueue.size()); 7516 verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any()); 7517 } 7518 7519 @Test backgroundTextToast_callsSetProcessImportantAsNotForegroundForToast()7520 public void backgroundTextToast_callsSetProcessImportantAsNotForegroundForToast() throws 7521 Exception { 7522 final String testPackage = "testPackageName"; 7523 assertEquals(0, mService.mToastQueue.size()); 7524 mService.isSystemUid = false; 7525 mService.isSystemAppId = false; 7526 setToastRateIsWithinQuota(true); 7527 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7528 7529 // package is not suspended 7530 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7531 .thenReturn(false); 7532 7533 setAppInForegroundForToasts(mUid, false); 7534 7535 // enqueue toast -> toast should still enqueue 7536 enqueueTextToast(testPackage, "Text"); 7537 assertEquals(1, mService.mToastQueue.size()); 7538 verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any()); 7539 } 7540 7541 @Test testTextToastsCallStatusBar()7542 public void testTextToastsCallStatusBar() throws Exception { 7543 allowTestPackageToToast(); 7544 7545 // enqueue toast -> no toasts enqueued 7546 enqueueTextToast(TEST_PACKAGE, "Text"); 7547 7548 verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY); 7549 } 7550 7551 @Test testTextToastsCallStatusBar_nonUiContext_defaultDisplay()7552 public void testTextToastsCallStatusBar_nonUiContext_defaultDisplay() 7553 throws Exception { 7554 allowTestPackageToToast(); 7555 7556 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, DEFAULT_DISPLAY); 7557 7558 verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY); 7559 } 7560 7561 @Test testTextToastsCallStatusBar_nonUiContext_secondaryDisplay()7562 public void testTextToastsCallStatusBar_nonUiContext_secondaryDisplay() 7563 throws Exception { 7564 allowTestPackageToToast(); 7565 mockIsUserVisible(SECONDARY_DISPLAY_ID, true); 7566 7567 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, SECONDARY_DISPLAY_ID); 7568 7569 verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID); 7570 } 7571 7572 @Test testTextToastsCallStatusBar_visibleBgUsers_uiContext_defaultDisplay()7573 public void testTextToastsCallStatusBar_visibleBgUsers_uiContext_defaultDisplay() 7574 throws Exception { 7575 mockIsVisibleBackgroundUsersSupported(true); 7576 mockDisplayAssignedToUser(SECONDARY_DISPLAY_ID); 7577 allowTestPackageToToast(); 7578 7579 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ true, DEFAULT_DISPLAY); 7580 7581 verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY); 7582 7583 } 7584 7585 @Test testTextToastsCallStatusBar_visibleBgUsers_uiContext_secondaryDisplay()7586 public void testTextToastsCallStatusBar_visibleBgUsers_uiContext_secondaryDisplay() 7587 throws Exception { 7588 mockIsVisibleBackgroundUsersSupported(true); 7589 mockIsUserVisible(SECONDARY_DISPLAY_ID, true); 7590 mockDisplayAssignedToUser(INVALID_DISPLAY); // make sure it's not used 7591 allowTestPackageToToast(); 7592 7593 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ true, SECONDARY_DISPLAY_ID); 7594 7595 verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID); 7596 } 7597 7598 @Test testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_defaultDisplay()7599 public void testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_defaultDisplay() 7600 throws Exception { 7601 mockIsVisibleBackgroundUsersSupported(true); 7602 mockIsUserVisible(SECONDARY_DISPLAY_ID, true); 7603 mockDisplayAssignedToUser(SECONDARY_DISPLAY_ID); 7604 allowTestPackageToToast(); 7605 7606 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, DEFAULT_DISPLAY); 7607 7608 verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID); 7609 } 7610 7611 @Test testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_secondaryDisplay()7612 public void testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_secondaryDisplay() 7613 throws Exception { 7614 mockIsVisibleBackgroundUsersSupported(true); 7615 mockIsUserVisible(SECONDARY_DISPLAY_ID, true); 7616 mockDisplayAssignedToUser(INVALID_DISPLAY); // make sure it's not used 7617 allowTestPackageToToast(); 7618 7619 enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, SECONDARY_DISPLAY_ID); 7620 7621 verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID); 7622 } 7623 7624 @Test testTextToastsCallStatusBar_userNotVisibleOnDisplay()7625 public void testTextToastsCallStatusBar_userNotVisibleOnDisplay() throws Exception { 7626 final String testPackage = "testPackageName"; 7627 assertEquals(0, mService.mToastQueue.size()); 7628 mService.isSystemUid = false; 7629 mService.isSystemAppId = false; 7630 setToastRateIsWithinQuota(true); 7631 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7632 mockIsUserVisible(DEFAULT_DISPLAY, false); 7633 7634 // package is not suspended 7635 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) 7636 .thenReturn(false); 7637 7638 // enqueue toast -> no toasts enqueued 7639 enqueueTextToast(testPackage, "Text"); 7640 verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), 7641 anyInt()); 7642 assertEquals(0, mService.mToastQueue.size()); 7643 } 7644 7645 @Test testDisallowToastsFromSuspendedPackages()7646 public void testDisallowToastsFromSuspendedPackages() throws Exception { 7647 final String testPackage = "testPackageName"; 7648 assertEquals(0, mService.mToastQueue.size()); 7649 mService.isSystemUid = false; 7650 mService.isSystemAppId = false; 7651 setToastRateIsWithinQuota(true); 7652 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7653 7654 // package is suspended 7655 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7656 .thenReturn(true); 7657 7658 // notifications from this package are NOT blocked by the user 7659 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 7660 7661 // enqueue toast -> no toasts enqueued 7662 enqueueToast(testPackage, new TestableToastCallback()); 7663 verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), 7664 anyInt()); 7665 assertEquals(0, mService.mToastQueue.size()); 7666 } 7667 7668 @Test testDisallowToastsFromBlockedApps()7669 public void testDisallowToastsFromBlockedApps() throws Exception { 7670 final String testPackage = "testPackageName"; 7671 assertEquals(0, mService.mToastQueue.size()); 7672 mService.isSystemUid = false; 7673 mService.isSystemAppId = false; 7674 setToastRateIsWithinQuota(true); 7675 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7676 7677 // package is not suspended 7678 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7679 .thenReturn(false); 7680 7681 // notifications from this package are blocked by the user 7682 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 7683 7684 setAppInForegroundForToasts(mUid, false); 7685 7686 // enqueue toast -> no toasts enqueued 7687 enqueueToast(testPackage, new TestableToastCallback()); 7688 assertEquals(0, mService.mToastQueue.size()); 7689 } 7690 7691 @Test testAlwaysAllowSystemToasts()7692 public void testAlwaysAllowSystemToasts() throws Exception { 7693 final String testPackage = "testPackageName"; 7694 assertEquals(0, mService.mToastQueue.size()); 7695 mService.isSystemUid = true; 7696 setToastRateIsWithinQuota(true); 7697 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7698 7699 // package is suspended 7700 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7701 .thenReturn(true); 7702 7703 // notifications from this package ARE blocked by the user 7704 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 7705 7706 setAppInForegroundForToasts(mUid, false); 7707 7708 // enqueue toast -> system toast can still be enqueued 7709 enqueueToast(testPackage, new TestableToastCallback()); 7710 assertEquals(1, mService.mToastQueue.size()); 7711 } 7712 7713 @Test testLimitNumberOfQueuedToastsFromPackage()7714 public void testLimitNumberOfQueuedToastsFromPackage() throws Exception { 7715 final String testPackage = "testPackageName"; 7716 assertEquals(0, mService.mToastQueue.size()); 7717 mService.isSystemUid = false; 7718 mService.isSystemAppId = false; 7719 setToastRateIsWithinQuota(true); 7720 setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); 7721 7722 // package is not suspended 7723 when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId)) 7724 .thenReturn(false); 7725 7726 INotificationManager nmService = (INotificationManager) mService.mService; 7727 7728 // Trying to quickly enqueue more toast than allowed. 7729 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS + 1; i++) { 7730 enqueueTextToast(testPackage, "Text"); 7731 } 7732 // Only allowed number enqueued, rest ignored. 7733 assertEquals(NotificationManagerService.MAX_PACKAGE_TOASTS, mService.mToastQueue.size()); 7734 } 7735 setAppInForegroundForToasts(int uid, boolean inForeground)7736 private void setAppInForegroundForToasts(int uid, boolean inForeground) { 7737 int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE; 7738 when(mActivityManager.getUidImportance(mUid)).thenReturn(importance); 7739 when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground); 7740 } 7741 setToastRateIsWithinQuota(boolean isWithinQuota)7742 private void setToastRateIsWithinQuota(boolean isWithinQuota) { 7743 when(mToastRateLimiter.isWithinQuota( 7744 anyInt(), 7745 anyString(), 7746 eq(NotificationManagerService.TOAST_QUOTA_TAG))) 7747 .thenReturn(isWithinQuota); 7748 } 7749 setIfPackageHasPermissionToAvoidToastRateLimiting( String pkg, boolean hasPermission)7750 private void setIfPackageHasPermissionToAvoidToastRateLimiting( 7751 String pkg, boolean hasPermission) throws Exception { 7752 when(mPackageManager.checkPermission(android.Manifest.permission.UNLIMITED_TOASTS, 7753 pkg, mUserId)) 7754 .thenReturn(hasPermission ? PERMISSION_GRANTED : PERMISSION_DENIED); 7755 } 7756 7757 @Test testOnPanelRevealedAndHidden()7758 public void testOnPanelRevealedAndHidden() { 7759 int items = 5; 7760 mService.mNotificationDelegate.onPanelRevealed(false, items); 7761 verify(mAssistants, times(1)).onPanelRevealed(eq(items)); 7762 7763 mService.mNotificationDelegate.onPanelHidden(); 7764 verify(mAssistants, times(1)).onPanelHidden(); 7765 7766 assertEquals(2, mNotificationRecordLogger.numCalls()); 7767 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_OPEN, 7768 mNotificationRecordLogger.event(0)); 7769 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_CLOSE, 7770 mNotificationRecordLogger.event(1)); 7771 } 7772 7773 @Test testOnNotificationSmartReplySent()7774 public void testOnNotificationSmartReplySent() { 7775 final int replyIndex = 2; 7776 final String reply = "Hello"; 7777 final boolean modifiedBeforeSending = true; 7778 final boolean generatedByAssistant = true; 7779 7780 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7781 r.setSuggestionsGeneratedByAssistant(generatedByAssistant); 7782 mService.addNotification(r); 7783 7784 mService.mNotificationDelegate.onNotificationSmartReplySent( 7785 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN, 7786 modifiedBeforeSending); 7787 verify(mAssistants).notifyAssistantSuggestedReplySent( 7788 eq(r.getSbn()), eq(FLAG_FILTER_TYPE_ALERTING), eq(reply), eq(generatedByAssistant)); 7789 assertEquals(1, mNotificationRecordLogger.numCalls()); 7790 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED, 7791 mNotificationRecordLogger.event(0)); 7792 } 7793 7794 @Test testOnNotificationActionClick()7795 public void testOnNotificationActionClick() { 7796 final int actionIndex = 2; 7797 final Notification.Action action = 7798 new Notification.Action.Builder(null, "text", PendingIntent.getActivity( 7799 mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build(); 7800 final boolean generatedByAssistant = false; 7801 7802 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7803 mService.addNotification(r); 7804 7805 NotificationVisibility notificationVisibility = 7806 NotificationVisibility.obtain(r.getKey(), 1, 2, true); 7807 mService.mNotificationDelegate.onNotificationActionClick( 7808 10, 10, r.getKey(), actionIndex, action, notificationVisibility, 7809 generatedByAssistant); 7810 verify(mAssistants).notifyAssistantActionClicked( 7811 eq(r), eq(action), eq(generatedByAssistant)); 7812 7813 assertEquals(1, mNotificationRecordLogger.numCalls()); 7814 assertEquals( 7815 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ACTION_CLICKED_2, 7816 mNotificationRecordLogger.event(0)); 7817 } 7818 7819 @Test testOnAssistantNotificationActionClick()7820 public void testOnAssistantNotificationActionClick() { 7821 final int actionIndex = 1; 7822 final Notification.Action action = 7823 new Notification.Action.Builder(null, "text", PendingIntent.getActivity( 7824 mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build(); 7825 final boolean generatedByAssistant = true; 7826 7827 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7828 mService.addNotification(r); 7829 7830 NotificationVisibility notificationVisibility = 7831 NotificationVisibility.obtain(r.getKey(), 1, 2, true); 7832 mService.mNotificationDelegate.onNotificationActionClick( 7833 10, 10, r.getKey(), actionIndex, action, notificationVisibility, 7834 generatedByAssistant); 7835 verify(mAssistants).notifyAssistantActionClicked( 7836 eq(r), eq(action), eq(generatedByAssistant)); 7837 7838 assertEquals(1, mNotificationRecordLogger.numCalls()); 7839 assertEquals( 7840 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ASSIST_ACTION_CLICKED_1, 7841 mNotificationRecordLogger.event(0)); 7842 } 7843 7844 @Test testLogSmartSuggestionsVisible_triggerOnExpandAndVisible()7845 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() { 7846 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7847 mService.addNotification(r); 7848 7849 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 7850 NOTIFICATION_LOCATION_UNKNOWN); 7851 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] { 7852 NotificationVisibility.obtain(r.getKey(), 0, 0, true) 7853 }; 7854 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility, 7855 new NotificationVisibility[0]); 7856 7857 assertEquals(1, mService.countLogSmartSuggestionsVisible); 7858 } 7859 7860 @Test testLogSmartSuggestionsVisible_noTriggerOnExpand()7861 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() { 7862 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7863 mService.addNotification(r); 7864 7865 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true, 7866 NOTIFICATION_LOCATION_UNKNOWN); 7867 7868 assertEquals(0, mService.countLogSmartSuggestionsVisible); 7869 } 7870 7871 @Test testLogSmartSuggestionsVisible_noTriggerOnVisible()7872 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() { 7873 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7874 mService.addNotification(r); 7875 7876 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{ 7877 NotificationVisibility.obtain(r.getKey(), 0, 0, true) 7878 }; 7879 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility, 7880 new NotificationVisibility[0]); 7881 7882 assertEquals(0, mService.countLogSmartSuggestionsVisible); 7883 } 7884 7885 @Test testReportSeen_delegated()7886 public void testReportSeen_delegated() { 7887 Notification.Builder nb = 7888 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 7889 .setContentTitle("foo") 7890 .setSmallIcon(android.R.drawable.sym_def_app_icon); 7891 7892 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0, 7893 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 7894 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7895 7896 mService.reportSeen(r); 7897 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt()); 7898 7899 } 7900 7901 @Test testReportSeen_notDelegated()7902 public void testReportSeen_notDelegated() { 7903 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7904 7905 mService.reportSeen(r); 7906 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt()); 7907 } 7908 7909 @Test testNotificationStats_notificationError()7910 public void testNotificationStats_notificationError() { 7911 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 7912 mService.addNotification(r); 7913 7914 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.getSbn().getId(), 7915 r.getSbn().getTag(), mUid, 0, 7916 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(), 7917 UserHandle.getUserHandleForUid(mUid), null, 0); 7918 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 7919 mService.addEnqueuedNotification(update); 7920 assertNull(update.getSbn().getNotification().getSmallIcon()); 7921 7922 NotificationManagerService.PostNotificationRunnable runnable = 7923 mService.new PostNotificationRunnable(update.getKey(), r.getSbn().getPackageName(), 7924 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 7925 runnable.run(); 7926 waitForIdle(); 7927 7928 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class); 7929 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture()); 7930 assertNotNull(captor.getValue()); 7931 } 7932 7933 @Test testCanNotifyAsUser_crossUser()7934 public void testCanNotifyAsUser_crossUser() throws Exception { 7935 // same user no problem 7936 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId()); 7937 7938 // cross user, no permission, problem 7939 try { 7940 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); 7941 fail("Should not be callable cross user without cross user permission"); 7942 } catch (SecurityException e) { 7943 // good 7944 } 7945 7946 // cross user, with permission, no problem 7947 enableInteractAcrossUsers(); 7948 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); 7949 } 7950 7951 @Test testGetNotificationChannels_crossUser()7952 public void testGetNotificationChannels_crossUser() throws Exception { 7953 // same user no problem 7954 mBinderService.getNotificationChannels("src", "target", mContext.getUserId()); 7955 7956 // cross user, no permission, problem 7957 try { 7958 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); 7959 fail("Should not be callable cross user without cross user permission"); 7960 } catch (SecurityException e) { 7961 // good 7962 } 7963 7964 // cross user, with permission, no problem 7965 enableInteractAcrossUsers(); 7966 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); 7967 } 7968 7969 @Test setDefaultAssistantForUser_fromConfigXml()7970 public void setDefaultAssistantForUser_fromConfigXml() { 7971 clearDeviceConfig(); 7972 ComponentName xmlConfig = new ComponentName("config", "xml"); 7973 ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig)); 7974 when(mResources 7975 .getString( 7976 com.android.internal.R.string.config_defaultAssistantAccessComponent)) 7977 .thenReturn(xmlConfig.flattenToString()); 7978 when(mContext.getResources()).thenReturn(mResources); 7979 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt())) 7980 .thenReturn(components); 7981 when(mAssistants.getDefaultComponents()) 7982 .thenReturn(components); 7983 mService.setNotificationAssistantAccessGrantedCallback( 7984 mNotificationAssistantAccessGrantedCallback); 7985 7986 7987 mService.setDefaultAssistantForUser(0); 7988 7989 verify(mNotificationAssistantAccessGrantedCallback) 7990 .onGranted(eq(xmlConfig), eq(0), eq(true), eq(false)); 7991 } 7992 7993 @Test setDefaultAssistantForUser_fromDeviceConfig()7994 public void setDefaultAssistantForUser_fromDeviceConfig() { 7995 ComponentName xmlConfig = new ComponentName("xml", "config"); 7996 ComponentName deviceConfig = new ComponentName("device", "config"); 7997 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString()); 7998 when(mResources 7999 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent)) 8000 .thenReturn(xmlConfig.flattenToString()); 8001 when(mContext.getResources()).thenReturn(mResources); 8002 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt())) 8003 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig))); 8004 when(mAssistants.getDefaultComponents()) 8005 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig))); 8006 mService.setNotificationAssistantAccessGrantedCallback( 8007 mNotificationAssistantAccessGrantedCallback); 8008 8009 mService.setDefaultAssistantForUser(0); 8010 8011 verify(mNotificationAssistantAccessGrantedCallback) 8012 .onGranted(eq(deviceConfig), eq(0), eq(true), eq(false)); 8013 } 8014 8015 @Test setDefaultAssistantForUser_deviceConfigInvalid()8016 public void setDefaultAssistantForUser_deviceConfigInvalid() { 8017 ComponentName xmlConfig = new ComponentName("xml", "config"); 8018 ComponentName deviceConfig = new ComponentName("device", "config"); 8019 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString()); 8020 when(mResources 8021 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent)) 8022 .thenReturn(xmlConfig.flattenToString()); 8023 when(mContext.getResources()).thenReturn(mResources); 8024 // Only xmlConfig is valid, deviceConfig is not. 8025 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0))) 8026 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig))); 8027 when(mAssistants.getDefaultComponents()) 8028 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig))); 8029 mService.setNotificationAssistantAccessGrantedCallback( 8030 mNotificationAssistantAccessGrantedCallback); 8031 8032 mService.setDefaultAssistantForUser(0); 8033 8034 verify(mNotificationAssistantAccessGrantedCallback) 8035 .onGranted(eq(xmlConfig), eq(0), eq(true), eq(false)); 8036 } 8037 8038 @Test clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne()8039 public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException { 8040 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners = 8041 generateResetComponentValues(); 8042 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners); 8043 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>(); 8044 ComponentName deviceConfig1 = new ComponentName("device", "config1"); 8045 ComponentName deviceConfig2 = new ComponentName("device", "config2"); 8046 changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2))); 8047 changes.put(false, new ArrayList()); 8048 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes); 8049 mService.getBinderService().clearData("device", 0, false); 8050 verify(mAssistants, times(1)) 8051 .setPackageOrComponentEnabled( 8052 eq("device/config2"), 8053 eq(0), eq(true), eq(false)); 8054 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 8055 eq("device"), eq(0), eq(false), eq(true)); 8056 } 8057 8058 @Test testNASSettingUpgrade_userSetNull()8059 public void testNASSettingUpgrade_userSetNull() throws RemoteException { 8060 ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component1"); 8061 TestableNotificationManagerService service = spy(mService); 8062 int userId = 11; 8063 setUsers(new int[]{userId}); 8064 when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId}); 8065 setNASMigrationDone(false, userId); 8066 when(mAssistants.getDefaultFromConfig()) 8067 .thenReturn(newDefaultComponent); 8068 when(mAssistants.getAllowedComponents(anyInt())) 8069 .thenReturn(new ArrayList<>()); 8070 when(mAssistants.hasUserSet(userId)).thenReturn(true); 8071 8072 service.migrateDefaultNAS(); 8073 assertTrue(service.isNASMigrationDone(userId)); 8074 verify(mAssistants, times(1)).clearDefaults(); 8075 } 8076 8077 @Test testNASSettingUpgrade_userSet()8078 public void testNASSettingUpgrade_userSet() throws RemoteException { 8079 ComponentName defaultComponent = ComponentName.unflattenFromString("package/Component1"); 8080 TestableNotificationManagerService service = spy(mService); 8081 int userId = 11; 8082 setUsers(new int[]{userId}); 8083 when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId}); 8084 setNASMigrationDone(false, userId); 8085 when(mAssistants.getDefaultFromConfig()) 8086 .thenReturn(defaultComponent); 8087 when(mAssistants.getAllowedComponents(anyInt())) 8088 .thenReturn(new ArrayList(Arrays.asList(defaultComponent))); 8089 when(mAssistants.hasUserSet(userId)).thenReturn(true); 8090 8091 service.migrateDefaultNAS(); 8092 verify(mAssistants, times(1)).setUserSet(userId, false); 8093 //resetDefaultAssistantsIfNecessary should invoke from readPolicyXml() and migration 8094 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary(); 8095 } 8096 8097 @Test testNASSettingUpgrade_multiUser()8098 public void testNASSettingUpgrade_multiUser() throws RemoteException { 8099 ComponentName oldDefaultComponent = ComponentName.unflattenFromString("package/Component1"); 8100 ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component2"); 8101 TestableNotificationManagerService service = spy(mService); 8102 int userId1 = 11; 8103 int userId2 = 12; 8104 setUsers(new int[]{userId1, userId2}); 8105 when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1}); 8106 when(mUm.getProfileIds(userId2, false)).thenReturn(new int[]{userId2}); 8107 8108 setNASMigrationDone(false, userId1); 8109 setNASMigrationDone(false, userId2); 8110 when(mAssistants.getDefaultComponents()) 8111 .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent))); 8112 when(mAssistants.getDefaultFromConfig()) 8113 .thenReturn(newDefaultComponent); 8114 //User1: set different NAS 8115 when(mAssistants.getAllowedComponents(userId1)) 8116 .thenReturn(Arrays.asList(oldDefaultComponent)); 8117 //User2: set to none 8118 when(mAssistants.getAllowedComponents(userId2)) 8119 .thenReturn(new ArrayList<>()); 8120 8121 when(mAssistants.hasUserSet(userId1)).thenReturn(true); 8122 when(mAssistants.hasUserSet(userId2)).thenReturn(true); 8123 8124 service.migrateDefaultNAS(); 8125 // user1's setting get reset 8126 verify(mAssistants, times(1)).setUserSet(userId1, false); 8127 verify(mAssistants, times(0)).setUserSet(eq(userId2), anyBoolean()); 8128 assertTrue(service.isNASMigrationDone(userId2)); 8129 8130 } 8131 8132 @Test testNASSettingUpgrade_multiProfile()8133 public void testNASSettingUpgrade_multiProfile() throws RemoteException { 8134 ComponentName oldDefaultComponent = ComponentName.unflattenFromString("package/Component1"); 8135 ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component2"); 8136 TestableNotificationManagerService service = spy(mService); 8137 int userId1 = 11; 8138 int userId2 = 12; //work profile 8139 setUsers(new int[]{userId1, userId2}); 8140 when(mUm.isManagedProfile(userId2)).thenReturn(true); 8141 when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1, userId2}); 8142 8143 setNASMigrationDone(false, userId1); 8144 setNASMigrationDone(false, userId2); 8145 when(mAssistants.getDefaultComponents()) 8146 .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent))); 8147 when(mAssistants.getDefaultFromConfig()) 8148 .thenReturn(newDefaultComponent); 8149 //Both profiles: set different NAS 8150 when(mAssistants.getAllowedComponents(userId1)) 8151 .thenReturn(Arrays.asList(oldDefaultComponent)); 8152 when(mAssistants.getAllowedComponents(userId2)) 8153 .thenReturn(Arrays.asList(oldDefaultComponent)); 8154 8155 when(mAssistants.hasUserSet(userId1)).thenReturn(true); 8156 when(mAssistants.hasUserSet(userId2)).thenReturn(true); 8157 8158 service.migrateDefaultNAS(); 8159 assertFalse(service.isNASMigrationDone(userId1)); 8160 assertFalse(service.isNASMigrationDone(userId2)); 8161 } 8162 8163 8164 8165 @Test testNASSettingUpgrade_clearDataAfterMigrationIsDone()8166 public void testNASSettingUpgrade_clearDataAfterMigrationIsDone() throws RemoteException { 8167 ComponentName defaultComponent = ComponentName.unflattenFromString("package/Component"); 8168 TestableNotificationManagerService service = spy(mService); 8169 int userId = 12; 8170 setUsers(new int[]{userId}); 8171 when(mAssistants.getDefaultComponents()) 8172 .thenReturn(new ArraySet<>(Arrays.asList(defaultComponent))); 8173 when(mAssistants.hasUserSet(userId)).thenReturn(true); 8174 setNASMigrationDone(true, userId); 8175 8176 //Test User clear data 8177 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners = 8178 generateResetComponentValues(); 8179 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners); 8180 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>(); 8181 changes.put(true, new ArrayList(Arrays.asList(defaultComponent))); 8182 changes.put(false, new ArrayList()); 8183 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes); 8184 8185 //Clear data 8186 service.getBinderService().clearData("package", userId, false); 8187 //Test migrate flow again 8188 service.migrateDefaultNAS(); 8189 8190 //Migration should not happen again 8191 verify(mAssistants, times(0)).setUserSet(userId, false); 8192 verify(mAssistants, times(0)).clearDefaults(); 8193 //resetDefaultAssistantsIfNecessary should only invoke once from readPolicyXml() 8194 verify(mAssistants, times(1)).resetDefaultAssistantsIfNecessary(); 8195 8196 } 8197 setNASMigrationDone(boolean done, int userId)8198 private void setNASMigrationDone(boolean done, int userId) { 8199 Settings.Secure.putIntForUser(mContext.getContentResolver(), 8200 Settings.Secure.NAS_SETTINGS_UPDATED, done ? 1 : 0, userId); 8201 } 8202 setUsers(int[] userIds)8203 private void setUsers(int[] userIds) { 8204 List<UserInfo> users = new ArrayList<>(); 8205 for (int id: userIds) { 8206 users.add(new UserInfo(id, String.valueOf(id), 0)); 8207 } 8208 for (UserInfo user : users) { 8209 when(mUm.getUserInfo(eq(user.id))).thenReturn(user); 8210 } 8211 when(mUm.getUsers()).thenReturn(users); 8212 } 8213 8214 @Test clearDefaultListenersPackageShouldEnableIt()8215 public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException { 8216 ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants = 8217 generateResetComponentValues(); 8218 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants); 8219 ComponentName deviceConfig = new ComponentName("device", "config"); 8220 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>(); 8221 changes.put(true, new ArrayList(Arrays.asList(deviceConfig))); 8222 changes.put(false, new ArrayList()); 8223 when(mListeners.resetComponents(anyString(), anyInt())) 8224 .thenReturn(changes); 8225 mService.getBinderService().clearData("device", 0, false); 8226 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( 8227 eq("device"), eq(0), eq(false), eq(true)); 8228 } 8229 8230 @Test clearDefaultDnDPackageShouldEnableIt()8231 public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException { 8232 ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues(); 8233 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed); 8234 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed); 8235 mService.getBinderService().clearData("pkgName", 0, false); 8236 verify(mConditionProviders, times(1)).resetPackage( 8237 eq("pkgName"), eq(0)); 8238 } 8239 8240 @Test testFlagBubble()8241 public void testFlagBubble() throws RemoteException { 8242 setUpPrefsForBubbles(PKG, mUid, 8243 true /* global */, 8244 BUBBLE_PREFERENCE_ALL /* app */, 8245 true /* channel */); 8246 8247 NotificationRecord nr = 8248 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble"); 8249 8250 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8251 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8252 waitForIdle(); 8253 8254 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8255 assertEquals(1, notifs.length); 8256 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0); 8257 assertTrue(mService.getNotificationRecord( 8258 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8259 } 8260 8261 @Test testFlagBubble_noFlag_appNotAllowed()8262 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException { 8263 setUpPrefsForBubbles(PKG, mUid, 8264 true /* global */, 8265 BUBBLE_PREFERENCE_NONE /* app */, 8266 true /* channel */); 8267 8268 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8269 "testFlagBubble_noFlag_appNotAllowed"); 8270 8271 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8272 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8273 waitForIdle(); 8274 8275 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8276 assertEquals(1, notifs.length); 8277 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0); 8278 assertFalse(mService.getNotificationRecord( 8279 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8280 } 8281 8282 @Test testFlagBubbleNotifs_noFlag_whenAppForeground()8283 public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException { 8284 setUpPrefsForBubbles(PKG, mUid, 8285 true /* global */, 8286 BUBBLE_PREFERENCE_ALL /* app */, 8287 true /* channel */); 8288 8289 // Notif with bubble metadata but not our other misc requirements 8290 Notification.Builder nb = new Notification.Builder(mContext, 8291 mTestNotificationChannel.getId()) 8292 .setContentTitle("foo") 8293 .setSmallIcon(android.R.drawable.sym_def_app_icon) 8294 .setBubbleMetadata(getBubbleMetadata()); 8295 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, 8296 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 8297 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 8298 8299 // Say we're foreground 8300 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn( 8301 IMPORTANCE_FOREGROUND); 8302 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8303 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8304 waitForIdle(); 8305 8306 // if notif isn't configured properly it doesn't get to bubble just because app is 8307 // foreground. 8308 assertFalse(mService.getNotificationRecord( 8309 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8310 } 8311 8312 @Test testFlagBubbleNotifs_flag_messaging()8313 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException { 8314 setUpPrefsForBubbles(PKG, mUid, 8315 true /* global */, 8316 BUBBLE_PREFERENCE_ALL /* app */, 8317 true /* channel */); 8318 8319 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8320 "testFlagBubbleNotifs_flag_messaging"); 8321 8322 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8323 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8324 waitForIdle(); 8325 8326 // yes allowed, yes messaging, yes bubble 8327 assertTrue(mService.getNotificationRecord( 8328 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8329 } 8330 8331 @Test testFlagBubbleNotifs_noFlag_noShortcut()8332 public void testFlagBubbleNotifs_noFlag_noShortcut() throws RemoteException { 8333 setUpPrefsForBubbles(PKG, mUid, 8334 true /* global */, 8335 BUBBLE_PREFERENCE_ALL /* app */, 8336 true /* channel */); 8337 8338 Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false); 8339 nb.setShortcutId(null); 8340 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 8341 null, mUid, 0, 8342 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 8343 8344 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 8345 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 8346 waitForIdle(); 8347 8348 // no shortcut no bubble 8349 assertFalse(mService.getNotificationRecord( 8350 sbn.getKey()).getNotification().isBubbleNotification()); 8351 } 8352 8353 @Test testFlagBubbleNotifs_noFlag_messaging_appNotAllowed()8354 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException { 8355 setUpPrefsForBubbles(PKG, mUid, 8356 true /* global */, 8357 BUBBLE_PREFERENCE_NONE /* app */, 8358 true /* channel */); 8359 8360 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8361 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed"); 8362 8363 // Post the notification 8364 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8365 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8366 waitForIdle(); 8367 8368 // not allowed, no bubble 8369 assertFalse(mService.getNotificationRecord( 8370 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8371 } 8372 8373 @Test testFlagBubbleNotifs_noFlag_notBubble()8374 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException { 8375 setUpPrefsForBubbles(PKG, mUid, 8376 true /* global */, 8377 BUBBLE_PREFERENCE_ALL /* app */, 8378 true /* channel */); 8379 8380 // Messaging notif WITHOUT bubble metadata 8381 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */, 8382 null /* groupKey */, false /* isSummary */); 8383 8384 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 8385 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0, 8386 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 8387 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 8388 8389 // Post the notification 8390 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8391 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8392 waitForIdle(); 8393 8394 // no bubble metadata, no bubble 8395 assertFalse(mService.getNotificationRecord( 8396 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8397 } 8398 8399 @Test testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed()8400 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException { 8401 setUpPrefsForBubbles(PKG, mUid, 8402 true /* global */, 8403 BUBBLE_PREFERENCE_ALL /* app */, 8404 false /* channel */); 8405 8406 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8407 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed"); 8408 nr.getChannel().lockFields(USER_LOCKED_ALLOW_BUBBLE); 8409 8410 // Post the notification 8411 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8412 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8413 waitForIdle(); 8414 8415 // channel not allowed, no bubble 8416 assertFalse(mService.getNotificationRecord( 8417 nr.getSbn().getKey()).getNotification().isBubbleNotification()); 8418 } 8419 8420 @Test testCancelNotificationsFromApp_cancelsBubbles()8421 public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception { 8422 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); 8423 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE; 8424 8425 // Post the notification 8426 mBinderService.enqueueNotificationWithTag(PKG, PKG, 8427 "testAppCancelNotifications_cancelsBubbles", 8428 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(), 8429 nrBubble.getSbn().getUserId()); 8430 waitForIdle(); 8431 8432 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8433 assertEquals(1, notifs.length); 8434 assertEquals(1, mService.getNotificationRecordCount()); 8435 8436 mBinderService.cancelNotificationWithTag(PKG, PKG, 8437 "testAppCancelNotifications_cancelsBubbles", nrBubble.getSbn().getId(), 8438 nrBubble.getSbn().getUserId()); 8439 waitForIdle(); 8440 8441 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG); 8442 assertEquals(0, notifs2.length); 8443 assertEquals(0, mService.getNotificationRecordCount()); 8444 } 8445 8446 @Test testCancelAllNotificationsFromApp_cancelsBubble()8447 public void testCancelAllNotificationsFromApp_cancelsBubble() throws Exception { 8448 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 8449 nr.getSbn().getNotification().flags |= FLAG_BUBBLE; 8450 mService.addNotification(nr); 8451 8452 mBinderService.cancelAllNotifications(PKG, nr.getSbn().getUserId()); 8453 waitForIdle(); 8454 8455 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8456 assertEquals(0, notifs.length); 8457 assertEquals(0, mService.getNotificationRecordCount()); 8458 } 8459 8460 @Test testCancelAllNotificationsFromListener_ignoresBubbles()8461 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception { 8462 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel); 8463 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); 8464 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE; 8465 8466 mService.addNotification(nrNormal); 8467 mService.addNotification(nrBubble); 8468 8469 mService.getBinderService().cancelNotificationsFromListener(null, null); 8470 waitForIdle(); 8471 8472 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8473 assertEquals(1, notifs.length); 8474 assertEquals(1, mService.getNotificationRecordCount()); 8475 } 8476 8477 @Test testCancelNotificationsFromListener_cancelsNonBubble()8478 public void testCancelNotificationsFromListener_cancelsNonBubble() throws Exception { 8479 // Add non-bubble notif 8480 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 8481 mService.addNotification(nr); 8482 8483 // Cancel via listener 8484 String[] keys = {nr.getSbn().getKey()}; 8485 mService.getBinderService().cancelNotificationsFromListener(null, keys); 8486 waitForIdle(); 8487 8488 // Notif not active anymore 8489 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8490 assertEquals(0, notifs.length); 8491 assertEquals(0, mService.getNotificationRecordCount()); 8492 // Cancel event is logged 8493 assertEquals(1, mNotificationRecordLogger.numCalls()); 8494 assertEquals(NotificationRecordLogger.NotificationCancelledEvent 8495 .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0)); 8496 } 8497 8498 @Test testCancelNotificationsFromListener_suppressesBubble()8499 public void testCancelNotificationsFromListener_suppressesBubble() throws Exception { 8500 // Add bubble notif 8501 setUpPrefsForBubbles(PKG, mUid, 8502 true /* global */, 8503 BUBBLE_PREFERENCE_ALL /* app */, 8504 true /* channel */); 8505 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag"); 8506 8507 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8508 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8509 waitForIdle(); 8510 8511 // Cancel via listener 8512 String[] keys = {nr.getSbn().getKey()}; 8513 mService.getBinderService().cancelNotificationsFromListener(null, keys); 8514 waitForIdle(); 8515 8516 // Bubble notif active and suppressed 8517 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8518 assertEquals(1, notifs.length); 8519 assertEquals(1, mService.getNotificationRecordCount()); 8520 assertTrue(notifs[0].getNotification().getBubbleMetadata().isNotificationSuppressed()); 8521 } 8522 8523 @Test testCancelAllNotificationsFromStatusBar_ignoresBubble()8524 public void testCancelAllNotificationsFromStatusBar_ignoresBubble() throws Exception { 8525 // GIVEN a notification bubble 8526 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 8527 nr.getSbn().getNotification().flags |= FLAG_BUBBLE; 8528 mService.addNotification(nr); 8529 8530 // WHEN the status bar clears all notifications 8531 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 8532 nr.getSbn().getUserId()); 8533 waitForIdle(); 8534 8535 // THEN the bubble notification does not get removed 8536 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 8537 assertEquals(1, notifs.length); 8538 assertEquals(1, mService.getNotificationRecordCount()); 8539 } 8540 8541 8542 @Test testGetAllowedAssistantAdjustments()8543 public void testGetAllowedAssistantAdjustments() throws Exception { 8544 List<String> adjustments = mBinderService.getAllowedAssistantAdjustments(null); 8545 assertNotNull(adjustments); 8546 } 8547 8548 @Test testAdjustRestrictedKey()8549 public void testAdjustRestrictedKey() throws Exception { 8550 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 8551 mService.addNotification(r); 8552 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 8553 8554 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true); 8555 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false); 8556 8557 Bundle signals = new Bundle(); 8558 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW); 8559 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE); 8560 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, 8561 "", r.getUser().getIdentifier()); 8562 8563 mBinderService.applyAdjustmentFromAssistant(null, adjustment); 8564 r.applyAdjustments(); 8565 8566 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance()); 8567 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment()); 8568 } 8569 8570 @Test testAutomaticZenRuleValidation_policyFilterAgreement()8571 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception { 8572 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) 8573 .thenReturn(true); 8574 mService.setZenHelper(mock(ZenModeHelper.class)); 8575 ComponentName owner = new ComponentName(mContext, this.getClass()); 8576 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build(); 8577 boolean isEnabled = true; 8578 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8579 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled); 8580 8581 try { 8582 mBinderService.addAutomaticZenRule(rule, mContext.getPackageName()); 8583 fail("Zen policy only applies to priority only mode"); 8584 } catch (IllegalArgumentException e) { 8585 // yay 8586 } 8587 8588 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8589 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled); 8590 mBinderService.addAutomaticZenRule(rule, mContext.getPackageName()); 8591 8592 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8593 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled); 8594 mBinderService.addAutomaticZenRule(rule, mContext.getPackageName()); 8595 } 8596 8597 @Test testAddAutomaticZenRule_systemCallTakesPackageFromOwner()8598 public void testAddAutomaticZenRule_systemCallTakesPackageFromOwner() throws Exception { 8599 mService.isSystemUid = true; 8600 ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class); 8601 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) 8602 .thenReturn(true); 8603 mService.setZenHelper(mockZenModeHelper); 8604 ComponentName owner = new ComponentName("android", "ProviderName"); 8605 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build(); 8606 boolean isEnabled = true; 8607 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8608 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled); 8609 mBinderService.addAutomaticZenRule(rule, "com.android.settings"); 8610 8611 // verify that zen mode helper gets passed in a package name of "android" 8612 verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString(), 8613 anyInt(), eq(true)); // system call counts as "is system or system ui" 8614 } 8615 8616 @Test testAddAutomaticZenRule_systemAppIdCallTakesPackageFromOwner()8617 public void testAddAutomaticZenRule_systemAppIdCallTakesPackageFromOwner() throws Exception { 8618 // The multi-user case: where the calling uid doesn't match the system uid, but the calling 8619 // *appid* is the system. 8620 mService.isSystemUid = false; 8621 mService.isSystemAppId = true; 8622 ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class); 8623 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) 8624 .thenReturn(true); 8625 mService.setZenHelper(mockZenModeHelper); 8626 ComponentName owner = new ComponentName("android", "ProviderName"); 8627 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build(); 8628 boolean isEnabled = true; 8629 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8630 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled); 8631 mBinderService.addAutomaticZenRule(rule, "com.android.settings"); 8632 8633 // verify that zen mode helper gets passed in a package name of "android" 8634 verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString(), 8635 anyInt(), eq(true)); // system call counts as "system or system ui" 8636 } 8637 8638 @Test testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg()8639 public void testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg() throws Exception { 8640 mService.isSystemUid = false; 8641 mService.isSystemAppId = false; 8642 ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class); 8643 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) 8644 .thenReturn(true); 8645 mService.setZenHelper(mockZenModeHelper); 8646 ComponentName owner = new ComponentName("android", "ProviderName"); 8647 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build(); 8648 boolean isEnabled = true; 8649 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class), 8650 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled); 8651 mBinderService.addAutomaticZenRule(rule, "another.package"); 8652 8653 // verify that zen mode helper gets passed in the package name from the arg, not the owner 8654 verify(mockZenModeHelper).addAutomaticZenRule( 8655 eq("another.package"), eq(rule), anyString(), anyInt(), 8656 eq(false)); // doesn't count as a system/systemui call 8657 } 8658 8659 @Test onZenModeChanged_sendsBroadcasts()8660 public void onZenModeChanged_sendsBroadcasts() throws Exception { 8661 when(mAmi.getCurrentUserId()).thenReturn(100); 8662 when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102}); 8663 when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() { 8664 @Override 8665 public List<String> answer(InvocationOnMock invocation) { 8666 int userId = invocation.getArgument(0); 8667 switch (userId) { 8668 case 100: 8669 return Lists.newArrayList("a", "b", "c"); 8670 case 101: 8671 return Lists.newArrayList(); 8672 case 102: 8673 return Lists.newArrayList("b"); 8674 default: 8675 throw new IllegalArgumentException( 8676 "Why would you ask for packages of userId " + userId + "?"); 8677 } 8678 } 8679 }); 8680 8681 mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null, 8682 "testing!"); 8683 waitForIdle(); 8684 8685 InOrder inOrder = inOrder(mContext); 8686 // Verify broadcasts for registered receivers 8687 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent( 8688 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags( 8689 Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(100)), eq(null)); 8690 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent( 8691 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags( 8692 Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(101)), eq(null)); 8693 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent( 8694 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags( 8695 Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(102)), eq(null)); 8696 8697 // Verify broadcast for packages that manage DND. 8698 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent( 8699 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("a").setFlags( 8700 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100))); 8701 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent( 8702 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags( 8703 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100))); 8704 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent( 8705 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("c").setFlags( 8706 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100))); 8707 inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent( 8708 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags( 8709 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102))); 8710 } 8711 eqIntent(Intent wanted)8712 private static Intent eqIntent(Intent wanted) { 8713 return ArgumentMatchers.argThat( 8714 new ArgumentMatcher<Intent>() { 8715 @Override 8716 public boolean matches(Intent argument) { 8717 return wanted.filterEquals(argument) 8718 && wanted.getFlags() == argument.getFlags(); 8719 } 8720 8721 @Override 8722 public String toString() { 8723 return wanted.toString(); 8724 } 8725 }); 8726 } 8727 8728 @Test 8729 public void testAreNotificationsEnabledForPackage() throws Exception { 8730 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), 8731 mUid); 8732 8733 verify(mPermissionHelper).hasPermission(mUid); 8734 } 8735 8736 @Test 8737 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception { 8738 try { 8739 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), 8740 mUid + UserHandle.PER_USER_RANGE); 8741 fail("Cannot call cross user without permission"); 8742 } catch (SecurityException e) { 8743 // pass 8744 } 8745 verify(mPermissionHelper, never()).hasPermission(anyInt()); 8746 8747 // cross user, with permission, no problem 8748 enableInteractAcrossUsers(); 8749 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), 8750 mUid + UserHandle.PER_USER_RANGE); 8751 8752 verify(mPermissionHelper).hasPermission(mUid + UserHandle.PER_USER_RANGE); 8753 } 8754 8755 @Test 8756 public void testAreNotificationsEnabledForPackage_viaInternalService() { 8757 mInternalService.areNotificationsEnabledForPackage(mContext.getPackageName(), mUid); 8758 verify(mPermissionHelper).hasPermission(mUid); 8759 } 8760 8761 @Test 8762 public void testGetPackageImportance() throws Exception { 8763 when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); 8764 assertThat(mBinderService.getPackageImportance(mContext.getPackageName())) 8765 .isEqualTo(IMPORTANCE_DEFAULT); 8766 8767 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 8768 assertThat(mBinderService.getPackageImportance(mContext.getPackageName())) 8769 .isEqualTo(IMPORTANCE_NONE); 8770 } 8771 8772 @Test 8773 public void testAreBubblesAllowedForPackage_crossUser() throws Exception { 8774 try { 8775 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(), 8776 mUid + UserHandle.PER_USER_RANGE); 8777 fail("Cannot call cross user without permission"); 8778 } catch (SecurityException e) { 8779 // pass 8780 } 8781 8782 // cross user, with permission, no problem 8783 enableInteractAcrossUsers(); 8784 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(), 8785 mUid + UserHandle.PER_USER_RANGE); 8786 } 8787 8788 private void enableInteractAcrossUsers() { 8789 TestablePermissions perms = mContext.getTestablePermissions(); 8790 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); 8791 } 8792 8793 @Test 8794 public void testNotificationBubbleChanged_false() throws Exception { 8795 setUpPrefsForBubbles(PKG, mUid, 8796 true /* global */, 8797 BUBBLE_PREFERENCE_ALL /* app */, 8798 true /* channel */); 8799 8800 // Notif with bubble metadata 8801 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8802 "testNotificationBubbleChanged_false"); 8803 8804 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8805 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8806 waitForIdle(); 8807 8808 // Reset as this is called when the notif is first sent 8809 reset(mListeners); 8810 8811 // First we were a bubble 8812 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 8813 assertEquals(1, notifsBefore.length); 8814 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0); 8815 8816 // Notify we're not a bubble 8817 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0); 8818 waitForIdle(); 8819 8820 // Make sure we are not a bubble 8821 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 8822 assertEquals(1, notifsAfter.length); 8823 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 8824 } 8825 8826 @Test 8827 public void testNotificationBubbleChanged_true() throws Exception { 8828 setUpPrefsForBubbles(PKG, mUid, 8829 true /* global */, 8830 BUBBLE_PREFERENCE_ALL /* app */, 8831 true /* channel */); 8832 8833 // Notif that is not a bubble 8834 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 8835 1, null, false); 8836 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8837 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8838 waitForIdle(); 8839 8840 // Would be a normal notification because wouldn't have met requirements to bubble 8841 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 8842 assertEquals(1, notifsBefore.length); 8843 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); 8844 8845 // Update the notification to be message style / meet bubble requirements 8846 NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8847 nr.getSbn().getTag()); 8848 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.getSbn().getTag(), 8849 nr2.getSbn().getId(), nr2.getSbn().getNotification(), nr2.getSbn().getUserId()); 8850 waitForIdle(); 8851 8852 // Reset as this is called when the notif is first sent 8853 reset(mListeners); 8854 8855 // Notify we are now a bubble 8856 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0); 8857 waitForIdle(); 8858 8859 // Make sure we are a bubble 8860 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 8861 assertEquals(1, notifsAfter.length); 8862 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0); 8863 } 8864 8865 @Test 8866 public void testNotificationBubbleChanged_true_notAllowed() throws Exception { 8867 setUpPrefsForBubbles(PKG, mUid, 8868 true /* global */, 8869 BUBBLE_PREFERENCE_ALL /* app */, 8870 true /* channel */); 8871 8872 // Notif that is not a bubble 8873 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 8874 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8875 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8876 waitForIdle(); 8877 8878 // Reset as this is called when the notif is first sent 8879 reset(mListeners); 8880 8881 // Would be a normal notification because wouldn't have met requirements to bubble 8882 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 8883 assertEquals(1, notifsBefore.length); 8884 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); 8885 8886 // Notify we are now a bubble 8887 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0); 8888 waitForIdle(); 8889 8890 // We still wouldn't be a bubble because the notification didn't meet requirements 8891 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 8892 assertEquals(1, notifsAfter.length); 8893 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 8894 } 8895 8896 @Test 8897 public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception { 8898 setUpPrefsForBubbles(PKG, mUid, 8899 true /* global */, 8900 BUBBLE_PREFERENCE_ALL /* app */, 8901 true /* channel */); 8902 8903 // Notif with bubble metadata 8904 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8905 "testNotificationBubbleIsFlagRemoved_resetOnUpdate"); 8906 8907 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8908 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8909 waitForIdle(); 8910 // Flag shouldn't be modified 8911 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 8912 assertFalse(recordToCheck.isFlagBubbleRemoved()); 8913 8914 // Notify we're not a bubble 8915 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0); 8916 waitForIdle(); 8917 // Flag should be modified 8918 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 8919 assertTrue(recordToCheck.isFlagBubbleRemoved()); 8920 8921 8922 // Update the notif 8923 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8924 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8925 waitForIdle(); 8926 // And the flag is reset 8927 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 8928 assertFalse(recordToCheck.isFlagBubbleRemoved()); 8929 } 8930 8931 @Test 8932 public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception { 8933 setUpPrefsForBubbles(PKG, mUid, 8934 true /* global */, 8935 BUBBLE_PREFERENCE_ALL /* app */, 8936 true /* channel */); 8937 8938 // Notif with bubble metadata 8939 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 8940 "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue"); 8941 8942 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8943 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8944 waitForIdle(); 8945 // Flag shouldn't be modified 8946 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 8947 assertFalse(recordToCheck.isFlagBubbleRemoved()); 8948 8949 // Notify we're not a bubble 8950 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0); 8951 waitForIdle(); 8952 // Flag should be modified 8953 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey()); 8954 assertTrue(recordToCheck.isFlagBubbleRemoved()); 8955 8956 // Notify we are a bubble 8957 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0); 8958 waitForIdle(); 8959 // And the flag is reset 8960 assertFalse(recordToCheck.isFlagBubbleRemoved()); 8961 } 8962 8963 @Test 8964 public void testOnBubbleMetadataFlagChanged() throws Exception { 8965 setUpPrefsForBubbles(PKG, mUid, 8966 true /* global */, 8967 BUBBLE_PREFERENCE_ALL /* app */, 8968 true /* channel */); 8969 8970 // Post a bubble notification 8971 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag"); 8972 // Set this so that the bubble can be suppressed 8973 nr.getNotification().getBubbleMetadata().setFlags( 8974 Notification.BubbleMetadata.FLAG_SUPPRESSABLE_BUBBLE); 8975 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 8976 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 8977 waitForIdle(); 8978 8979 // Check the flags 8980 Notification n = mBinderService.getActiveNotifications(PKG)[0].getNotification(); 8981 assertFalse(n.getBubbleMetadata().isNotificationSuppressed()); 8982 assertFalse(n.getBubbleMetadata().getAutoExpandBubble()); 8983 assertFalse(n.getBubbleMetadata().isBubbleSuppressed()); 8984 assertTrue(n.getBubbleMetadata().isBubbleSuppressable()); 8985 8986 // Reset as this is called when the notif is first sent 8987 reset(mListeners); 8988 8989 // Test: change the flags 8990 int flags = Notification.BubbleMetadata.FLAG_SUPPRESSABLE_BUBBLE; 8991 flags |= Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE; 8992 flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; 8993 flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_BUBBLE; 8994 mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(), flags); 8995 waitForIdle(); 8996 8997 // Check 8998 n = mBinderService.getActiveNotifications(PKG)[0].getNotification(); 8999 assertEquals(flags, n.getBubbleMetadata().getFlags()); 9000 9001 // Reset to check again 9002 reset(mListeners); 9003 9004 // Test: clear flags 9005 mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(), 0); 9006 waitForIdle(); 9007 9008 // Check 9009 n = mBinderService.getActiveNotifications(PKG)[0].getNotification(); 9010 assertEquals(0, n.getBubbleMetadata().getFlags()); 9011 } 9012 9013 @Test 9014 public void testOnBubbleMetadataChangedToSuppressNotification_soundStopped() 9015 throws RemoteException { 9016 IRingtonePlayer mockPlayer = mock(IRingtonePlayer.class); 9017 when(mAudioManager.getRingtonePlayer()).thenReturn(mockPlayer); 9018 // Set up volume to be above 0 for the sound to actually play 9019 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10); 9020 9021 setUpPrefsForBubbles(PKG, mUid, 9022 true /* global */, 9023 BUBBLE_PREFERENCE_ALL /* app */, 9024 true /* channel */); 9025 9026 // Post a bubble notification 9027 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag"); 9028 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9029 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9030 waitForIdle(); 9031 9032 // Test: suppress notification via bubble metadata update 9033 mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(), 9034 Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 9035 waitForIdle(); 9036 9037 // Check audio is stopped 9038 verify(mockPlayer).stopAsync(); 9039 } 9040 9041 @Test 9042 public void testGrantInlineReplyUriPermission_recordExists() throws Exception { 9043 int userId = UserManager.isHeadlessSystemUserMode() 9044 ? UserHandle.getUserId(UID_HEADLESS) 9045 : USER_SYSTEM; 9046 9047 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId); 9048 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 9049 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9050 waitForIdle(); 9051 9052 // A notification exists for the given record 9053 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 9054 assertEquals(1, notifsBefore.length); 9055 9056 reset(mPackageManager); 9057 9058 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9059 9060 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9061 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9062 nr.getSbn().getUid()); 9063 9064 // Grant permission called for the UID of SystemUI under the target user ID 9065 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 9066 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), 9067 anyInt(), eq(nr.getSbn().getUserId())); 9068 } 9069 9070 @Test 9071 public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception { 9072 int userId = UserManager.isHeadlessSystemUserMode() 9073 ? UserHandle.getUserId(UID_HEADLESS) 9074 : USER_SYSTEM; 9075 9076 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId); 9077 waitForIdle(); 9078 9079 // No notifications exist for the given record 9080 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 9081 assertEquals(0, notifsBefore.length); 9082 9083 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9084 9085 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9086 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9087 nr.getSbn().getUid()); 9088 9089 // Grant permission still called if no NotificationRecord exists for the given key 9090 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 9091 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), 9092 anyInt(), eq(nr.getSbn().getUserId())); 9093 } 9094 9095 @Test 9096 public void testGrantInlineReplyUriPermission_userAll() throws Exception { 9097 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM 9098 NotificationRecord nr = 9099 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL); 9100 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 9101 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9102 waitForIdle(); 9103 9104 // A notification exists for the given record 9105 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); 9106 assertEquals(1, notifsBefore.length); 9107 9108 reset(mPackageManager); 9109 9110 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9111 9112 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9113 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9114 nr.getSbn().getUid()); 9115 9116 // Target user for the grant is USER_ALL instead of USER_SYSTEM 9117 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 9118 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), 9119 anyInt(), UserManager.isHeadlessSystemUserMode() 9120 ? eq(UserHandle.getUserId(UID_HEADLESS)) 9121 : eq(USER_SYSTEM)); 9122 } 9123 9124 @Test 9125 public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception { 9126 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM 9127 int otherUserId = 11; 9128 NotificationRecord nr = 9129 generateNotificationRecord(mTestNotificationChannel, otherUserId); 9130 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 9131 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9132 waitForIdle(); 9133 9134 // A notification exists for the given record 9135 List<StatusBarNotification> notifsBefore = 9136 mBinderService.getAppActiveNotifications(PKG, nr.getSbn().getUserId()).getList(); 9137 assertEquals(1, notifsBefore.size()); 9138 9139 reset(mPackageManager); 9140 9141 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9142 9143 int uid = 0; // sysui on primary user 9144 int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user 9145 String sysuiPackage = "sysui"; 9146 final String[] sysuiPackages = new String[] { sysuiPackage }; 9147 when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages); 9148 9149 // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the 9150 // time this is called 9151 when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId)) 9152 .thenReturn(otherUserUid); 9153 9154 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9155 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), uid); 9156 9157 // Target user for the grant is USER_ALL instead of USER_SYSTEM 9158 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), 9159 eq(otherUserUid), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), anyInt(), 9160 eq(otherUserId)); 9161 } 9162 9163 @Test 9164 public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception { 9165 int userId = UserManager.isHeadlessSystemUserMode() 9166 ? UserHandle.getUserId(UID_HEADLESS) 9167 : USER_SYSTEM; 9168 9169 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId); 9170 reset(mPackageManager); 9171 9172 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9173 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2); 9174 9175 // create an inline record with two uris in it 9176 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9177 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9178 nr.getSbn().getUid()); 9179 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9180 nr.getKey(), uri2, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9181 nr.getSbn().getUid()); 9182 9183 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey()); 9184 assertNotNull(record); // record exists 9185 assertEquals(record.getUris().size(), 2); // record has two uris in it 9186 9187 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), 9188 nr.getSbn().getUid()); 9189 9190 // permissionOwner destroyed 9191 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner( 9192 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId())); 9193 } 9194 9195 9196 @Test 9197 public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception { 9198 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0); 9199 reset(mPackageManager); 9200 9201 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), 9202 nr.getSbn().getUid()); 9203 9204 // no permissionOwner destroyed 9205 verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner( 9206 any(), eq(null), eq(~0), eq(nr.getUserId())); 9207 } 9208 9209 @Test 9210 public void testClearInlineReplyUriPermission_userAll() throws Exception { 9211 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 9212 UserHandle.USER_ALL); 9213 reset(mPackageManager); 9214 9215 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1); 9216 9217 // create an inline record a uri in it 9218 mService.mNotificationDelegate.grantInlineReplyUriPermission( 9219 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(), 9220 nr.getSbn().getUid()); 9221 9222 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey()); 9223 assertNotNull(record); // record exists 9224 9225 mService.mNotificationDelegate.clearInlineReplyUriPermissions( 9226 nr.getKey(), nr.getSbn().getUid()); 9227 9228 // permissionOwner destroyed for USER_SYSTEM, not USER_ALL 9229 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner( 9230 eq(record.getPermissionOwner()), eq(null), eq(~0), 9231 UserManager.isHeadlessSystemUserMode() 9232 ? eq(UserHandle.getUserId(UID_HEADLESS)) 9233 : eq(USER_SYSTEM)); 9234 } 9235 9236 @Test 9237 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception { 9238 setUpPrefsForBubbles(PKG, mUid, 9239 true /* global */, 9240 BUBBLE_PREFERENCE_ALL /* app */, 9241 true /* channel */); 9242 9243 // And we are low ram 9244 when(mActivityManager.isLowRamDevice()).thenReturn(true); 9245 9246 // Notification that would typically bubble 9247 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 9248 "testNotificationBubbles_disabled_lowRamDevice"); 9249 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9250 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9251 waitForIdle(); 9252 9253 // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled. 9254 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9255 assertEquals(1, notifsAfter.length); 9256 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); 9257 } 9258 9259 @Test 9260 public void testRemoveLargeRemoteViews() throws Exception { 9261 int removeSize = mContext.getResources().getInteger( 9262 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes); 9263 9264 RemoteViews rv = mock(RemoteViews.class); 9265 when(rv.estimateMemoryUsage()).thenReturn(removeSize); 9266 when(rv.clone()).thenReturn(rv); 9267 RemoteViews rv1 = mock(RemoteViews.class); 9268 when(rv1.estimateMemoryUsage()).thenReturn(removeSize); 9269 when(rv1.clone()).thenReturn(rv1); 9270 RemoteViews rv2 = mock(RemoteViews.class); 9271 when(rv2.estimateMemoryUsage()).thenReturn(removeSize); 9272 when(rv2.clone()).thenReturn(rv2); 9273 RemoteViews rv3 = mock(RemoteViews.class); 9274 when(rv3.estimateMemoryUsage()).thenReturn(removeSize); 9275 when(rv3.clone()).thenReturn(rv3); 9276 RemoteViews rv4 = mock(RemoteViews.class); 9277 when(rv4.estimateMemoryUsage()).thenReturn(removeSize); 9278 when(rv4.clone()).thenReturn(rv4); 9279 // note: different! 9280 RemoteViews rv5 = mock(RemoteViews.class); 9281 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1); 9282 when(rv5.clone()).thenReturn(rv5); 9283 9284 Notification np = new Notification.Builder(mContext, "test") 9285 .setSmallIcon(android.R.drawable.sym_def_app_icon) 9286 .setContentText("test") 9287 .setCustomContentView(rv) 9288 .setCustomBigContentView(rv1) 9289 .setCustomHeadsUpContentView(rv2) 9290 .build(); 9291 Notification n = new Notification.Builder(mContext, "test") 9292 .setSmallIcon(android.R.drawable.sym_def_app_icon) 9293 .setContentText("test") 9294 .setCustomContentView(rv3) 9295 .setCustomBigContentView(rv4) 9296 .setCustomHeadsUpContentView(rv5) 9297 .setPublicVersion(np) 9298 .build(); 9299 9300 assertNotNull(np.contentView); 9301 assertNotNull(np.bigContentView); 9302 assertNotNull(np.headsUpContentView); 9303 9304 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW)); 9305 assertNotNull(n.publicVersion.contentView); 9306 assertNotNull(n.publicVersion.bigContentView); 9307 assertNotNull(n.publicVersion.headsUpContentView); 9308 9309 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 9310 9311 assertNull(n.contentView); 9312 assertNull(n.bigContentView); 9313 assertNotNull(n.headsUpContentView); 9314 assertNull(n.publicVersion.contentView); 9315 assertNull(n.publicVersion.bigContentView); 9316 assertNull(n.publicVersion.headsUpContentView); 9317 9318 verify(mUsageStats, times(5)).registerImageRemoved(PKG); 9319 } 9320 9321 @Test 9322 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground() 9323 throws Exception { 9324 setUpPrefsForBubbles(PKG, mUid, 9325 true /* global */, 9326 BUBBLE_PREFERENCE_ALL /* app */, 9327 true /* channel */); 9328 9329 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 9330 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground"); 9331 // Modify metadata flags 9332 nr.getSbn().getNotification().getBubbleMetadata().setFlags( 9333 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE 9334 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 9335 9336 // Ensure we're not foreground 9337 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn( 9338 IMPORTANCE_VISIBLE); 9339 9340 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9341 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9342 waitForIdle(); 9343 9344 // yes allowed, yes messaging, yes bubble 9345 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 9346 assertTrue(notif.isBubbleNotification()); 9347 9348 // The flag should have failed since we're not foreground 9349 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble()); 9350 } 9351 9352 @Test 9353 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground() 9354 throws RemoteException { 9355 setUpPrefsForBubbles(PKG, mUid, 9356 true /* global */, 9357 BUBBLE_PREFERENCE_ALL /* app */, 9358 true /* channel */); 9359 9360 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 9361 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground"); 9362 // Modify metadata flags 9363 nr.getSbn().getNotification().getBubbleMetadata().setFlags( 9364 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE 9365 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 9366 9367 // Ensure we are in the foreground 9368 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn( 9369 IMPORTANCE_FOREGROUND); 9370 9371 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9372 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9373 waitForIdle(); 9374 9375 // yes allowed, yes messaging, yes bubble 9376 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 9377 assertTrue(notif.isBubbleNotification()); 9378 9379 // Our flags should have passed since we are foreground 9380 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble()); 9381 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed()); 9382 } 9383 9384 @Test 9385 public void testNotificationBubbles_flagRemoved_whenShortcutRemoved() 9386 throws RemoteException { 9387 setUpPrefsForBubbles(PKG, mUid, 9388 true /* global */, 9389 BUBBLE_PREFERENCE_ALL /* app */, 9390 true /* channel */); 9391 9392 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback = 9393 ArgumentCaptor.forClass(LauncherApps.Callback.class); 9394 9395 // Messaging notification with shortcut info 9396 Notification.BubbleMetadata metadata = 9397 new Notification.BubbleMetadata.Builder(VALID_CONVO_SHORTCUT_ID).build(); 9398 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 9399 null /* groupKey */, false /* isSummary */); 9400 nb.setShortcutId(VALID_CONVO_SHORTCUT_ID); 9401 nb.setBubbleMetadata(metadata); 9402 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 9403 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 9404 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 9405 9406 // Test: Send the bubble notification 9407 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9408 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9409 waitForIdle(); 9410 9411 // Verify: 9412 9413 // Make sure we register the callback for shortcut changes 9414 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any()); 9415 9416 // yes allowed, yes messaging w/shortcut, yes bubble 9417 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 9418 assertTrue(notif.isBubbleNotification()); 9419 9420 // Make sure the shortcut is cached. 9421 verify(mShortcutServiceInternal).cacheShortcuts( 9422 anyInt(), any(), eq(PKG), eq(singletonList(VALID_CONVO_SHORTCUT_ID)), 9423 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 9424 9425 // Test: Remove the shortcut 9426 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 9427 launcherAppsCallback.getValue().onShortcutsChanged(PKG, emptyList(), 9428 UserHandle.getUserHandleForUid(mUid)); 9429 waitForIdle(); 9430 9431 // Verify: 9432 9433 // Make sure callback is unregistered 9434 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue()); 9435 9436 // We're no longer a bubble 9437 NotificationRecord notif2 = mService.getNotificationRecord( 9438 nr.getSbn().getKey()); 9439 assertNull(notif2.getShortcutInfo()); 9440 assertFalse(notif2.getNotification().isBubbleNotification()); 9441 } 9442 9443 @Test 9444 public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved() 9445 throws RemoteException { 9446 final String shortcutId = "someshortcutId"; 9447 setUpPrefsForBubbles(PKG, mUid, 9448 true /* global */, 9449 BUBBLE_PREFERENCE_ALL /* app */, 9450 true /* channel */); 9451 9452 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback = 9453 ArgumentCaptor.forClass(LauncherApps.Callback.class); 9454 9455 // Messaging notification with shortcut info 9456 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder( 9457 shortcutId).build(); 9458 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 9459 null /* groupKey */, false /* isSummary */); 9460 nb.setShortcutId(shortcutId); 9461 nb.setBubbleMetadata(metadata); 9462 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 9463 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 9464 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 9465 9466 // Pretend the shortcut exists 9467 List<ShortcutInfo> shortcutInfos = new ArrayList<>(); 9468 ShortcutInfo info = mock(ShortcutInfo.class); 9469 when(info.getPackage()).thenReturn(PKG); 9470 when(info.getId()).thenReturn(shortcutId); 9471 when(info.getUserId()).thenReturn(USER_SYSTEM); 9472 when(info.isLongLived()).thenReturn(true); 9473 when(info.isEnabled()).thenReturn(true); 9474 shortcutInfos.add(info); 9475 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos); 9476 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), 9477 anyString(), anyInt(), any())).thenReturn(true); 9478 9479 // Test: Send the bubble notification 9480 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9481 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9482 waitForIdle(); 9483 9484 // Verify: 9485 9486 // Make sure we register the callback for shortcut changes 9487 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any()); 9488 9489 // yes allowed, yes messaging w/shortcut, yes bubble 9490 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification(); 9491 assertTrue(notif.isBubbleNotification()); 9492 9493 // Make sure the shortcut is cached. 9494 verify(mShortcutServiceInternal).cacheShortcuts( 9495 anyInt(), any(), eq(PKG), eq(singletonList(shortcutId)), 9496 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 9497 9498 // Test: Remove the notification 9499 mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9500 nr.getSbn().getId(), nr.getSbn().getUserId()); 9501 waitForIdle(); 9502 9503 // Verify: 9504 9505 // Make sure callback is unregistered 9506 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue()); 9507 } 9508 9509 @Test 9510 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed() 9511 throws Exception { 9512 setUpPrefsForBubbles(PKG, mUid, 9513 true /* global */, 9514 BUBBLE_PREFERENCE_ALL /* app */, 9515 true /* channel */); 9516 9517 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded( 9518 true /* summaryAutoCancel */); 9519 9520 // Dismiss summary 9521 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2, 9522 true); 9523 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, 9524 nrSummary.getUserId(), nrSummary.getKey(), 9525 NotificationStats.DISMISSAL_SHADE, 9526 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv); 9527 waitForIdle(); 9528 9529 // The bubble should still exist 9530 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9531 assertEquals(1, notifsAfter.length); 9532 } 9533 9534 @Test 9535 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked() 9536 throws Exception { 9537 setUpPrefsForBubbles(PKG, mUid, 9538 true /* global */, 9539 BUBBLE_PREFERENCE_ALL /* app */, 9540 true /* channel */); 9541 9542 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded( 9543 true /* summaryAutoCancel */); 9544 9545 // Click summary 9546 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2, 9547 true); 9548 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(), 9549 nrSummary.getKey(), nv); 9550 waitForIdle(); 9551 9552 // The bubble should still exist 9553 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9554 assertEquals(1, notifsAfter.length); 9555 9556 // Check we got the click log and associated dismissal logs 9557 assertEquals(6, mNotificationRecordLogger.numCalls()); 9558 // Skip the notification-creation logs 9559 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED, 9560 mNotificationRecordLogger.event(3)); 9561 assertEquals(NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_CLICK, 9562 mNotificationRecordLogger.event(4)); 9563 assertEquals(NotificationRecordLogger.NotificationCancelledEvent 9564 .NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED, 9565 mNotificationRecordLogger.event(5)); 9566 } 9567 9568 @Test 9569 public void testNotificationBubbles_bubbleStays_whenClicked() 9570 throws Exception { 9571 setUpPrefsForBubbles(PKG, mUid, 9572 true /* global */, 9573 BUBBLE_PREFERENCE_ALL /* app */, 9574 true /* channel */); 9575 9576 // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble 9577 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 9578 nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL; 9579 mService.addNotification(nr); 9580 9581 // WHEN we click the notification 9582 final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true); 9583 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(), 9584 nr.getKey(), nv); 9585 waitForIdle(); 9586 9587 // THEN the bubble should still exist 9588 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9589 assertEquals(1, notifsAfter.length); 9590 9591 // Check we got the click log 9592 assertEquals(1, mNotificationRecordLogger.numCalls()); 9593 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED, 9594 mNotificationRecordLogger.event(0)); 9595 } 9596 9597 /** 9598 * When something is bubble'd and the bubble is dismissed, but the notification is still 9599 * visible, clicking on the notification shouldn't auto-cancel it because clicking on 9600 * it will produce a bubble. 9601 */ 9602 @Test 9603 public void testNotificationBubbles_bubbleStays_whenClicked_afterBubbleDismissed() 9604 throws Exception { 9605 setUpPrefsForBubbles(PKG, mUid, 9606 true /* global */, 9607 BUBBLE_PREFERENCE_ALL /* app */, 9608 true /* channel */); 9609 9610 // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble 9611 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); 9612 nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL; 9613 nr.setAllowBubble(true); 9614 mService.addNotification(nr); 9615 9616 // And the bubble is dismissed 9617 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), 9618 false /* isBubble */, 0 /* bubbleFlags */); 9619 waitForIdle(); 9620 assertTrue(nr.isFlagBubbleRemoved()); 9621 9622 // WHEN we click the notification 9623 final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true); 9624 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(), 9625 nr.getKey(), nv); 9626 waitForIdle(); 9627 9628 // THEN the bubble should still exist 9629 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); 9630 assertEquals(1, notifsAfter.length); 9631 9632 // Check we got the click log 9633 assertEquals(1, mNotificationRecordLogger.numCalls()); 9634 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED, 9635 mNotificationRecordLogger.event(0)); 9636 } 9637 9638 @Test 9639 public void testLoadDefaultApprovedServices_emptyResources() { 9640 TestableResources tr = mContext.getOrCreateTestableResources(); 9641 tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, ""); 9642 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, ""); 9643 tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, ""); 9644 setDefaultAssistantInDeviceConfig(""); 9645 9646 mService.loadDefaultApprovedServices(USER_SYSTEM); 9647 9648 verify(mListeners, never()).addDefaultComponentOrPackage(anyString()); 9649 verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString()); 9650 verify(mAssistants, never()).addDefaultComponentOrPackage(anyString()); 9651 } 9652 9653 @Test 9654 public void testLoadDefaultApprovedServices_dnd() { 9655 TestableResources tr = mContext.getOrCreateTestableResources(); 9656 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test"); 9657 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt())) 9658 .thenReturn(new ArraySet<>()); 9659 9660 mService.loadDefaultApprovedServices(USER_SYSTEM); 9661 9662 verify(mConditionProviders, times(1)).loadDefaultsFromConfig(); 9663 } 9664 9665 // TODO: add tests for the rest of the non-empty cases 9666 9667 @Test 9668 public void testOnUnlockUser() { 9669 UserInfo ui = new UserInfo(); 9670 ui.id = 10; 9671 mService.onUserUnlocked(new TargetUser(ui)); 9672 waitForIdle(); 9673 9674 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id); 9675 } 9676 9677 @Test 9678 public void testOnStopUser() { 9679 UserInfo ui = new UserInfo(); 9680 ui.id = 10; 9681 mService.onUserStopping(new TargetUser(ui)); 9682 waitForIdle(); 9683 9684 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id); 9685 } 9686 9687 @Test 9688 public void testHandleOnPackageChanged() { 9689 String[] pkgs = new String[] {PKG, PKG_N_MR1}; 9690 int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1}; 9691 9692 mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids); 9693 9694 verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString()); 9695 9696 mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids); 9697 9698 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]); 9699 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]); 9700 } 9701 9702 @Test 9703 public void testNotificationHistory_addNoisyNotification() throws Exception { 9704 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 9705 null /* tvExtender */); 9706 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9707 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9708 waitForIdle(); 9709 9710 verify(mHistoryManager, times(1)).addNotification(any()); 9711 } 9712 9713 @Test 9714 public void createConversationNotificationChannel() throws Exception { 9715 int userId = UserManager.isHeadlessSystemUserMode() 9716 ? UserHandle.getUserId(UID_HEADLESS) 9717 : USER_SYSTEM; 9718 9719 NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 9720 original.setAllowBubbles(!original.canBubble()); 9721 original.setShowBadge(!original.canShowBadge()); 9722 9723 Parcel parcel = Parcel.obtain(); 9724 original.writeToParcel(parcel, 0); 9725 parcel.setDataPosition(0); 9726 NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel); 9727 assertEquals(original, orig); 9728 assertFalse(TextUtils.isEmpty(orig.getName())); 9729 9730 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList( 9731 orig))); 9732 9733 mBinderService.createConversationNotificationChannelForPackage( 9734 PKG, mUid, orig, "friend"); 9735 9736 NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel( 9737 PKG, userId, PKG, original.getId(), false, "friend"); 9738 9739 assertEquals(original.getName(), friendChannel.getName()); 9740 assertEquals(original.getId(), friendChannel.getParentChannelId()); 9741 assertEquals("friend", friendChannel.getConversationId()); 9742 assertEquals(null, original.getConversationId()); 9743 assertEquals(original.canShowBadge(), friendChannel.canShowBadge()); 9744 assertFalse(friendChannel.canBubble()); // can't be modified by app 9745 assertFalse(original.getId().equals(friendChannel.getId())); 9746 assertNotNull(friendChannel.getId()); 9747 } 9748 9749 @Test 9750 public void testCorrectCategory_systemOn_appCannotTurnOff() { 9751 int requested = 0; 9752 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 9753 9754 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 9755 system); 9756 9757 assertEquals(PRIORITY_CATEGORY_CONVERSATIONS, actual); 9758 } 9759 9760 @Test 9761 public void testCorrectCategory_systemOff_appTurnOff_noChanges() { 9762 int requested = PRIORITY_CATEGORY_CALLS; 9763 int system = PRIORITY_CATEGORY_CALLS; 9764 9765 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 9766 system); 9767 9768 assertEquals(PRIORITY_CATEGORY_CALLS, actual); 9769 } 9770 9771 @Test 9772 public void testCorrectCategory_systemOn_appTurnOn_noChanges() { 9773 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 9774 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 9775 9776 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 9777 system); 9778 9779 assertEquals(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS, actual); 9780 } 9781 9782 @Test 9783 public void testCorrectCategory_systemOff_appCannotTurnOn() { 9784 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS; 9785 int system = PRIORITY_CATEGORY_CALLS; 9786 9787 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS, 9788 system); 9789 9790 assertEquals(PRIORITY_CATEGORY_CALLS, actual); 9791 } 9792 9793 @Test 9794 public void testGetConversationsForPackage_hasShortcut() throws Exception { 9795 mService.setPreferencesHelper(mPreferencesHelper); 9796 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>(); 9797 ConversationChannelWrapper convo1 = new ConversationChannelWrapper(); 9798 NotificationChannel channel1 = new NotificationChannel("a", "a", 1); 9799 channel1.setConversationId("parent1", "convo 1"); 9800 convo1.setNotificationChannel(channel1); 9801 convos.add(convo1); 9802 9803 ConversationChannelWrapper convo2 = new ConversationChannelWrapper(); 9804 NotificationChannel channel2 = new NotificationChannel("b", "b", 1); 9805 channel2.setConversationId("parent1", "convo 2"); 9806 convo2.setNotificationChannel(channel2); 9807 convos.add(convo2); 9808 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos); 9809 9810 ShortcutInfo si = mock(ShortcutInfo.class); 9811 when(si.getPackage()).thenReturn(PKG_P); 9812 when(si.getId()).thenReturn("convo"); 9813 when(si.getUserId()).thenReturn(USER_SYSTEM); 9814 when(si.getLabel()).thenReturn("Hello"); 9815 when(si.isLongLived()).thenReturn(true); 9816 when(si.isEnabled()).thenReturn(true); 9817 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si)); 9818 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), 9819 anyString(), anyInt(), any())).thenReturn(true); 9820 9821 List<ConversationChannelWrapper> conversations = 9822 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 9823 assertEquals(si, conversations.get(0).getShortcutInfo()); 9824 assertEquals(si, conversations.get(1).getShortcutInfo()); 9825 9826 // Returns null shortcuts when locked. 9827 when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(false); 9828 conversations = 9829 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 9830 assertThat(conversations.get(0).getShortcutInfo()).isNull(); 9831 assertThat(conversations.get(1).getShortcutInfo()).isNull(); 9832 } 9833 9834 @Test 9835 public void testGetConversationsForPackage_shortcut_notLongLived() throws Exception { 9836 mService.setPreferencesHelper(mPreferencesHelper); 9837 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>(); 9838 ConversationChannelWrapper convo1 = new ConversationChannelWrapper(); 9839 NotificationChannel channel1 = new NotificationChannel("a", "a", 1); 9840 channel1.setConversationId("parent1", "convo 1"); 9841 convo1.setNotificationChannel(channel1); 9842 convos.add(convo1); 9843 9844 ConversationChannelWrapper convo2 = new ConversationChannelWrapper(); 9845 NotificationChannel channel2 = new NotificationChannel("b", "b", 1); 9846 channel2.setConversationId("parent1", "convo 2"); 9847 convo2.setNotificationChannel(channel2); 9848 convos.add(convo2); 9849 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos); 9850 9851 ShortcutInfo si = mock(ShortcutInfo.class); 9852 when(si.getPackage()).thenReturn(PKG_P); 9853 when(si.getId()).thenReturn("convo"); 9854 when(si.getUserId()).thenReturn(USER_SYSTEM); 9855 when(si.getLabel()).thenReturn("Hello"); 9856 when(si.isLongLived()).thenReturn(false); 9857 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si)); 9858 9859 List<ConversationChannelWrapper> conversations = 9860 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 9861 assertNull(conversations.get(0).getShortcutInfo()); 9862 assertNull(conversations.get(1).getShortcutInfo()); 9863 } 9864 9865 @Test 9866 public void testGetConversationsForPackage_doesNotHaveShortcut() throws Exception { 9867 mService.setPreferencesHelper(mPreferencesHelper); 9868 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>(); 9869 ConversationChannelWrapper convo1 = new ConversationChannelWrapper(); 9870 NotificationChannel channel1 = new NotificationChannel("a", "a", 1); 9871 channel1.setConversationId("parent1", "convo 1"); 9872 convo1.setNotificationChannel(channel1); 9873 convos.add(convo1); 9874 9875 ConversationChannelWrapper convo2 = new ConversationChannelWrapper(); 9876 NotificationChannel channel2 = new NotificationChannel("b", "b", 1); 9877 channel2.setConversationId("parent1", "convo 2"); 9878 convo2.setNotificationChannel(channel2); 9879 convos.add(convo2); 9880 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos); 9881 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 9882 9883 List<ConversationChannelWrapper> conversations = 9884 mBinderService.getConversationsForPackage(PKG_P, mUid).getList(); 9885 assertNull(conversations.get(0).getShortcutInfo()); 9886 assertNull(conversations.get(1).getShortcutInfo()); 9887 } 9888 9889 @Test 9890 public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException { 9891 mService.setShortcutHelper(null); 9892 NotificationRecord nr = 9893 generateMessageBubbleNotifRecord(mTestNotificationChannel, 9894 "testShortcutHelperNull_doesntCrashEnqueue"); 9895 try { 9896 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9897 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9898 waitForIdle(); 9899 } catch (Exception e) { 9900 fail(e.getMessage()); 9901 } 9902 } 9903 9904 @Test 9905 public void testRecordMessages_invalidMsg() throws RemoteException { 9906 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 9907 null /* groupKey */, false /* isSummary */); 9908 nb.setShortcutId(null); 9909 StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1, 9910 "testRecordMessages_invalidMsg", mUid, 0, nb.build(), 9911 UserHandle.getUserHandleForUid(mUid), null, 0); 9912 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 9913 9914 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 9915 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(), 9916 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9917 waitForIdle(); 9918 9919 assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid)); 9920 } 9921 9922 @Test 9923 public void testRecordMessages_invalidMsg_notMessageStyle() throws RemoteException { 9924 Notification.Builder nb = new Notification.Builder(mContext, 9925 mTestNotificationChannel.getId()) 9926 .setContentTitle("foo") 9927 .setShortcutId(null) 9928 .setSmallIcon(android.R.drawable.sym_def_app_icon) 9929 .setCategory(Notification.CATEGORY_MESSAGE); 9930 StatusBarNotification sbn = new StatusBarNotification(PKG_O, PKG_O, 1, 9931 "testRecordMessages_invalidMsg_notMessageStyle", mUid, 0, nb.build(), 9932 UserHandle.getUserHandleForUid(mUid), null, 0); 9933 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 9934 9935 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null); 9936 mBinderService.enqueueNotificationWithTag(PKG_O, PKG_O, nr.getSbn().getTag(), 9937 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9938 waitForIdle(); 9939 9940 // PKG_O is allowed to be in conversation space b/c of override in 9941 // TestableNotificationManagerService 9942 assertTrue(mBinderService.isInInvalidMsgState(PKG_O, mUid)); 9943 } 9944 9945 @Test 9946 public void testRecordMessages_validMsg() throws RemoteException { 9947 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 9948 null /* groupKey */, false /* isSummary */); 9949 nb.setShortcutId(null); 9950 StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1, 9951 "testRecordMessages_validMsg", mUid, 0, nb.build(), 9952 UserHandle.getUserHandleForUid(mUid), null, 0); 9953 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 9954 9955 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(), 9956 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9957 waitForIdle(); 9958 9959 assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid)); 9960 9961 nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 9962 "testRecordMessages_validMsg"); 9963 9964 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(), 9965 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9966 waitForIdle(); 9967 9968 assertFalse(mBinderService.isInInvalidMsgState(PKG_P, mUid)); 9969 } 9970 9971 @Test 9972 public void testRecordMessages_invalidMsg_afterValidMsg() throws RemoteException { 9973 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, 9974 "testRecordMessages_invalidMsg_afterValidMsg_1"); 9975 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9976 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9977 waitForIdle(); 9978 assertTrue(mService.getNotificationRecord(nr.getKey()).isConversation()); 9979 9980 mBinderService.cancelAllNotifications(PKG, mUid); 9981 waitForIdle(); 9982 9983 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, 9984 null /* groupKey */, false /* isSummary */); 9985 nb.setShortcutId(null); 9986 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, 9987 "testRecordMessages_invalidMsg_afterValidMsg_2", mUid, 0, nb.build(), 9988 UserHandle.getUserHandleForUid(mUid), null, 0); 9989 nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 9990 9991 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), 9992 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); 9993 waitForIdle(); 9994 9995 assertFalse(mService.getNotificationRecord(nr.getKey()).isConversation()); 9996 } 9997 9998 @Test 9999 public void testCanPostFgsWhenOverLimit() throws RemoteException { 10000 when(mAmi.applyForegroundServiceNotification( 10001 any(), anyString(), anyInt(), anyString(), anyInt())) 10002 .thenReturn(SHOW_IMMEDIATELY); 10003 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 10004 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 10005 i, null, false).getSbn(); 10006 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10007 "testCanPostFgsWhenOverLimit", 10008 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 10009 } 10010 10011 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 10012 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 10013 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10014 "testCanPostFgsWhenOverLimit - fgs over limit!", 10015 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 10016 10017 waitForIdle(); 10018 10019 StatusBarNotification[] notifs = 10020 mBinderService.getActiveNotifications(sbn.getPackageName()); 10021 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); 10022 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, 10023 mService.getNotificationRecordCount()); 10024 } 10025 10026 @Test 10027 public void testCannotPostNonFgsWhenOverLimit() throws RemoteException { 10028 when(mAmi.applyForegroundServiceNotification( 10029 any(), anyString(), anyInt(), anyString(), anyInt())) 10030 .thenReturn(SHOW_IMMEDIATELY); 10031 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 10032 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 10033 i, null, false).getSbn(); 10034 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10035 "testCanPostFgsWhenOverLimit", 10036 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 10037 waitForIdle(); 10038 } 10039 10040 final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 10041 100, null, false).getSbn(); 10042 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 10043 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10044 "testCanPostFgsWhenOverLimit - fgs over limit!", 10045 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 10046 10047 final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel, 10048 101, null, false).getSbn(); 10049 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10050 "testCanPostFgsWhenOverLimit - non fgs over limit!", 10051 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId()); 10052 10053 10054 when(mAmi.applyForegroundServiceNotification( 10055 any(), anyString(), anyInt(), anyString(), anyInt())) 10056 .thenReturn(NOT_FOREGROUND_SERVICE); 10057 final StatusBarNotification sbn3 = generateNotificationRecord(mTestNotificationChannel, 10058 101, null, false).getSbn(); 10059 sbn3.getNotification().flags |= FLAG_FOREGROUND_SERVICE; 10060 mBinderService.enqueueNotificationWithTag(PKG, PKG, 10061 "testCanPostFgsWhenOverLimit - fake fgs over limit!", 10062 sbn3.getId(), sbn3.getNotification(), sbn3.getUserId()); 10063 10064 waitForIdle(); 10065 10066 StatusBarNotification[] notifs = 10067 mBinderService.getActiveNotifications(sbn.getPackageName()); 10068 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); 10069 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, 10070 mService.getNotificationRecordCount()); 10071 } 10072 10073 @Test 10074 public void testIsVisibleToListener_notEnabled() { 10075 StatusBarNotification sbn = mock(StatusBarNotification.class); 10076 when(sbn.getUserId()).thenReturn(10); 10077 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10078 ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class); 10079 info.userid = 10; 10080 when(info.isSameUser(anyInt())).thenReturn(true); 10081 when(assistant.isSameUser(anyInt())).thenReturn(true); 10082 when(info.enabledAndUserMatches(info.userid)).thenReturn(false); 10083 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant); 10084 10085 assertFalse(mService.isVisibleToListener(sbn, 0, info)); 10086 } 10087 10088 @Test 10089 public void testIsVisibleToListener_noAssistant() { 10090 StatusBarNotification sbn = mock(StatusBarNotification.class); 10091 when(sbn.getUserId()).thenReturn(10); 10092 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10093 info.userid = 10; 10094 when(info.isSameUser(anyInt())).thenReturn(true); 10095 when(info.enabledAndUserMatches(info.userid)).thenReturn(true); 10096 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(null); 10097 10098 assertTrue(mService.isVisibleToListener(sbn, 0, info)); 10099 } 10100 10101 @Test 10102 public void testIsVisibleToListener_assistant_differentUser() { 10103 StatusBarNotification sbn = mock(StatusBarNotification.class); 10104 when(sbn.getUserId()).thenReturn(10); 10105 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10106 ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class); 10107 info.userid = 0; 10108 when(info.isSameUser(anyInt())).thenReturn(true); 10109 when(assistant.isSameUser(anyInt())).thenReturn(true); 10110 when(info.enabledAndUserMatches(info.userid)).thenReturn(true); 10111 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant); 10112 10113 assertFalse(mService.isVisibleToListener(sbn, 0, info)); 10114 } 10115 10116 @Test 10117 public void testIsVisibleToListener_assistant_sameUser() { 10118 StatusBarNotification sbn = mock(StatusBarNotification.class); 10119 when(sbn.getUserId()).thenReturn(10); 10120 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10121 ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class); 10122 info.userid = 10; 10123 when(info.isSameUser(anyInt())).thenReturn(true); 10124 when(assistant.isSameUser(anyInt())).thenReturn(true); 10125 when(info.enabledAndUserMatches(info.userid)).thenReturn(true); 10126 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant); 10127 10128 assertTrue(mService.isVisibleToListener(sbn, 0, info)); 10129 } 10130 10131 @Test 10132 public void testIsVisibleToListener_mismatchedType() { 10133 when(mNlf.isTypeAllowed(anyInt())).thenReturn(false); 10134 10135 StatusBarNotification sbn = mock(StatusBarNotification.class); 10136 when(sbn.getUserId()).thenReturn(10); 10137 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10138 ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class); 10139 info.userid = 10; 10140 when(info.isSameUser(anyInt())).thenReturn(true); 10141 when(assistant.isSameUser(anyInt())).thenReturn(true); 10142 when(info.enabledAndUserMatches(info.userid)).thenReturn(true); 10143 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant); 10144 10145 assertFalse(mService.isVisibleToListener(sbn, 0, info)); 10146 } 10147 10148 @Test 10149 public void testIsVisibleToListener_disallowedPackage() { 10150 when(mNlf.isPackageAllowed(any())).thenReturn(false); 10151 10152 StatusBarNotification sbn = mock(StatusBarNotification.class); 10153 when(sbn.getUserId()).thenReturn(10); 10154 ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class); 10155 ManagedServices.ManagedServiceInfo assistant = 10156 mock(ManagedServices.ManagedServiceInfo.class); 10157 info.userid = 10; 10158 when(info.isSameUser(anyInt())).thenReturn(true); 10159 when(assistant.isSameUser(anyInt())).thenReturn(true); 10160 when(info.enabledAndUserMatches(info.userid)).thenReturn(true); 10161 when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant); 10162 10163 assertFalse(mService.isVisibleToListener(sbn, 0, info)); 10164 } 10165 10166 @Test 10167 public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedFirst() { 10168 final NotificationRecord parent = spy(generateNotificationRecord( 10169 mTestNotificationChannel, 1, "group", true)); 10170 final NotificationRecord child = spy(generateNotificationRecord( 10171 mTestNotificationChannel, 2, "group", false)); 10172 mService.addNotification(parent); 10173 mService.addNotification(child); 10174 10175 InOrder inOrder = inOrder(parent, child); 10176 10177 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 10178 parent.getUserId()); 10179 waitForIdle(); 10180 inOrder.verify(parent).recordDismissalSentiment(anyInt()); 10181 inOrder.verify(child).recordDismissalSentiment(anyInt()); 10182 } 10183 10184 @Test 10185 public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedSecond() { 10186 final NotificationRecord parent = spy(generateNotificationRecord( 10187 mTestNotificationChannel, 1, "group", true)); 10188 final NotificationRecord child = spy(generateNotificationRecord( 10189 mTestNotificationChannel, 2, "group", false)); 10190 mService.addNotification(child); 10191 mService.addNotification(parent); 10192 10193 InOrder inOrder = inOrder(parent, child); 10194 10195 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), 10196 parent.getUserId()); 10197 waitForIdle(); 10198 inOrder.verify(parent).recordDismissalSentiment(anyInt()); 10199 inOrder.verify(child).recordDismissalSentiment(anyInt()); 10200 } 10201 10202 @Test 10203 public void testImmutableBubbleIntent() throws Exception { 10204 when(mAmi.getPendingIntentFlags(pi1)) 10205 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT); 10206 NotificationRecord r = generateMessageBubbleNotifRecord(true, 10207 mTestNotificationChannel, 7, "testImmutableBubbleIntent", null, false); 10208 try { 10209 mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(), 10210 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId()); 10211 10212 waitForIdle(); 10213 fail("Allowed a bubble with an immutable intent to be posted"); 10214 } catch (IllegalArgumentException e) { 10215 // good 10216 } 10217 } 10218 10219 @Test 10220 public void testMutableBubbleIntent() throws Exception { 10221 when(mAmi.getPendingIntentFlags(pi1)) 10222 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); 10223 NotificationRecord r = generateMessageBubbleNotifRecord(true, 10224 mTestNotificationChannel, 7, "testMutableBubbleIntent", null, false); 10225 10226 mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(), 10227 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId()); 10228 10229 waitForIdle(); 10230 StatusBarNotification[] notifs = 10231 mBinderService.getActiveNotifications(r.getSbn().getPackageName()); 10232 assertEquals(1, notifs.length); 10233 } 10234 10235 @Test 10236 public void testImmutableDirectReplyActionIntent() throws Exception { 10237 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10238 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT); 10239 NotificationRecord r = generateMessageBubbleNotifRecord(false, 10240 mTestNotificationChannel, 7, "testImmutableDirectReplyActionIntent", null, false); 10241 try { 10242 mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(), 10243 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId()); 10244 10245 waitForIdle(); 10246 fail("Allowed a direct reply with an immutable intent to be posted"); 10247 } catch (IllegalArgumentException e) { 10248 // good 10249 } 10250 } 10251 10252 @Test 10253 public void testMutableDirectReplyActionIntent() throws Exception { 10254 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10255 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); 10256 NotificationRecord r = generateMessageBubbleNotifRecord(false, 10257 mTestNotificationChannel, 7, "testMutableDirectReplyActionIntent", null, false); 10258 mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(), 10259 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId()); 10260 10261 waitForIdle(); 10262 StatusBarNotification[] notifs = 10263 mBinderService.getActiveNotifications(r.getSbn().getPackageName()); 10264 assertEquals(1, notifs.length); 10265 } 10266 10267 @Test 10268 public void testImmutableDirectReplyContextualActionIntent() throws Exception { 10269 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10270 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT); 10271 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10272 10273 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 10274 ArrayList<Notification.Action> extraAction = new ArrayList<>(); 10275 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); 10276 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 10277 PendingIntent.FLAG_IMMUTABLE); 10278 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); 10279 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", 10280 inputIntent).addRemoteInput(remoteInput) 10281 .build(); 10282 extraAction.add(replyAction); 10283 Bundle signals = new Bundle(); 10284 signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction); 10285 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "", 10286 r.getUser()); 10287 r.addAdjustment(adjustment); 10288 r.applyAdjustments(); 10289 10290 try { 10291 mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(), 10292 r.getSbn().getTag(), r, false, false); 10293 fail("Allowed a contextual direct reply with an immutable intent to be posted"); 10294 } catch (IllegalArgumentException e) { 10295 // good 10296 } 10297 } 10298 10299 @Test 10300 public void testMutableDirectReplyContextualActionIntent() throws Exception { 10301 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10302 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); 10303 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10304 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 10305 ArrayList<Notification.Action> extraAction = new ArrayList<>(); 10306 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); 10307 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, 10308 new Intent().setPackage(mContext.getPackageName()), 10309 PendingIntent.FLAG_MUTABLE); 10310 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); 10311 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", 10312 inputIntent).addRemoteInput(remoteInput) 10313 .build(); 10314 extraAction.add(replyAction); 10315 Bundle signals = new Bundle(); 10316 signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction); 10317 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "", 10318 r.getUser()); 10319 r.addAdjustment(adjustment); 10320 r.applyAdjustments(); 10321 10322 mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(), 10323 r.getSbn().getTag(), r, false, false); 10324 } 10325 10326 @Test 10327 public void testImmutableActionIntent() throws Exception { 10328 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10329 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT); 10330 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 10331 10332 mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(), 10333 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId()); 10334 10335 waitForIdle(); 10336 StatusBarNotification[] notifs = 10337 mBinderService.getActiveNotifications(r.getSbn().getPackageName()); 10338 assertEquals(1, notifs.length); 10339 } 10340 10341 @Test 10342 public void testImmutableContextualActionIntent() throws Exception { 10343 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10344 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT); 10345 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10346 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); 10347 ArrayList<Notification.Action> extraAction = new ArrayList<>(); 10348 extraAction.add(new Notification.Action(0, "hello", null)); 10349 Bundle signals = new Bundle(); 10350 signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction); 10351 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "", 10352 r.getUser()); 10353 r.addAdjustment(adjustment); 10354 r.applyAdjustments(); 10355 10356 mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(), 10357 r.getSbn().getTag(), r, false, false); 10358 } 10359 10360 @Test 10361 public void testMigrateNotificationFilter_migrationAllAllowed() throws Exception { 10362 int uid = 9000; 10363 int[] userIds = new int[] {mUserId, 1000}; 10364 when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds); 10365 List<String> disallowedApps = ImmutableList.of("apples", "bananas", "cherries"); 10366 for (int userId : userIds) { 10367 for (String pkg : disallowedApps) { 10368 when(mPackageManager.getPackageUid(pkg, 0, userId)).thenReturn(uid++); 10369 } 10370 } 10371 10372 when(mListeners.getNotificationListenerFilter(any())).thenReturn( 10373 new NotificationListenerFilter()); 10374 10375 mBinderService.migrateNotificationFilter(null, 10376 FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING, 10377 disallowedApps); 10378 10379 ArgumentCaptor<NotificationListenerFilter> captor = 10380 ArgumentCaptor.forClass(NotificationListenerFilter.class); 10381 verify(mListeners).setNotificationListenerFilter(any(), captor.capture()); 10382 10383 assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING, 10384 captor.getValue().getTypes()); 10385 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 9000))); 10386 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("cherries", 9002))); 10387 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 9003))); 10388 10389 // hypothetical other user untouched 10390 assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 10000))); 10391 } 10392 10393 @Test 10394 public void testMigrateNotificationFilter_noPreexistingFilter() throws Exception { 10395 int[] userIds = new int[] {mUserId}; 10396 when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds); 10397 List<String> disallowedApps = ImmutableList.of("apples"); 10398 when(mPackageManager.getPackageUid("apples", 0, mUserId)) 10399 .thenReturn(1001); 10400 10401 when(mListeners.getNotificationListenerFilter(any())).thenReturn(null); 10402 10403 mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING, 10404 disallowedApps); 10405 10406 ArgumentCaptor<NotificationListenerFilter> captor = 10407 ArgumentCaptor.forClass(NotificationListenerFilter.class); 10408 verify(mListeners).setNotificationListenerFilter(any(), captor.capture()); 10409 10410 assertEquals(FLAG_FILTER_TYPE_ONGOING, captor.getValue().getTypes()); 10411 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001))); 10412 } 10413 10414 @Test 10415 public void testMigrateNotificationFilter_existingTypeFilter() throws Exception { 10416 int[] userIds = new int[] {mUserId}; 10417 when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds); 10418 List<String> disallowedApps = ImmutableList.of("apples"); 10419 when(mPackageManager.getPackageUid("apples", 0, mUserId)) 10420 .thenReturn(1001); 10421 10422 when(mListeners.getNotificationListenerFilter(any())).thenReturn( 10423 new NotificationListenerFilter(FLAG_FILTER_TYPE_CONVERSATIONS, new ArraySet<>())); 10424 10425 mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING, 10426 disallowedApps); 10427 10428 ArgumentCaptor<NotificationListenerFilter> captor = 10429 ArgumentCaptor.forClass(NotificationListenerFilter.class); 10430 verify(mListeners).setNotificationListenerFilter(any(), captor.capture()); 10431 10432 // type isn't saved but pkg list is 10433 assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS, captor.getValue().getTypes()); 10434 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001))); 10435 } 10436 10437 @Test 10438 public void testMigrateNotificationFilter_existingPkgFilter() throws Exception { 10439 int[] userIds = new int[] {mUserId}; 10440 when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds); 10441 List<String> disallowedApps = ImmutableList.of("apples"); 10442 when(mPackageManager.getPackageUid("apples", 0, mUserId)) 10443 .thenReturn(1001); 10444 10445 NotificationListenerFilter preexisting = new NotificationListenerFilter(); 10446 preexisting.addPackage(new VersionedPackage("test", 1002)); 10447 when(mListeners.getNotificationListenerFilter(any())).thenReturn(preexisting); 10448 10449 mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING, 10450 disallowedApps); 10451 10452 ArgumentCaptor<NotificationListenerFilter> captor = 10453 ArgumentCaptor.forClass(NotificationListenerFilter.class); 10454 verify(mListeners).setNotificationListenerFilter(any(), captor.capture()); 10455 10456 // type is saved but pkg list isn't 10457 assertEquals(FLAG_FILTER_TYPE_ONGOING, captor.getValue().getTypes()); 10458 assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001))); 10459 assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("test", 1002))); 10460 } 10461 10462 @Test 10463 public void testGetNotificationChannelsBypassingDnd_blocked() throws RemoteException { 10464 mService.setPreferencesHelper(mPreferencesHelper); 10465 10466 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 10467 10468 assertThat(mBinderService.getNotificationChannelsBypassingDnd(PKG, mUid).getList()) 10469 .isEmpty(); 10470 verify(mPreferencesHelper, never()).getNotificationChannelsBypassingDnd(PKG, mUid); 10471 } 10472 10473 @Test 10474 public void testMatchesCallFilter_noPermissionShouldThrow() throws Exception { 10475 // set the testable NMS to not system uid/appid 10476 mService.isSystemUid = false; 10477 mService.isSystemAppId = false; 10478 10479 // make sure a caller without listener access or read_contacts permission can't call 10480 // matchesCallFilter. 10481 when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false); 10482 doThrow(new SecurityException()).when(mContext).enforceCallingPermission( 10483 eq("android.permission.READ_CONTACTS"), anyString()); 10484 10485 try { 10486 // shouldn't matter what we're passing in, if we get past this line fail immediately 10487 ((INotificationManager) mService.mService).matchesCallFilter(null); 10488 fail("call to matchesCallFilter with no permissions should fail"); 10489 } catch (SecurityException e) { 10490 // pass 10491 } 10492 } 10493 10494 @Test 10495 public void testMatchesCallFilter_hasSystemPermission() throws Exception { 10496 // set the testable NMS to system uid 10497 mService.isSystemUid = true; 10498 10499 // make sure caller doesn't have listener access or read_contacts permission 10500 when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false); 10501 doThrow(new SecurityException()).when(mContext).enforceCallingPermission( 10502 eq("android.permission.READ_CONTACTS"), anyString()); 10503 10504 try { 10505 ((INotificationManager) mService.mService).matchesCallFilter(null); 10506 // pass, but check that we actually checked for system permissions 10507 assertTrue(mService.countSystemChecks > 0); 10508 } catch (SecurityException e) { 10509 fail("call to matchesCallFilter with just system permissions should work"); 10510 } 10511 } 10512 10513 @Test 10514 public void testMatchesCallFilter_hasListenerPermission() throws Exception { 10515 mService.isSystemUid = false; 10516 mService.isSystemAppId = false; 10517 10518 // make sure a caller with only listener access and not read_contacts permission can call 10519 // matchesCallFilter. 10520 when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(true); 10521 doThrow(new SecurityException()).when(mContext).enforceCallingPermission( 10522 eq("android.permission.READ_CONTACTS"), anyString()); 10523 10524 try { 10525 ((INotificationManager) mService.mService).matchesCallFilter(null); 10526 // pass, this is not a functionality test 10527 } catch (SecurityException e) { 10528 fail("call to matchesCallFilter with listener permissions should work"); 10529 } 10530 } 10531 10532 @Test 10533 public void testMatchesCallFilter_hasContactsPermission() throws Exception { 10534 mService.isSystemUid = false; 10535 mService.isSystemAppId = false; 10536 10537 // make sure a caller with only read_contacts permission and not listener access can call 10538 // matchesCallFilter. 10539 when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false); 10540 doNothing().when(mContext).enforceCallingPermission( 10541 eq("android.permission.READ_CONTACTS"), anyString()); 10542 10543 try { 10544 ((INotificationManager) mService.mService).matchesCallFilter(null); 10545 // pass, this is not a functionality test 10546 } catch (SecurityException e) { 10547 fail("call to matchesCallFilter with listener permissions should work"); 10548 } 10549 } 10550 10551 @Test 10552 public void testMediaNotificationsBypassBlock() throws Exception { 10553 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10554 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); 10555 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10556 10557 Notification.Builder nb = new Notification.Builder( 10558 mContext, mTestNotificationChannel.getId()) 10559 .setContentTitle("foo") 10560 .setSmallIcon(android.R.drawable.sym_def_app_icon) 10561 .addAction(new Notification.Action.Builder(null, "test", null).build()); 10562 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10563 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10564 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10565 10566 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 10567 10568 // normal blocked notifications - blocked 10569 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10570 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse(); 10571 10572 // just using the style - blocked 10573 nb.setStyle(new Notification.MediaStyle()); 10574 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10575 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10576 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10577 10578 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10579 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse(); 10580 10581 // using the style, but incorrect type in session - blocked 10582 nb.setStyle(new Notification.MediaStyle()); 10583 Bundle extras = new Bundle(); 10584 extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent()); 10585 nb.addExtras(extras); 10586 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10587 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10588 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10589 10590 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10591 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse(); 10592 10593 // style + media session - bypasses block 10594 nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class))); 10595 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10596 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10597 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10598 10599 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10600 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 10601 } 10602 10603 @Test 10604 public void testMediaNotificationsBypassBlock_atPost() throws Exception { 10605 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 10606 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10607 10608 Notification.Builder nb = new Notification.Builder( 10609 mContext, mTestNotificationChannel.getId()) 10610 .setContentTitle("foo") 10611 .setSmallIcon(android.R.drawable.sym_def_app_icon) 10612 .addAction(new Notification.Action.Builder(null, "test", null).build()); 10613 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10614 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10615 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10616 10617 when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false); 10618 10619 mService.addEnqueuedNotification(r); 10620 NotificationManagerService.PostNotificationRunnable runnable = 10621 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 10622 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 10623 runnable.run(); 10624 waitForIdle(); 10625 10626 verify(mUsageStats).registerBlocked(any()); 10627 verify(mUsageStats, never()).registerPostedByApp(any()); 10628 10629 // just using the style - blocked 10630 mService.clearNotifications(); 10631 reset(mUsageStats); 10632 nb.setStyle(new Notification.MediaStyle()); 10633 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10634 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10635 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10636 10637 mService.addEnqueuedNotification(r); 10638 runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 10639 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 10640 runnable.run(); 10641 waitForIdle(); 10642 10643 verify(mUsageStats).registerBlocked(any()); 10644 verify(mUsageStats, never()).registerPostedByApp(any()); 10645 10646 // style + media session - bypasses block 10647 mService.clearNotifications(); 10648 reset(mUsageStats); 10649 nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class))); 10650 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10651 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10652 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10653 10654 mService.addEnqueuedNotification(r); 10655 runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), 10656 r.getUid(), mPostNotificationTrackerFactory.newTracker(null)); 10657 runnable.run(); 10658 waitForIdle(); 10659 10660 verify(mUsageStats, never()).registerBlocked(any()); 10661 verify(mUsageStats).registerPostedByApp(any()); 10662 } 10663 10664 @Test 10665 public void testCallNotificationsBypassBlock() throws Exception { 10666 when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) 10667 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); 10668 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10669 10670 Notification.Builder nb = new Notification.Builder( 10671 mContext, mTestNotificationChannel.getId()) 10672 .setContentTitle("foo") 10673 .setSmallIcon(android.R.drawable.sym_def_app_icon) 10674 .addAction(new Notification.Action.Builder(null, "test", null).build()); 10675 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10676 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10677 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10678 10679 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 10680 10681 // normal blocked notifications - blocked 10682 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10683 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse(); 10684 10685 // just using the style - blocked 10686 Person person = new Person.Builder() 10687 .setName("caller") 10688 .build(); 10689 nb.setStyle(Notification.CallStyle.forOngoingCall( 10690 person, mock(PendingIntent.class))); 10691 nb.setFullScreenIntent(mock(PendingIntent.class), true); 10692 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10693 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10694 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10695 10696 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10697 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse(); 10698 10699 // style + managed call - bypasses block 10700 when(mTelecomManager.isInManagedCall()).thenReturn(true); 10701 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10702 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 10703 10704 // style + self managed call - bypasses block 10705 when(mTelecomManager.isInSelfManagedCall( 10706 r.getSbn().getPackageName(), r.getUser())).thenReturn(true); 10707 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10708 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 10709 10710 // set telecom manager to null - blocked 10711 mService.setTelecomManager(null); 10712 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10713 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)) 10714 .isFalse(); 10715 10716 // set telecom feature to false - blocked 10717 when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false); 10718 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10719 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)) 10720 .isFalse(); 10721 10722 // telecom manager is not ready - blocked 10723 mService.setTelecomManager(mTelecomManager); 10724 when(mTelecomManager.isInCall()).thenThrow(new IllegalStateException("not ready")); 10725 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 10726 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)) 10727 .isFalse(); 10728 } 10729 10730 @Test 10731 public void testCallNotificationsBypassBlock_atPost() throws Exception { 10732 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); 10733 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); 10734 10735 Notification.Builder nb = 10736 new Notification.Builder(mContext, mTestNotificationChannel.getId()) 10737 .setContentTitle("foo") 10738 .setSmallIcon(android.R.drawable.sym_def_app_icon) 10739 .addAction(new Notification.Action.Builder(null, "test", null).build()); 10740 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 10741 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); 10742 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10743 10744 when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); 10745 10746 // normal blocked notifications - blocked 10747 mService.addEnqueuedNotification(r); 10748 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10749 mPostNotificationTrackerFactory.newTracker(null)).run(); 10750 waitForIdle(); 10751 10752 verify(mUsageStats).registerBlocked(any()); 10753 verify(mUsageStats, never()).registerPostedByApp(any()); 10754 10755 // just using the style - blocked 10756 mService.clearNotifications(); 10757 reset(mUsageStats); 10758 Person person = new Person.Builder().setName("caller").build(); 10759 nb.setStyle(Notification.CallStyle.forOngoingCall(person, mock(PendingIntent.class))); 10760 nb.setFullScreenIntent(mock(PendingIntent.class), true); 10761 sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, nb.build(), 10762 UserHandle.getUserHandleForUid(mUid), null, 0); 10763 r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 10764 10765 mService.addEnqueuedNotification(r); 10766 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10767 mPostNotificationTrackerFactory.newTracker(null)).run(); 10768 waitForIdle(); 10769 10770 verify(mUsageStats).registerBlocked(any()); 10771 verify(mUsageStats, never()).registerPostedByApp(any()); 10772 10773 // style + managed call - bypasses block 10774 mService.clearNotifications(); 10775 reset(mUsageStats); 10776 when(mTelecomManager.isInManagedCall()).thenReturn(true); 10777 10778 mService.addEnqueuedNotification(r); 10779 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10780 mPostNotificationTrackerFactory.newTracker(null)).run(); 10781 waitForIdle(); 10782 10783 verify(mUsageStats, never()).registerBlocked(any()); 10784 verify(mUsageStats).registerPostedByApp(any()); 10785 10786 // style + self managed call - bypasses block 10787 mService.clearNotifications(); 10788 reset(mUsageStats); 10789 when(mTelecomManager.isInSelfManagedCall(r.getSbn().getPackageName(), r.getUser())) 10790 .thenReturn(true); 10791 10792 mService.addEnqueuedNotification(r); 10793 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10794 mPostNotificationTrackerFactory.newTracker(null)).run(); 10795 waitForIdle(); 10796 10797 verify(mUsageStats, never()).registerBlocked(any()); 10798 verify(mUsageStats).registerPostedByApp(any()); 10799 10800 // set telecom manager to null - notifications should be blocked 10801 // but post notifications runnable should not crash 10802 mService.clearNotifications(); 10803 reset(mUsageStats); 10804 mService.setTelecomManager(null); 10805 10806 mService.addEnqueuedNotification(r); 10807 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10808 mPostNotificationTrackerFactory.newTracker(null)).run(); 10809 waitForIdle(); 10810 10811 verify(mUsageStats).registerBlocked(any()); 10812 verify(mUsageStats, never()).registerPostedByApp(any()); 10813 10814 // set FEATURE_TELECOM to false - notifications should be blocked 10815 // but post notifications runnable should not crash 10816 mService.setTelecomManager(mTelecomManager); 10817 when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false); 10818 reset(mUsageStats); 10819 mService.setTelecomManager(null); 10820 10821 mService.addEnqueuedNotification(r); 10822 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10823 mPostNotificationTrackerFactory.newTracker(null)).run(); 10824 waitForIdle(); 10825 10826 verify(mUsageStats).registerBlocked(any()); 10827 verify(mUsageStats, never()).registerPostedByApp(any()); 10828 10829 // telecom is not ready - notifications should be blocked but no crashes 10830 mService.setTelecomManager(mTelecomManager); 10831 when(mTelecomManager.isInCall()).thenThrow(new IllegalStateException("not ready")); 10832 reset(mUsageStats); 10833 10834 mService.addEnqueuedNotification(r); 10835 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(), 10836 mPostNotificationTrackerFactory.newTracker(null)).run(); 10837 waitForIdle(); 10838 10839 verify(mUsageStats).registerBlocked(any()); 10840 verify(mUsageStats, never()).registerPostedByApp(any()); 10841 } 10842 10843 @Test 10844 public void testGetAllUsersNotificationPermissions() { 10845 // In this case, there are multiple users each with notification permissions (and also, 10846 // for good measure, some without). 10847 // make sure the collection returned contains info for all of them 10848 final List<UserInfo> userInfos = new ArrayList<>(); 10849 userInfos.add(new UserInfo(0, "user0", 0)); 10850 userInfos.add(new UserInfo(1, "user1", 0)); 10851 userInfos.add(new UserInfo(2, "user2", 0)); 10852 when(mUm.getUsers()).thenReturn(userInfos); 10853 10854 // construct the permissions for each of them 10855 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> permissions0 = new ArrayMap<>(), 10856 permissions1 = new ArrayMap<>(); 10857 permissions0.put(new Pair<>(10, "package1"), new Pair<>(true, false)); 10858 permissions0.put(new Pair<>(20, "package2"), new Pair<>(false, true)); 10859 permissions1.put(new Pair<>(11, "package1"), new Pair<>(false, false)); 10860 permissions1.put(new Pair<>(21, "package2"), new Pair<>(true, true)); 10861 when(mPermissionHelper.getNotificationPermissionValues(0)).thenReturn(permissions0); 10862 when(mPermissionHelper.getNotificationPermissionValues(1)).thenReturn(permissions1); 10863 when(mPermissionHelper.getNotificationPermissionValues(2)).thenReturn(new ArrayMap<>()); 10864 10865 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> combinedPermissions = 10866 mService.getAllUsersNotificationPermissions(); 10867 assertTrue(combinedPermissions.get(new Pair<>(10, "package1")).first); 10868 assertFalse(combinedPermissions.get(new Pair<>(10, "package1")).second); 10869 assertFalse(combinedPermissions.get(new Pair<>(20, "package2")).first); 10870 assertTrue(combinedPermissions.get(new Pair<>(20, "package2")).second); 10871 assertFalse(combinedPermissions.get(new Pair<>(11, "package1")).first); 10872 assertFalse(combinedPermissions.get(new Pair<>(11, "package1")).second); 10873 assertTrue(combinedPermissions.get(new Pair<>(21, "package2")).first); 10874 assertTrue(combinedPermissions.get(new Pair<>(21, "package2")).second); 10875 } 10876 10877 @Test 10878 public void testGetActiveNotification_filtersUsers() throws Exception { 10879 when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0, 10}); 10880 10881 NotificationRecord nr0 = 10882 generateNotificationRecord(mTestNotificationChannel, 0); 10883 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag0", 10884 nr0.getSbn().getId(), nr0.getSbn().getNotification(), nr0.getSbn().getUserId()); 10885 10886 NotificationRecord nr10 = 10887 generateNotificationRecord(mTestNotificationChannel, 10); 10888 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag10", 10889 nr10.getSbn().getId(), nr10.getSbn().getNotification(), nr10.getSbn().getUserId()); 10890 10891 NotificationRecord nr11 = 10892 generateNotificationRecord(mTestNotificationChannel, 11); 10893 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag11", 10894 nr11.getSbn().getId(), nr11.getSbn().getNotification(), nr11.getSbn().getUserId()); 10895 waitForIdle(); 10896 10897 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); 10898 assertEquals(2, notifs.length); 10899 for (StatusBarNotification sbn : notifs) { 10900 if (sbn.getUserId() == 11) { 10901 fail("leaked data across users"); 10902 } 10903 } 10904 } 10905 10906 @Test 10907 public void testUngroupingOngoingAutoSummary() throws Exception { 10908 NotificationRecord nr0 = 10909 generateNotificationRecord(mTestNotificationChannel, 0); 10910 NotificationRecord nr1 = 10911 generateNotificationRecord(mTestNotificationChannel, 0); 10912 nr1.getSbn().getNotification().flags |= FLAG_ONGOING_EVENT; 10913 10914 mService.addNotification(nr0); 10915 mService.addNotification(nr1); 10916 10917 // grouphelper is a mock here, so make the calls it would make 10918 10919 // add summary 10920 mService.addNotification(mService.createAutoGroupSummary(nr1.getUserId(), 10921 nr1.getSbn().getPackageName(), nr1.getKey(), 10922 GroupHelper.BASE_FLAGS | FLAG_ONGOING_EVENT)); 10923 10924 // cancel both children 10925 mBinderService.cancelNotificationWithTag(PKG, PKG, nr0.getSbn().getTag(), 10926 nr0.getSbn().getId(), nr0.getSbn().getUserId()); 10927 mBinderService.cancelNotificationWithTag(PKG, PKG, nr1.getSbn().getTag(), 10928 nr1.getSbn().getId(), nr1.getSbn().getUserId()); 10929 waitForIdle(); 10930 10931 // group helper would send 'remove summary' event 10932 mService.clearAutogroupSummaryLocked(nr1.getUserId(), nr1.getSbn().getPackageName()); 10933 waitForIdle(); 10934 10935 // make sure the summary was removed and not re-posted 10936 assertThat(mService.getNotificationRecordCount()).isEqualTo(0); 10937 } 10938 10939 @Test 10940 public void testUngroupingAutoSummary_differentUsers() throws Exception { 10941 NotificationRecord nr0 = 10942 generateNotificationRecord(mTestNotificationChannel, 0, USER_SYSTEM); 10943 NotificationRecord nr1 = 10944 generateNotificationRecord(mTestNotificationChannel, 1, USER_SYSTEM); 10945 10946 // add notifications + summary for USER_SYSTEM 10947 mService.addNotification(nr0); 10948 mService.addNotification(nr1); 10949 mService.addNotification(mService.createAutoGroupSummary(nr1.getUserId(), 10950 nr1.getSbn().getPackageName(), nr1.getKey(), GroupHelper.BASE_FLAGS)); 10951 10952 // add notifications + summary for USER_ALL 10953 NotificationRecord nr0_all = 10954 generateNotificationRecord(mTestNotificationChannel, 2, UserHandle.USER_ALL); 10955 NotificationRecord nr1_all = 10956 generateNotificationRecord(mTestNotificationChannel, 3, UserHandle.USER_ALL); 10957 10958 mService.addNotification(nr0_all); 10959 mService.addNotification(nr1_all); 10960 mService.addNotification(mService.createAutoGroupSummary(nr0_all.getUserId(), 10961 nr0_all.getSbn().getPackageName(), nr0_all.getKey(), GroupHelper.BASE_FLAGS)); 10962 10963 // cancel both children for USER_ALL 10964 mBinderService.cancelNotificationWithTag(PKG, PKG, nr0_all.getSbn().getTag(), 10965 nr0_all.getSbn().getId(), UserHandle.USER_ALL); 10966 mBinderService.cancelNotificationWithTag(PKG, PKG, nr1_all.getSbn().getTag(), 10967 nr1_all.getSbn().getId(), UserHandle.USER_ALL); 10968 waitForIdle(); 10969 10970 // group helper would send 'remove summary' event 10971 mService.clearAutogroupSummaryLocked(UserHandle.USER_ALL, 10972 nr0_all.getSbn().getPackageName()); 10973 waitForIdle(); 10974 10975 // make sure the right summary was removed 10976 assertThat(mService.getNotificationCount(nr0_all.getSbn().getPackageName(), 10977 UserHandle.USER_ALL, 0, null)).isEqualTo(0); 10978 10979 // the USER_SYSTEM notifications + summary were not removed 10980 assertThat(mService.getNotificationCount(nr0.getSbn().getPackageName(), 10981 USER_SYSTEM, 0, null)).isEqualTo(3); 10982 } 10983 10984 @Test 10985 public void testStrongAuthTracker_isInLockDownMode() { 10986 mStrongAuthTracker.setGetStrongAuthForUserReturnValue( 10987 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); 10988 mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId()); 10989 assertTrue(mStrongAuthTracker.isInLockDownMode(mContext.getUserId())); 10990 mStrongAuthTracker.setGetStrongAuthForUserReturnValue(mContext.getUserId()); 10991 mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId()); 10992 assertFalse(mStrongAuthTracker.isInLockDownMode(mContext.getUserId())); 10993 } 10994 10995 @Test 10996 public void testCancelAndPostNotificationsWhenEnterAndExitLockDownMode() { 10997 // post 2 notifications from 2 packages 10998 NotificationRecord pkgA = new NotificationRecord(mContext, 10999 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 11000 mService.addNotification(pkgA); 11001 NotificationRecord pkgB = new NotificationRecord(mContext, 11002 generateSbn("b", 1001, 9, 0), mTestNotificationChannel); 11003 mService.addNotification(pkgB); 11004 11005 // when entering the lockdown mode, cancel the 2 notifications. 11006 mStrongAuthTracker.setGetStrongAuthForUserReturnValue( 11007 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); 11008 mStrongAuthTracker.onStrongAuthRequiredChanged(0); 11009 assertTrue(mStrongAuthTracker.isInLockDownMode(0)); 11010 11011 // the notifyRemovedLocked function is called twice due to REASON_LOCKDOWN. 11012 ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class); 11013 verify(mListeners, times(2)).notifyRemovedLocked(any(), captor.capture(), any()); 11014 assertEquals(REASON_LOCKDOWN, captor.getValue().intValue()); 11015 11016 // exit lockdown mode. 11017 mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0); 11018 mStrongAuthTracker.onStrongAuthRequiredChanged(0); 11019 assertFalse(mStrongAuthTracker.isInLockDownMode(0)); 11020 11021 // the notifyPostedLocked function is called twice. 11022 verify(mWorkerHandler, times(2)).postDelayed(any(Runnable.class), anyLong()); 11023 //verify(mListeners, times(2)).notifyPostedLocked(any(), any()); 11024 } 11025 11026 @Test 11027 public void testMakeRankingUpdateLockedInLockDownMode() { 11028 // post 2 notifications from a same package 11029 NotificationRecord pkgA = new NotificationRecord(mContext, 11030 generateSbn("a", 1000, 9, 0), mTestNotificationChannel); 11031 mService.addNotification(pkgA); 11032 NotificationRecord pkgB = new NotificationRecord(mContext, 11033 generateSbn("a", 1000, 9, 1), mTestNotificationChannel); 11034 mService.addNotification(pkgB); 11035 11036 mService.setIsVisibleToListenerReturnValue(true); 11037 NotificationRankingUpdate nru = mService.makeRankingUpdateLocked(null); 11038 assertEquals(2, nru.getRankingMap().getOrderedKeys().length); 11039 11040 // when only user 0 entering the lockdown mode, its notification will be suppressed. 11041 mStrongAuthTracker.setGetStrongAuthForUserReturnValue( 11042 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); 11043 mStrongAuthTracker.onStrongAuthRequiredChanged(0); 11044 assertTrue(mStrongAuthTracker.isInLockDownMode(0)); 11045 assertFalse(mStrongAuthTracker.isInLockDownMode(1)); 11046 11047 nru = mService.makeRankingUpdateLocked(null); 11048 assertEquals(1, nru.getRankingMap().getOrderedKeys().length); 11049 11050 // User 0 exits lockdown mode. Its notification will be resumed. 11051 mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0); 11052 mStrongAuthTracker.onStrongAuthRequiredChanged(0); 11053 assertFalse(mStrongAuthTracker.isInLockDownMode(0)); 11054 assertFalse(mStrongAuthTracker.isInLockDownMode(1)); 11055 11056 nru = mService.makeRankingUpdateLocked(null); 11057 assertEquals(2, nru.getRankingMap().getOrderedKeys().length); 11058 } 11059 11060 @Test 11061 public void testMaybeShowReviewPermissionsNotification_flagOff() { 11062 mService.setShowReviewPermissionsNotification(false); 11063 reset(mMockNm); 11064 11065 // If state is SHOULD_SHOW, it would show, but not if the flag is off! 11066 Settings.Global.putInt(mContext.getContentResolver(), 11067 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11068 NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW); 11069 mService.maybeShowInitialReviewPermissionsNotification(); 11070 verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class)); 11071 } 11072 11073 @Test 11074 public void testMaybeShowReviewPermissionsNotification_unknown() { 11075 mService.setShowReviewPermissionsNotification(true); 11076 reset(mMockNm); 11077 11078 // Set up various possible states of the settings int and confirm whether or not the 11079 // notification is shown as expected 11080 11081 // Initial state: default/unknown setting, make sure nothing happens 11082 Settings.Global.putInt(mContext.getContentResolver(), 11083 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11084 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN); 11085 mService.maybeShowInitialReviewPermissionsNotification(); 11086 verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class)); 11087 } 11088 11089 @Test 11090 public void testMaybeShowReviewPermissionsNotification_shouldShow() { 11091 mService.setShowReviewPermissionsNotification(true); 11092 reset(mMockNm); 11093 11094 // If state is SHOULD_SHOW, it ... should show 11095 Settings.Global.putInt(mContext.getContentResolver(), 11096 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11097 NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW); 11098 mService.maybeShowInitialReviewPermissionsNotification(); 11099 verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG), 11100 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS), 11101 any(Notification.class)); 11102 } 11103 11104 @Test 11105 public void testMaybeShowReviewPermissionsNotification_alreadyShown() { 11106 mService.setShowReviewPermissionsNotification(true); 11107 reset(mMockNm); 11108 11109 // If state is either USER_INTERACTED or DISMISSED, we should not show this on boot 11110 Settings.Global.putInt(mContext.getContentResolver(), 11111 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11112 NotificationManagerService.REVIEW_NOTIF_STATE_USER_INTERACTED); 11113 mService.maybeShowInitialReviewPermissionsNotification(); 11114 11115 Settings.Global.putInt(mContext.getContentResolver(), 11116 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11117 NotificationManagerService.REVIEW_NOTIF_STATE_DISMISSED); 11118 mService.maybeShowInitialReviewPermissionsNotification(); 11119 11120 verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class)); 11121 } 11122 11123 @Test 11124 public void testMaybeShowReviewPermissionsNotification_reshown() { 11125 mService.setShowReviewPermissionsNotification(true); 11126 reset(mMockNm); 11127 11128 // If we have re-shown the notification and the user did not subsequently interacted with 11129 // it, then make sure we show when trying on boot 11130 Settings.Global.putInt(mContext.getContentResolver(), 11131 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11132 NotificationManagerService.REVIEW_NOTIF_STATE_RESHOWN); 11133 mService.maybeShowInitialReviewPermissionsNotification(); 11134 verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG), 11135 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS), 11136 any(Notification.class)); 11137 } 11138 11139 @Test 11140 public void testRescheduledReviewPermissionsNotification() { 11141 mService.setShowReviewPermissionsNotification(true); 11142 reset(mMockNm); 11143 11144 // when rescheduled, the notification goes through the NotificationManagerInternal service 11145 // this call doesn't need to know anything about previously scheduled state -- if called, 11146 // it should send the notification & write the appropriate int to Settings 11147 mInternalService.sendReviewPermissionsNotification(); 11148 11149 // Notification should be sent 11150 verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG), 11151 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS), 11152 any(Notification.class)); 11153 11154 // write STATE_RESHOWN to settings 11155 assertEquals(NotificationManagerService.REVIEW_NOTIF_STATE_RESHOWN, 11156 Settings.Global.getInt(mContext.getContentResolver(), 11157 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 11158 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN)); 11159 } 11160 11161 @Test 11162 public void testRescheduledReviewPermissionsNotification_flagOff() { 11163 mService.setShowReviewPermissionsNotification(false); 11164 reset(mMockNm); 11165 11166 // no notification should be sent if the flag is off 11167 mInternalService.sendReviewPermissionsNotification(); 11168 verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class)); 11169 } 11170 11171 private void verifyStickyHun(Flag flag, int permissionState, boolean appRequested, 11172 boolean isSticky) throws Exception { 11173 11174 when(mPermissionHelper.hasRequestedPermission(Manifest.permission.USE_FULL_SCREEN_INTENT, 11175 PKG, mUserId)).thenReturn(appRequested); 11176 11177 mTestFlagResolver.setFlagOverride(flag, true); 11178 11179 when(mPermissionManager.checkPermissionForDataDelivery( 11180 eq(Manifest.permission.USE_FULL_SCREEN_INTENT), any(), any())) 11181 .thenReturn(permissionState); 11182 11183 Notification n = new Notification.Builder(mContext, "test") 11184 .setFullScreenIntent(mock(PendingIntent.class), true) 11185 .build(); 11186 11187 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11188 11189 final int stickyFlag = n.flags & Notification.FLAG_FSI_REQUESTED_BUT_DENIED; 11190 11191 if (isSticky) { 11192 assertNotSame(0, stickyFlag); 11193 } else { 11194 assertSame(0, stickyFlag); 11195 } 11196 } 11197 11198 @Test 11199 public void testFixNotification_flagEnableStickyHun_fsiPermissionHardDenied_showStickyHun() 11200 throws Exception { 11201 11202 verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, 11203 /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED, true, 11204 /* isSticky= */ true); 11205 } 11206 11207 @Test 11208 public void testFixNotification_flagEnableStickyHun_fsiPermissionSoftDenied_showStickyHun() 11209 throws Exception { 11210 11211 verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, 11212 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, true, 11213 /* isSticky= */ true); 11214 } 11215 11216 @Test 11217 public void testFixNotification_fsiPermissionSoftDenied_appNotRequest_noShowStickyHun() 11218 throws Exception { 11219 verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, 11220 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, false, 11221 /* isSticky= */ false); 11222 } 11223 11224 11225 @Test 11226 public void testFixNotification_flagEnableStickyHun_fsiPermissionGranted_showFsi() 11227 throws Exception { 11228 11229 verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, 11230 /* permissionState= */ PermissionManager.PERMISSION_GRANTED, true, 11231 /* isSticky= */ false); 11232 } 11233 11234 @Test 11235 public void testFixNotification_flagForceStickyHun_fsiPermissionHardDenied_showStickyHun() 11236 throws Exception { 11237 11238 verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, 11239 /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED, true, 11240 /* isSticky= */ true); 11241 } 11242 11243 @Test 11244 public void testFixNotification_flagForceStickyHun_fsiPermissionSoftDenied_showStickyHun() 11245 throws Exception { 11246 11247 verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, 11248 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, true, 11249 /* isSticky= */ true); 11250 } 11251 11252 @Test 11253 public void testFixNotification_flagForceStickyHun_fsiPermissionGranted_showStickyHun() 11254 throws Exception { 11255 11256 verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, 11257 /* permissionState= */ PermissionManager.PERMISSION_GRANTED, true, 11258 /* isSticky= */ true); 11259 } 11260 11261 @Test 11262 public void fixNotification_withFgsFlag_butIsNotFgs() throws Exception { 11263 final ApplicationInfo applicationInfo = new ApplicationInfo(); 11264 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 11265 .thenReturn(applicationInfo); 11266 11267 Notification n = new Notification.Builder(mContext, "test") 11268 .setFlag(FLAG_FOREGROUND_SERVICE, true) 11269 .setFlag(FLAG_CAN_COLORIZE, true) 11270 .build(); 11271 11272 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11273 11274 assertFalse(n.isForegroundService()); 11275 assertFalse(n.hasColorizedPermission()); 11276 } 11277 11278 @Test 11279 public void checkCallStyleNotification_withoutAnyValidUseCase_throws() throws Exception { 11280 Person person = new Person.Builder().setName("caller").build(); 11281 Notification n = new Notification.Builder(mContext, "test") 11282 .setStyle(Notification.CallStyle.forOngoingCall( 11283 person, mock(PendingIntent.class))) 11284 .build(); 11285 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11286 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11287 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11288 11289 try { 11290 mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11291 r.getSbn().getId(), r.getSbn().getTag(), r, false, false); 11292 assertFalse("CallStyle should not be allowed without a valid use case", true); 11293 } catch (IllegalArgumentException error) { 11294 assertThat(error.getMessage()).contains("CallStyle"); 11295 } 11296 } 11297 11298 @Test 11299 public void checkCallStyleNotification_allowedForFgs() throws Exception { 11300 Person person = new Person.Builder().setName("caller").build(); 11301 Notification n = new Notification.Builder(mContext, "test") 11302 .setFlag(FLAG_FOREGROUND_SERVICE, true) 11303 .setStyle(Notification.CallStyle.forOngoingCall( 11304 person, mock(PendingIntent.class))) 11305 .build(); 11306 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11307 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11308 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11309 11310 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11311 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 11312 } 11313 11314 @Test 11315 public void checkCallStyleNotification_allowedForByForegroundService() throws Exception { 11316 Person person = new Person.Builder().setName("caller").build(); 11317 Notification n = new Notification.Builder(mContext, "test") 11318 // Without FLAG_FOREGROUND_SERVICE. 11319 //.setFlag(FLAG_FOREGROUND_SERVICE, true) 11320 .setStyle(Notification.CallStyle.forOngoingCall( 11321 person, mock(PendingIntent.class))) 11322 .build(); 11323 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11324 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11325 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11326 11327 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11328 r.getSbn().getId(), r.getSbn().getTag(), r, false, 11329 true /* byForegroundService */)).isTrue(); 11330 } 11331 11332 @Test 11333 public void checkCallStyleNotification_allowedForUij() throws Exception { 11334 Person person = new Person.Builder().setName("caller").build(); 11335 Notification n = new Notification.Builder(mContext, "test") 11336 .setFlag(FLAG_USER_INITIATED_JOB, true) 11337 .setStyle(Notification.CallStyle.forOngoingCall( 11338 person, mock(PendingIntent.class))) 11339 .build(); 11340 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11341 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11342 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11343 11344 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11345 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 11346 } 11347 11348 @Test 11349 public void checkCallStyleNotification_allowedForFsiAllowed() throws Exception { 11350 Person person = new Person.Builder().setName("caller").build(); 11351 Notification n = new Notification.Builder(mContext, "test") 11352 .setFullScreenIntent(mock(PendingIntent.class), true) 11353 .setStyle(Notification.CallStyle.forOngoingCall( 11354 person, mock(PendingIntent.class))) 11355 .build(); 11356 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11357 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11358 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11359 11360 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11361 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 11362 } 11363 11364 @Test 11365 public void checkCallStyleNotification_allowedForFsiDenied() throws Exception { 11366 Person person = new Person.Builder().setName("caller").build(); 11367 Notification n = new Notification.Builder(mContext, "test") 11368 .setFlag(Notification.FLAG_FSI_REQUESTED_BUT_DENIED, true) 11369 .setStyle(Notification.CallStyle.forOngoingCall( 11370 person, mock(PendingIntent.class))) 11371 .build(); 11372 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, 11373 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11374 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 11375 11376 assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), 11377 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); 11378 } 11379 11380 @Test 11381 public void fixSystemNotification_withOnGoingFlag_shouldBeDismissible() 11382 throws Exception { 11383 final ApplicationInfo ai = new ApplicationInfo(); 11384 ai.packageName = "pkg"; 11385 ai.uid = mUid; 11386 ai.flags |= ApplicationInfo.FLAG_SYSTEM; 11387 11388 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 11389 .thenReturn(ai); 11390 when(mAppOpsManager.checkOpNoThrow( 11391 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid, 11392 ai.packageName)).thenReturn(AppOpsManager.MODE_IGNORED); 11393 // Given: a notification from an app on the system partition has the flag 11394 // FLAG_ONGOING_EVENT set 11395 Notification n = new Notification.Builder(mContext, "test") 11396 .setOngoing(true) 11397 .build(); 11398 11399 // When: fix the notification with NotificationManagerService 11400 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11401 11402 // Then: the notification's flag FLAG_NO_DISMISS should not be set 11403 assertSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11404 } 11405 11406 @Test 11407 public void fixMediaNotification_withOnGoingFlag_shouldBeNonDismissible() 11408 throws Exception { 11409 // Given: a media notification has the flag FLAG_ONGOING_EVENT set 11410 Notification n = new Notification.Builder(mContext, "test") 11411 .setOngoing(true) 11412 .setStyle(new Notification.MediaStyle() 11413 .setMediaSession(mock(MediaSession.Token.class))) 11414 .build(); 11415 11416 // When: fix the notification with NotificationManagerService 11417 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11418 11419 // Then: the notification's flag FLAG_NO_DISMISS should be set 11420 assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11421 } 11422 11423 @Test 11424 public void fixSystemNotification_defaultSearchSelectior_withOnGoingFlag_nondismissible() 11425 throws Exception { 11426 final ApplicationInfo ai = new ApplicationInfo(); 11427 ai.packageName = SEARCH_SELECTOR_PKG; 11428 ai.uid = mUid; 11429 ai.flags |= ApplicationInfo.FLAG_SYSTEM; 11430 11431 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 11432 .thenReturn(ai); 11433 when(mAppOpsManager.checkOpNoThrow( 11434 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid, 11435 ai.packageName)).thenReturn(AppOpsManager.MODE_IGNORED); 11436 // Given: a notification from an app on the system partition has the flag 11437 // FLAG_ONGOING_EVENT set 11438 Notification n = new Notification.Builder(mContext, "test") 11439 .setOngoing(true) 11440 .build(); 11441 11442 // When: fix the notification with NotificationManagerService 11443 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11444 11445 // Then: the notification's flag FLAG_NO_DISMISS should be set 11446 assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11447 } 11448 11449 @Test 11450 public void fixCallNotification_withOnGoingFlag_shouldNotBeNonDismissible() 11451 throws Exception { 11452 // Given: a call notification has the flag FLAG_ONGOING_EVENT set 11453 Person person = new Person.Builder() 11454 .setName("caller") 11455 .build(); 11456 Notification n = new Notification.Builder(mContext, "test") 11457 .setOngoing(true) 11458 .setStyle(Notification.CallStyle.forOngoingCall( 11459 person, mock(PendingIntent.class))) 11460 .build(); 11461 11462 // When: fix the notification with NotificationManagerService 11463 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11464 11465 // Then: the notification's flag FLAG_NO_DISMISS should be set 11466 assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11467 } 11468 11469 11470 @Test 11471 public void fixNonExemptNotification_withOnGoingFlag_shouldBeDismissible() throws Exception { 11472 // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set 11473 Notification n = new Notification.Builder(mContext, "test") 11474 .setOngoing(true) 11475 .build(); 11476 11477 // When: fix the notification with NotificationManagerService 11478 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11479 11480 // Then: the notification's flag FLAG_NO_DISMISS should not be set 11481 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11482 } 11483 11484 @Test 11485 public void fixNonExemptNotification_withNoDismissFlag_shouldBeDismissible() 11486 throws Exception { 11487 // Given: a non-exempt notification has the flag FLAG_NO_DISMISS set (even though this is 11488 // not allowed) 11489 Notification n = new Notification.Builder(mContext, "test") 11490 .build(); 11491 n.flags |= Notification.FLAG_NO_DISMISS; 11492 11493 // When: fix the notification with NotificationManagerService 11494 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11495 11496 // Then: the notification's flag FLAG_NO_DISMISS should be cleared 11497 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11498 } 11499 11500 @Test 11501 public void fixMediaNotification_withoutOnGoingFlag_shouldBeDismissible() throws Exception { 11502 // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set 11503 Notification n = new Notification.Builder(mContext, "test") 11504 .setOngoing(false) 11505 .setStyle(new Notification.MediaStyle() 11506 .setMediaSession(mock(MediaSession.Token.class))) 11507 .build(); 11508 11509 // When: fix the notification with NotificationManagerService 11510 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11511 11512 // Then: the notification's flag FLAG_NO_DISMISS should not be set 11513 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11514 } 11515 11516 @Test 11517 public void fixMediaNotification_withoutOnGoingFlag_withNoDismissFlag_shouldBeDismissible() 11518 throws Exception { 11519 // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set, 11520 // but has the flag FLAG_NO_DISMISS set 11521 Notification n = new Notification.Builder(mContext, "test") 11522 .setOngoing(false) 11523 .setStyle(new Notification.MediaStyle() 11524 .setMediaSession(mock(MediaSession.Token.class))) 11525 .build(); 11526 n.flags |= Notification.FLAG_NO_DISMISS; 11527 11528 // When: fix the notification with NotificationManagerService 11529 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11530 11531 // Then: the notification's flag FLAG_NO_DISMISS should be cleared 11532 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11533 } 11534 11535 @Test 11536 public void fixNonExempt_Notification_withoutOnGoingFlag_shouldBeDismissible() 11537 throws Exception { 11538 // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set 11539 Notification n = new Notification.Builder(mContext, "test") 11540 .setOngoing(false) 11541 .build(); 11542 11543 // When: fix the notification with NotificationManagerService 11544 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11545 11546 // Then: the notification's flag FLAG_NO_DISMISS should not be set 11547 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11548 } 11549 11550 @Test 11551 public void fixOrganizationAdminNotification_withOnGoingFlag_shouldBeNonDismissible() 11552 throws Exception { 11553 when(mDevicePolicyManager.isActiveDeviceOwner(mUid)).thenReturn(true); 11554 // Given: a notification has the flag FLAG_ONGOING_EVENT set 11555 setDpmAppOppsExemptFromDismissal(false); 11556 Notification n = new Notification.Builder(mContext, "test") 11557 .setOngoing(true) 11558 .build(); 11559 11560 // When: fix the notification with NotificationManagerService 11561 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11562 11563 // Then: the notification's flag FLAG_NO_DISMISS should be set 11564 assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11565 } 11566 11567 @Test 11568 public void fixExemptAppOpNotification_withFlag_shouldBeNonDismissible() 11569 throws Exception { 11570 final ApplicationInfo ai = new ApplicationInfo(); 11571 ai.packageName = PKG; 11572 ai.uid = mUid; 11573 ai.flags |= ApplicationInfo.FLAG_SYSTEM; 11574 11575 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 11576 .thenReturn(ai); 11577 when(mAppOpsManager.checkOpNoThrow( 11578 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid, 11579 PKG)).thenReturn(AppOpsManager.MODE_ALLOWED); 11580 // Given: a notification has the flag FLAG_ONGOING_EVENT set 11581 setDpmAppOppsExemptFromDismissal(true); 11582 Notification n = new Notification.Builder(mContext, "test") 11583 .setOngoing(true) 11584 .build(); 11585 11586 // When: fix the notification with NotificationManagerService 11587 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11588 11589 // Then: the notification's flag FLAG_NO_DISMISS should be cleared 11590 assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS); 11591 } 11592 11593 @Test 11594 public void fixExemptAppOpNotification_withoutAppOpsFlag_shouldBeDismissible() 11595 throws Exception { 11596 when(mAppOpsManager.checkOpNoThrow( 11597 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid, 11598 PKG)).thenReturn(AppOpsManager.MODE_ALLOWED); 11599 // Given: a notification has the flag FLAG_ONGOING_EVENT set 11600 setDpmAppOppsExemptFromDismissal(false); 11601 Notification n = new Notification.Builder(mContext, "test") 11602 .setOngoing(true) 11603 .build(); 11604 11605 // When: fix the notification with NotificationManagerService 11606 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 11607 11608 // Then: the notification's flag FLAG_NO_DISMISS should not be set 11609 assertSame(0, n.flags & Notification.FLAG_NO_DISMISS); 11610 } 11611 11612 @Test 11613 public void testCancelAllNotifications_IgnoreUserInitiatedJob() throws Exception { 11614 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11615 .thenReturn(true); 11616 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 11617 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11618 mBinderService.enqueueNotificationWithTag(PKG, PKG, 11619 "testCancelAllNotifications_IgnoreUserInitiatedJob", 11620 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11621 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 11622 waitForIdle(); 11623 StatusBarNotification[] notifs = 11624 mBinderService.getActiveNotifications(sbn.getPackageName()); 11625 assertEquals(1, notifs.length); 11626 assertEquals(1, mService.getNotificationRecordCount()); 11627 } 11628 11629 @Test 11630 public void testCancelAllNotifications_UijFlag_NoUij_Allowed() throws Exception { 11631 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11632 .thenReturn(false); 11633 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 11634 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11635 mBinderService.enqueueNotificationWithTag(PKG, PKG, 11636 "testCancelAllNotifications_UijFlag_NoUij_Allowed", 11637 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11638 mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); 11639 waitForIdle(); 11640 StatusBarNotification[] notifs = 11641 mBinderService.getActiveNotifications(sbn.getPackageName()); 11642 assertEquals(0, notifs.length); 11643 } 11644 11645 @Test 11646 public void testCancelAllNotificationsOtherPackage_IgnoresUijNotification() throws Exception { 11647 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11648 .thenReturn(true); 11649 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 11650 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11651 mBinderService.enqueueNotificationWithTag(PKG, PKG, 11652 "testCancelAllNotifications_IgnoreOtherPackages", 11653 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11654 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId()); 11655 waitForIdle(); 11656 StatusBarNotification[] notifs = 11657 mBinderService.getActiveNotifications(sbn.getPackageName()); 11658 assertEquals(1, notifs.length); 11659 assertEquals(1, mService.getNotificationRecordCount()); 11660 } 11661 11662 @Test 11663 public void testRemoveUserInitiatedJobFlag_ImmediatelyAfterEnqueue() throws Exception { 11664 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11665 .thenReturn(true); 11666 Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId()) 11667 .setSmallIcon(android.R.drawable.sym_def_app_icon) 11668 .build(); 11669 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0, 11670 n, UserHandle.getUserHandleForUid(mUid), null, 0); 11671 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11672 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, 11673 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11674 mInternalService.removeUserInitiatedJobFlagFromNotification(PKG, sbn.getId(), 11675 sbn.getUserId()); 11676 waitForIdle(); 11677 StatusBarNotification[] notifs = 11678 mBinderService.getActiveNotifications(sbn.getPackageName()); 11679 assertFalse(notifs[0].getNotification().isUserInitiatedJob()); 11680 } 11681 11682 @Test 11683 public void testCancelAfterSecondEnqueueDoesNotSpecifyUserInitiatedJobFlag() throws Exception { 11684 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 11685 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT | FLAG_USER_INITIATED_JOB; 11686 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 11687 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11688 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT; 11689 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), 11690 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 11691 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), 11692 sbn.getUserId()); 11693 waitForIdle(); 11694 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); 11695 assertEquals(0, mService.getNotificationRecordCount()); 11696 } 11697 11698 @Test 11699 public void testCancelNotificationWithTag_fromApp_cannotCancelUijChild() throws Exception { 11700 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11701 .thenReturn(true); 11702 mService.isSystemUid = false; 11703 mService.isSystemAppId = false; 11704 final NotificationRecord parent = generateNotificationRecord( 11705 mTestNotificationChannel, 1, "group", true); 11706 final NotificationRecord child = generateNotificationRecord( 11707 mTestNotificationChannel, 2, "group", false); 11708 final NotificationRecord child2 = generateNotificationRecord( 11709 mTestNotificationChannel, 3, "group", false); 11710 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11711 mService.addNotification(parent); 11712 mService.addNotification(child); 11713 mService.addNotification(child2); 11714 mService.getBinderService().cancelNotificationWithTag( 11715 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 11716 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 11717 waitForIdle(); 11718 StatusBarNotification[] notifs = 11719 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11720 assertEquals(1, notifs.length); 11721 } 11722 11723 @Test 11724 public void testCancelNotificationWithTag_fromApp_cannotCancelUijParent() throws Exception { 11725 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11726 .thenReturn(true); 11727 mService.isSystemUid = false; 11728 mService.isSystemAppId = false; 11729 final NotificationRecord parent = generateNotificationRecord( 11730 mTestNotificationChannel, 1, "group", true); 11731 parent.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11732 final NotificationRecord child = generateNotificationRecord( 11733 mTestNotificationChannel, 2, "group", false); 11734 final NotificationRecord child2 = generateNotificationRecord( 11735 mTestNotificationChannel, 3, "group", false); 11736 mService.addNotification(parent); 11737 mService.addNotification(child); 11738 mService.addNotification(child2); 11739 mService.getBinderService().cancelNotificationWithTag( 11740 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(), 11741 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId()); 11742 waitForIdle(); 11743 StatusBarNotification[] notifs = 11744 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11745 assertEquals(3, notifs.length); 11746 } 11747 11748 @Test 11749 public void testCancelAllNotificationsFromApp_cannotCancelUijChild() throws Exception { 11750 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11751 .thenReturn(true); 11752 mService.isSystemUid = false; 11753 mService.isSystemAppId = false; 11754 final NotificationRecord parent = generateNotificationRecord( 11755 mTestNotificationChannel, 1, "group", true); 11756 final NotificationRecord child = generateNotificationRecord( 11757 mTestNotificationChannel, 2, "group", false); 11758 final NotificationRecord child2 = generateNotificationRecord( 11759 mTestNotificationChannel, 3, "group", false); 11760 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11761 final NotificationRecord newGroup = generateNotificationRecord( 11762 mTestNotificationChannel, 4, "group2", false); 11763 mService.addNotification(parent); 11764 mService.addNotification(child); 11765 mService.addNotification(child2); 11766 mService.addNotification(newGroup); 11767 mService.getBinderService().cancelAllNotifications( 11768 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 11769 waitForIdle(); 11770 StatusBarNotification[] notifs = 11771 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11772 assertEquals(1, notifs.length); 11773 } 11774 11775 @Test 11776 public void testCancelAllNotifications_fromApp_cannotCancelUijParent() throws Exception { 11777 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11778 .thenReturn(true); 11779 mService.isSystemUid = false; 11780 mService.isSystemAppId = false; 11781 final NotificationRecord parent = generateNotificationRecord( 11782 mTestNotificationChannel, 1, "group", true); 11783 parent.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11784 final NotificationRecord child = generateNotificationRecord( 11785 mTestNotificationChannel, 2, "group", false); 11786 final NotificationRecord child2 = generateNotificationRecord( 11787 mTestNotificationChannel, 3, "group", false); 11788 final NotificationRecord newGroup = generateNotificationRecord( 11789 mTestNotificationChannel, 4, "group2", false); 11790 mService.addNotification(parent); 11791 mService.addNotification(child); 11792 mService.addNotification(child2); 11793 mService.addNotification(newGroup); 11794 mService.getBinderService().cancelAllNotifications( 11795 parent.getSbn().getPackageName(), parent.getSbn().getUserId()); 11796 waitForIdle(); 11797 StatusBarNotification[] notifs = 11798 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11799 assertEquals(1, notifs.length); 11800 } 11801 11802 @Test 11803 public void testCancelNotificationsFromListener_clearAll_GroupWithUijParent() throws Exception { 11804 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11805 .thenReturn(true); 11806 final NotificationRecord parent = generateNotificationRecord( 11807 mTestNotificationChannel, 1, "group", true); 11808 parent.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11809 final NotificationRecord child = generateNotificationRecord( 11810 mTestNotificationChannel, 2, "group", false); 11811 final NotificationRecord child2 = generateNotificationRecord( 11812 mTestNotificationChannel, 3, "group", false); 11813 final NotificationRecord newGroup = generateNotificationRecord( 11814 mTestNotificationChannel, 4, "group2", false); 11815 mService.addNotification(parent); 11816 mService.addNotification(child); 11817 mService.addNotification(child2); 11818 mService.addNotification(newGroup); 11819 mService.getBinderService().cancelNotificationsFromListener(null, null); 11820 waitForIdle(); 11821 StatusBarNotification[] notifs = 11822 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11823 assertEquals(0, notifs.length); 11824 } 11825 11826 @Test 11827 public void testCancelNotificationsFromListener_clearAll_GroupWithUijChild() throws Exception { 11828 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11829 .thenReturn(true); 11830 final NotificationRecord parent = generateNotificationRecord( 11831 mTestNotificationChannel, 1, "group", true); 11832 final NotificationRecord child = generateNotificationRecord( 11833 mTestNotificationChannel, 2, "group", false); 11834 final NotificationRecord child2 = generateNotificationRecord( 11835 mTestNotificationChannel, 3, "group", false); 11836 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11837 final NotificationRecord newGroup = generateNotificationRecord( 11838 mTestNotificationChannel, 4, "group2", false); 11839 mService.addNotification(parent); 11840 mService.addNotification(child); 11841 mService.addNotification(child2); 11842 mService.addNotification(newGroup); 11843 mService.getBinderService().cancelNotificationsFromListener(null, null); 11844 waitForIdle(); 11845 StatusBarNotification[] notifs = 11846 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11847 assertEquals(0, notifs.length); 11848 } 11849 11850 @Test 11851 public void testCancelNotificationsFromListener_clearAll_Uij() throws Exception { 11852 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11853 .thenReturn(true); 11854 final NotificationRecord child2 = generateNotificationRecord( 11855 mTestNotificationChannel, 3, null, false); 11856 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11857 mService.addNotification(child2); 11858 mService.getBinderService().cancelNotificationsFromListener(null, null); 11859 waitForIdle(); 11860 StatusBarNotification[] notifs = 11861 mBinderService.getActiveNotifications(child2.getSbn().getPackageName()); 11862 assertEquals(0, notifs.length); 11863 } 11864 11865 @Test 11866 public void testCancelNotificationsFromListener_byKey_GroupWithUijParent() throws Exception { 11867 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11868 .thenReturn(true); 11869 final NotificationRecord parent = generateNotificationRecord( 11870 mTestNotificationChannel, 1, "group", true); 11871 parent.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11872 final NotificationRecord child = generateNotificationRecord( 11873 mTestNotificationChannel, 2, "group", false); 11874 final NotificationRecord child2 = generateNotificationRecord( 11875 mTestNotificationChannel, 3, "group", false); 11876 final NotificationRecord newGroup = generateNotificationRecord( 11877 mTestNotificationChannel, 4, "group2", false); 11878 mService.addNotification(parent); 11879 mService.addNotification(child); 11880 mService.addNotification(child2); 11881 mService.addNotification(newGroup); 11882 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 11883 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 11884 mService.getBinderService().cancelNotificationsFromListener(null, keys); 11885 waitForIdle(); 11886 StatusBarNotification[] notifs = 11887 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11888 assertEquals(0, notifs.length); 11889 } 11890 11891 @Test 11892 public void testCancelNotificationsFromListener_byKey_GroupWithUijChild() throws Exception { 11893 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11894 .thenReturn(true); 11895 final NotificationRecord parent = generateNotificationRecord( 11896 mTestNotificationChannel, 1, "group", true); 11897 final NotificationRecord child = generateNotificationRecord( 11898 mTestNotificationChannel, 2, "group", false); 11899 final NotificationRecord child2 = generateNotificationRecord( 11900 mTestNotificationChannel, 3, "group", false); 11901 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11902 final NotificationRecord newGroup = generateNotificationRecord( 11903 mTestNotificationChannel, 4, "group2", false); 11904 mService.addNotification(parent); 11905 mService.addNotification(child); 11906 mService.addNotification(child2); 11907 mService.addNotification(newGroup); 11908 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(), 11909 child2.getSbn().getKey(), newGroup.getSbn().getKey()}; 11910 mService.getBinderService().cancelNotificationsFromListener(null, keys); 11911 waitForIdle(); 11912 StatusBarNotification[] notifs = 11913 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11914 assertEquals(0, notifs.length); 11915 } 11916 11917 @Test 11918 public void testCancelNotificationsFromListener_byKey_Uij() throws Exception { 11919 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11920 .thenReturn(true); 11921 final NotificationRecord child = generateNotificationRecord( 11922 mTestNotificationChannel, 3, null, false); 11923 child.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11924 mService.addNotification(child); 11925 String[] keys = {child.getSbn().getKey()}; 11926 mService.getBinderService().cancelNotificationsFromListener(null, keys); 11927 waitForIdle(); 11928 StatusBarNotification[] notifs = 11929 mBinderService.getActiveNotifications(child.getSbn().getPackageName()); 11930 assertEquals(0, notifs.length); 11931 } 11932 11933 @Test 11934 public void testUserInitiatedCancelAllWithGroup_UserInitiatedFlag() throws Exception { 11935 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 11936 .thenReturn(true); 11937 final NotificationRecord parent = generateNotificationRecord( 11938 mTestNotificationChannel, 1, "group", true); 11939 final NotificationRecord child = generateNotificationRecord( 11940 mTestNotificationChannel, 2, "group", false); 11941 final NotificationRecord child2 = generateNotificationRecord( 11942 mTestNotificationChannel, 3, "group", false); 11943 child2.getNotification().flags |= FLAG_USER_INITIATED_JOB; 11944 final NotificationRecord newGroup = generateNotificationRecord( 11945 mTestNotificationChannel, 4, "group2", false); 11946 mService.addNotification(parent); 11947 mService.addNotification(child); 11948 mService.addNotification(child2); 11949 mService.addNotification(newGroup); 11950 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), parent.getUserId()); 11951 waitForIdle(); 11952 StatusBarNotification[] notifs = 11953 mBinderService.getActiveNotifications(parent.getSbn().getPackageName()); 11954 assertEquals(0, notifs.length); 11955 } 11956 11957 @Test 11958 public void testDeleteChannelGroupChecksForUijs() throws Exception { 11959 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) 11960 .thenReturn(singletonList(mock(AssociationInfo.class))); 11961 CountDownLatch latch = new CountDownLatch(2); 11962 mService.createNotificationChannelGroup(PKG, mUid, 11963 new NotificationChannelGroup("group", "group"), true, false); 11964 new Thread(() -> { 11965 NotificationChannel notificationChannel = new NotificationChannel("id", "id", 11966 NotificationManager.IMPORTANCE_HIGH); 11967 notificationChannel.setGroup("group"); 11968 ParceledListSlice<NotificationChannel> pls = 11969 new ParceledListSlice(ImmutableList.of(notificationChannel)); 11970 try { 11971 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); 11972 } catch (RemoteException e) { 11973 throw new RuntimeException(e); 11974 } 11975 latch.countDown(); 11976 }).start(); 11977 new Thread(() -> { 11978 try { 11979 synchronized (this) { 11980 wait(5000); 11981 } 11982 mService.createNotificationChannelGroup(PKG, mUid, 11983 new NotificationChannelGroup("new", "new group"), true, false); 11984 NotificationChannel notificationChannel = 11985 new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH); 11986 notificationChannel.setGroup("new"); 11987 ParceledListSlice<NotificationChannel> pls = 11988 new ParceledListSlice(ImmutableList.of(notificationChannel)); 11989 try { 11990 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); 11991 mBinderService.deleteNotificationChannelGroup(PKG, "group"); 11992 } catch (RemoteException e) { 11993 throw new RuntimeException(e); 11994 } 11995 } catch (Exception e) { 11996 e.printStackTrace(); 11997 } 11998 latch.countDown(); 11999 }).start(); 12000 12001 latch.await(); 12002 verify(mJsi).isNotificationChannelAssociatedWithAnyUserInitiatedJobs( 12003 anyString(), anyInt(), anyString()); 12004 } 12005 12006 @Test 12007 public void testRemoveUserInitiatedJobFlagFromNotification_enqueued() { 12008 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12009 .thenReturn(true); 12010 Notification n = new Notification.Builder(mContext, "").build(); 12011 n.flags |= FLAG_USER_INITIATED_JOB; 12012 12013 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 12014 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12015 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12016 12017 mService.addEnqueuedNotification(r); 12018 12019 mInternalService.removeUserInitiatedJobFlagFromNotification( 12020 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 12021 12022 waitForIdle(); 12023 12024 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any()); 12025 } 12026 12027 @Test 12028 public void testRemoveUserInitiatedJobFlagFromNotification_posted() { 12029 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12030 .thenReturn(true); 12031 Notification n = new Notification.Builder(mContext, "").build(); 12032 n.flags |= FLAG_USER_INITIATED_JOB; 12033 12034 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0, 12035 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12036 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12037 12038 mService.addNotification(r); 12039 12040 mInternalService.removeUserInitiatedJobFlagFromNotification( 12041 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 12042 12043 waitForIdle(); 12044 12045 ArgumentCaptor<NotificationRecord> captor = 12046 ArgumentCaptor.forClass(NotificationRecord.class); 12047 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any()); 12048 12049 assertEquals(0, captor.getValue().getNotification().flags); 12050 } 12051 12052 @Test 12053 public void testCannotRemoveUserInitiatedJobFlagWhenOverLimit_enqueued() { 12054 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 12055 Notification n = new Notification.Builder(mContext, "").build(); 12056 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0, 12057 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12058 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12059 mService.addEnqueuedNotification(r); 12060 } 12061 Notification n = new Notification.Builder(mContext, "").build(); 12062 n.flags |= FLAG_USER_INITIATED_JOB; 12063 12064 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 12065 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0, 12066 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12067 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12068 12069 mService.addEnqueuedNotification(r); 12070 12071 mInternalService.removeUserInitiatedJobFlagFromNotification( 12072 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 12073 12074 waitForIdle(); 12075 12076 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, 12077 mService.getNotificationRecordCount()); 12078 } 12079 12080 @Test 12081 public void testCannotRemoveUserInitiatedJobFlagWhenOverLimit_posted() { 12082 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12083 .thenReturn(true); 12084 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 12085 Notification n = new Notification.Builder(mContext, "").build(); 12086 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0, 12087 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12088 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12089 mService.addNotification(r); 12090 } 12091 Notification n = new Notification.Builder(mContext, "").build(); 12092 n.flags |= FLAG_USER_INITIATED_JOB; 12093 12094 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 12095 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0, 12096 n, UserHandle.getUserHandleForUid(mUid), null, 0); 12097 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); 12098 12099 mService.addNotification(r); 12100 12101 mInternalService.removeUserInitiatedJobFlagFromNotification( 12102 PKG, r.getSbn().getId(), r.getSbn().getUserId()); 12103 12104 waitForIdle(); 12105 12106 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, 12107 mService.getNotificationRecordCount()); 12108 } 12109 12110 @Test 12111 public void testCanPostUijWhenOverLimit() throws RemoteException { 12112 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12113 .thenReturn(true); 12114 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 12115 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 12116 i, null, false).getSbn(); 12117 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testCanPostUijWhenOverLimit", 12118 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 12119 } 12120 12121 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); 12122 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12123 mBinderService.enqueueNotificationWithTag(PKG, PKG, 12124 "testCanPostUijWhenOverLimit - uij over limit!", 12125 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 12126 12127 waitForIdle(); 12128 12129 StatusBarNotification[] notifs = 12130 mBinderService.getActiveNotifications(sbn.getPackageName()); 12131 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); 12132 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, 12133 mService.getNotificationRecordCount()); 12134 } 12135 12136 @Test 12137 public void testCannotPostNonUijWhenOverLimit() throws RemoteException { 12138 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12139 .thenReturn(true); 12140 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { 12141 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 12142 i, null, false).getSbn(); 12143 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testCannotPostNonUijWhenOverLimit", 12144 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 12145 waitForIdle(); 12146 } 12147 12148 final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, 12149 100, null, false).getSbn(); 12150 sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12151 mBinderService.enqueueNotificationWithTag(PKG, PKG, 12152 "testCannotPostNonUijWhenOverLimit - uij over limit!", 12153 sbn.getId(), sbn.getNotification(), sbn.getUserId()); 12154 12155 final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel, 12156 101, null, false).getSbn(); 12157 mBinderService.enqueueNotificationWithTag(PKG, PKG, 12158 "testCannotPostNonUijWhenOverLimit - non uij over limit!", 12159 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId()); 12160 12161 when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString())) 12162 .thenReturn(false); 12163 final StatusBarNotification sbn3 = generateNotificationRecord(mTestNotificationChannel, 12164 101, null, false).getSbn(); 12165 sbn3.getNotification().flags |= FLAG_USER_INITIATED_JOB; 12166 mBinderService.enqueueNotificationWithTag(PKG, PKG, 12167 "testCannotPostNonUijWhenOverLimit - fake uij over limit!", 12168 sbn3.getId(), sbn3.getNotification(), sbn3.getUserId()); 12169 12170 waitForIdle(); 12171 12172 StatusBarNotification[] notifs = 12173 mBinderService.getActiveNotifications(sbn.getPackageName()); 12174 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); 12175 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, 12176 mService.getNotificationRecordCount()); 12177 } 12178 12179 @Test 12180 public void fixNotification_withUijFlag_butIsNotUij() throws Exception { 12181 final ApplicationInfo applicationInfo = new ApplicationInfo(); 12182 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 12183 .thenReturn(applicationInfo); 12184 12185 Notification n = new Notification.Builder(mContext, "test") 12186 .setFlag(FLAG_USER_INITIATED_JOB, true) 12187 .build(); 12188 12189 mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); 12190 assertFalse(n.isUserInitiatedJob()); 12191 } 12192 12193 @Test 12194 public void enqueue_updatesEnqueueRate() throws Exception { 12195 Notification n = generateNotificationRecord(null).getNotification(); 12196 12197 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId); 12198 // Don't waitForIdle() here. We want to verify the "intermediate" state. 12199 12200 verify(mUsageStats).registerEnqueuedByApp(eq(PKG)); 12201 verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG)); 12202 verify(mUsageStats, never()).registerPostedByApp(any()); 12203 12204 waitForIdle(); 12205 } 12206 12207 @Test 12208 public void enqueue_withPost_updatesEnqueueRateAndPost() throws Exception { 12209 Notification n = generateNotificationRecord(null).getNotification(); 12210 12211 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId); 12212 waitForIdle(); 12213 12214 verify(mUsageStats).registerEnqueuedByApp(eq(PKG)); 12215 verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG)); 12216 verify(mUsageStats).registerPostedByApp(any()); 12217 } 12218 12219 @Test 12220 public void enqueueNew_whenOverEnqueueRate_accepts() throws Exception { 12221 Notification n = generateNotificationRecord(null).getNotification(); 12222 when(mUsageStats.getAppEnqueueRate(eq(PKG))) 12223 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE + 1f); 12224 12225 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId); 12226 waitForIdle(); 12227 12228 assertThat(mService.mNotificationsByKey).hasSize(1); 12229 verify(mUsageStats).registerEnqueuedByApp(eq(PKG)); 12230 verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG)); 12231 verify(mUsageStats).registerPostedByApp(any()); 12232 } 12233 12234 @Test 12235 public void enqueueUpdate_whenBelowMaxEnqueueRate_accepts() throws Exception { 12236 // Post the first version. 12237 Notification original = generateNotificationRecord(null).getNotification(); 12238 original.when = 111; 12239 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, original, mUserId); 12240 waitForIdle(); 12241 assertThat(mService.mNotificationList).hasSize(1); 12242 assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111); 12243 12244 reset(mUsageStats); 12245 when(mUsageStats.getAppEnqueueRate(eq(PKG))) 12246 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE - 1f); 12247 12248 // Post the update. 12249 Notification update = generateNotificationRecord(null).getNotification(); 12250 update.when = 222; 12251 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, update, mUserId); 12252 waitForIdle(); 12253 12254 verify(mUsageStats).registerEnqueuedByApp(eq(PKG)); 12255 verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG)); 12256 verify(mUsageStats, never()).registerPostedByApp(any()); 12257 verify(mUsageStats).registerUpdatedByApp(any(), any()); 12258 assertThat(mService.mNotificationList).hasSize(1); 12259 assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(222); 12260 } 12261 12262 @Test 12263 public void enqueueUpdate_whenAboveMaxEnqueueRate_rejects() throws Exception { 12264 // Post the first version. 12265 Notification original = generateNotificationRecord(null).getNotification(); 12266 original.when = 111; 12267 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, original, mUserId); 12268 waitForIdle(); 12269 assertThat(mService.mNotificationList).hasSize(1); 12270 assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111); 12271 12272 reset(mUsageStats); 12273 when(mUsageStats.getAppEnqueueRate(eq(PKG))) 12274 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE + 1f); 12275 12276 // Post the update. 12277 Notification update = generateNotificationRecord(null).getNotification(); 12278 update.when = 222; 12279 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, update, mUserId); 12280 waitForIdle(); 12281 12282 verify(mUsageStats).registerEnqueuedByApp(eq(PKG)); 12283 verify(mUsageStats, never()).registerEnqueuedByAppAndAccepted(any()); 12284 verify(mUsageStats, never()).registerPostedByApp(any()); 12285 verify(mUsageStats, never()).registerUpdatedByApp(any(), any()); 12286 assertThat(mService.mNotificationList).hasSize(1); 12287 assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111); // old 12288 } 12289 12290 @Test 12291 public void enqueueNotification_allowlistsPendingIntents() throws RemoteException { 12292 PendingIntent contentIntent = createPendingIntent("content"); 12293 PendingIntent actionIntent1 = createPendingIntent("action1"); 12294 PendingIntent actionIntent2 = createPendingIntent("action2"); 12295 Notification n = new Notification.Builder(mContext, TEST_CHANNEL_ID) 12296 .setContentIntent(contentIntent) 12297 .addAction(new Notification.Action.Builder(null, "action1", actionIntent1).build()) 12298 .addAction(new Notification.Action.Builder(null, "action2", actionIntent2).build()) 12299 .build(); 12300 12301 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1, 12302 parcelAndUnparcel(n, Notification.CREATOR), mUserId); 12303 12304 verify(mAmi, times(3)).setPendingIntentAllowlistDuration( 12305 any(), any(), anyLong(), 12306 eq(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED), 12307 eq(REASON_NOTIFICATION_SERVICE), any()); 12308 verify(mAmi, times(3)).setPendingIntentAllowBgActivityStarts(any(), 12309 any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER)); 12310 } 12311 12312 @Test 12313 public void enqueueNotification_allowlistsPendingIntents_includingFromPublicVersion() 12314 throws RemoteException { 12315 PendingIntent contentIntent = createPendingIntent("content"); 12316 PendingIntent actionIntent = createPendingIntent("action"); 12317 PendingIntent publicContentIntent = createPendingIntent("publicContent"); 12318 PendingIntent publicActionIntent = createPendingIntent("publicAction"); 12319 Notification source = new Notification.Builder(mContext, TEST_CHANNEL_ID) 12320 .setContentIntent(contentIntent) 12321 .addAction(new Notification.Action.Builder(null, "action", actionIntent).build()) 12322 .setPublicVersion(new Notification.Builder(mContext, "channel") 12323 .setContentIntent(publicContentIntent) 12324 .addAction(new Notification.Action.Builder( 12325 null, "publicAction", publicActionIntent).build()) 12326 .build()) 12327 .build(); 12328 12329 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1, 12330 parcelAndUnparcel(source, Notification.CREATOR), mUserId); 12331 12332 verify(mAmi, times(4)).setPendingIntentAllowlistDuration( 12333 any(), any(), anyLong(), 12334 eq(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED), 12335 eq(REASON_NOTIFICATION_SERVICE), any()); 12336 verify(mAmi, times(4)).setPendingIntentAllowBgActivityStarts(any(), 12337 any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER)); 12338 } 12339 12340 @Test 12341 public void onUserSwitched_updatesZenModeAndChannelsBypassingDnd() { 12342 Intent intent = new Intent(Intent.ACTION_USER_SWITCHED); 12343 intent.putExtra(Intent.EXTRA_USER_HANDLE, 20); 12344 mService.mZenModeHelper = mock(ZenModeHelper.class); 12345 mService.setPreferencesHelper(mPreferencesHelper); 12346 12347 mUserSwitchIntentReceiver.onReceive(mContext, intent); 12348 12349 InOrder inOrder = inOrder(mPreferencesHelper, mService.mZenModeHelper); 12350 inOrder.verify(mService.mZenModeHelper).onUserSwitched(eq(20)); 12351 inOrder.verify(mPreferencesHelper).syncChannelsBypassingDnd(); 12352 inOrder.verifyNoMoreInteractions(); 12353 } 12354 12355 @Test 12356 public void isNotificationPolicyAccessGranted_invalidPackage() throws Exception { 12357 final String notReal = "NOT REAL"; 12358 final var checker = mService.permissionChecker; 12359 12360 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow( 12361 PackageManager.NameNotFoundException.class); 12362 12363 assertThat(mBinderService.isNotificationPolicyAccessGranted(notReal)).isFalse(); 12364 verify(mPackageManagerClient).getPackageUidAsUser(eq(notReal), anyInt()); 12365 verify(checker, never()).check(any(), anyInt(), anyInt(), anyBoolean()); 12366 verify(mConditionProviders, never()).isPackageOrComponentAllowed(eq(notReal), anyInt()); 12367 verify(mListeners, never()).isComponentEnabledForPackage(any()); 12368 verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt()); 12369 } 12370 12371 @Test 12372 public void isNotificationPolicyAccessGranted_hasPermission() throws Exception { 12373 final String packageName = "target"; 12374 final int uid = 123; 12375 final var checker = mService.permissionChecker; 12376 12377 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12378 when(checker.check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true)) 12379 .thenReturn(PackageManager.PERMISSION_GRANTED); 12380 12381 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue(); 12382 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12383 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12384 verify(mConditionProviders, never()).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12385 verify(mListeners, never()).isComponentEnabledForPackage(any()); 12386 verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt()); 12387 } 12388 12389 @Test 12390 public void isNotificationPolicyAccessGranted_isPackageAllowed() throws Exception { 12391 final String packageName = "target"; 12392 final int uid = 123; 12393 final var checker = mService.permissionChecker; 12394 12395 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12396 when(mConditionProviders.isPackageOrComponentAllowed(eq(packageName), anyInt())) 12397 .thenReturn(true); 12398 12399 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue(); 12400 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12401 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12402 verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12403 verify(mListeners, never()).isComponentEnabledForPackage(any()); 12404 verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt()); 12405 } 12406 12407 @Test 12408 public void isNotificationPolicyAccessGranted_isComponentEnabled() throws Exception { 12409 final String packageName = "target"; 12410 final int uid = 123; 12411 final var checker = mService.permissionChecker; 12412 12413 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12414 when(mListeners.isComponentEnabledForPackage(packageName)).thenReturn(true); 12415 12416 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue(); 12417 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12418 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12419 verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12420 verify(mListeners).isComponentEnabledForPackage(packageName); 12421 verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt()); 12422 } 12423 12424 @Test 12425 public void isNotificationPolicyAccessGranted_isDeviceOwner() throws Exception { 12426 final String packageName = "target"; 12427 final int uid = 123; 12428 final var checker = mService.permissionChecker; 12429 12430 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12431 when(mDevicePolicyManager.isActiveDeviceOwner(uid)).thenReturn(true); 12432 12433 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue(); 12434 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12435 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12436 verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12437 verify(mListeners).isComponentEnabledForPackage(packageName); 12438 verify(mDevicePolicyManager).isActiveDeviceOwner(uid); 12439 } 12440 12441 /** 12442 * b/292163859 12443 */ 12444 @Test 12445 public void isNotificationPolicyAccessGranted_callerIsDeviceOwner() throws Exception { 12446 final String packageName = "target"; 12447 final int uid = 123; 12448 final int callingUid = Binder.getCallingUid(); 12449 final var checker = mService.permissionChecker; 12450 12451 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12452 when(mDevicePolicyManager.isActiveDeviceOwner(callingUid)).thenReturn(true); 12453 12454 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isFalse(); 12455 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12456 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12457 verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12458 verify(mListeners).isComponentEnabledForPackage(packageName); 12459 verify(mDevicePolicyManager).isActiveDeviceOwner(uid); 12460 verify(mDevicePolicyManager, never()).isActiveDeviceOwner(callingUid); 12461 } 12462 12463 @Test 12464 public void isNotificationPolicyAccessGranted_notGranted() throws Exception { 12465 final String packageName = "target"; 12466 final int uid = 123; 12467 final var checker = mService.permissionChecker; 12468 12469 when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 12470 12471 assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isFalse(); 12472 verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt()); 12473 verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true); 12474 verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt()); 12475 verify(mListeners).isComponentEnabledForPackage(packageName); 12476 verify(mDevicePolicyManager).isActiveDeviceOwner(uid); 12477 } 12478 12479 private static <T extends Parcelable> T parcelAndUnparcel(T source, 12480 Parcelable.Creator<T> creator) { 12481 Parcel parcel = Parcel.obtain(); 12482 source.writeToParcel(parcel, 0); 12483 parcel.setDataPosition(0); 12484 return creator.createFromParcel(parcel); 12485 } 12486 12487 private PendingIntent createPendingIntent(String action) { 12488 return PendingIntent.getActivity(mContext, 0, 12489 new Intent(action).setPackage(mContext.getPackageName()), 12490 PendingIntent.FLAG_MUTABLE); 12491 } 12492 12493 private void setDpmAppOppsExemptFromDismissal(boolean isOn) { 12494 DeviceConfig.setProperty( 12495 DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER, 12496 /* name= */ "application_exemptions", 12497 String.valueOf(isOn), 12498 /* makeDefault= */ false); 12499 } 12500 12501 private void allowTestPackageToToast() throws Exception { 12502 assertWithMessage("toast queue").that(mService.mToastQueue).isEmpty(); 12503 mService.isSystemUid = false; 12504 mService.isSystemAppId = false; 12505 setToastRateIsWithinQuota(true); 12506 setIfPackageHasPermissionToAvoidToastRateLimiting(TEST_PACKAGE, false); 12507 // package is not suspended 12508 when(mPackageManager.isPackageSuspendedForUser(TEST_PACKAGE, mUserId)) 12509 .thenReturn(false); 12510 } 12511 12512 private void enqueueToast(String testPackage, ITransientNotification callback) 12513 throws RemoteException { 12514 enqueueToast((INotificationManager) mService.mService, testPackage, new Binder(), callback); 12515 } 12516 12517 private void enqueueToast(INotificationManager service, String testPackage, 12518 IBinder token, ITransientNotification callback) throws RemoteException { 12519 service.enqueueToast(testPackage, token, callback, TOAST_DURATION, /* isUiContext= */ true, 12520 DEFAULT_DISPLAY); 12521 } 12522 12523 private void enqueueTextToast(String testPackage, CharSequence text) throws RemoteException { 12524 enqueueTextToast(testPackage, text, /* isUiContext= */ true, DEFAULT_DISPLAY); 12525 } 12526 12527 private void enqueueTextToast(String testPackage, CharSequence text, boolean isUiContext, 12528 int displayId) throws RemoteException { 12529 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), text, 12530 TOAST_DURATION, isUiContext, displayId, /* textCallback= */ null); 12531 } 12532 12533 private void mockIsVisibleBackgroundUsersSupported(boolean supported) { 12534 when(mUm.isVisibleBackgroundUsersSupported()).thenReturn(supported); 12535 } 12536 12537 private void mockIsUserVisible(int displayId, boolean visible) { 12538 when(mUmInternal.isUserVisible(mUserId, displayId)).thenReturn(visible); 12539 } 12540 12541 private void mockDisplayAssignedToUser(int displayId) { 12542 when(mUmInternal.getMainDisplayAssignedToUser(mUserId)).thenReturn(displayId); 12543 } 12544 12545 private void verifyToastShownForTestPackage(String text, int displayId) { 12546 verify(mStatusBar).showToast(eq(mUid), eq(TEST_PACKAGE), any(), eq(text), any(), 12547 eq(TOAST_DURATION), any(), eq(displayId)); 12548 } 12549 } 12550