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