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 package com.android.server.notification; 17 18 import static android.app.Notification.FLAG_BUBBLE; 19 import static android.app.Notification.GROUP_ALERT_ALL; 20 import static android.app.Notification.GROUP_ALERT_CHILDREN; 21 import static android.app.Notification.GROUP_ALERT_SUMMARY; 22 import static android.app.NotificationManager.IMPORTANCE_HIGH; 23 import static android.app.NotificationManager.IMPORTANCE_LOW; 24 import static android.app.NotificationManager.IMPORTANCE_MIN; 25 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS; 26 import static android.media.AudioAttributes.USAGE_NOTIFICATION; 27 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE; 28 29 import static junit.framework.Assert.assertFalse; 30 import static junit.framework.Assert.assertNull; 31 import static junit.framework.Assert.assertTrue; 32 33 import static org.junit.Assert.assertEquals; 34 import static org.junit.Assert.assertNotEquals; 35 import static org.mockito.Matchers.any; 36 import static org.mockito.Matchers.anyBoolean; 37 import static org.mockito.Matchers.anyInt; 38 import static org.mockito.Matchers.anyObject; 39 import static org.mockito.Matchers.anyString; 40 import static org.mockito.Matchers.argThat; 41 import static org.mockito.Matchers.eq; 42 import static org.mockito.Mockito.after; 43 import static org.mockito.Mockito.mock; 44 import static org.mockito.Mockito.never; 45 import static org.mockito.Mockito.spy; 46 import static org.mockito.Mockito.timeout; 47 import static org.mockito.Mockito.times; 48 import static org.mockito.Mockito.verify; 49 import static org.mockito.Mockito.when; 50 51 import android.annotation.SuppressLint; 52 import android.app.ActivityManager; 53 import android.app.KeyguardManager; 54 import android.app.Notification; 55 import android.app.Notification.Builder; 56 import android.app.NotificationChannel; 57 import android.app.NotificationManager; 58 import android.app.PendingIntent; 59 import android.content.Context; 60 import android.content.pm.PackageManager; 61 import android.graphics.Color; 62 import android.graphics.drawable.Icon; 63 import android.media.AudioAttributes; 64 import android.media.AudioManager; 65 import android.net.Uri; 66 import android.os.Handler; 67 import android.os.Process; 68 import android.os.RemoteException; 69 import android.os.UserHandle; 70 import android.os.VibrationAttributes; 71 import android.os.VibrationEffect; 72 import android.os.Vibrator; 73 import android.provider.Settings; 74 import android.service.notification.NotificationListenerService; 75 import android.service.notification.StatusBarNotification; 76 import android.test.suitebuilder.annotation.SmallTest; 77 import android.view.accessibility.AccessibilityEvent; 78 import android.view.accessibility.AccessibilityManager; 79 import android.view.accessibility.IAccessibilityManager; 80 import android.view.accessibility.IAccessibilityManagerClient; 81 82 import androidx.test.runner.AndroidJUnit4; 83 84 import com.android.internal.logging.InstanceIdSequence; 85 import com.android.internal.logging.InstanceIdSequenceFake; 86 import com.android.internal.util.IntPair; 87 import com.android.server.UiServiceTestCase; 88 import com.android.server.lights.LogicalLight; 89 import com.android.server.pm.PackageManagerService; 90 91 import org.junit.Before; 92 import org.junit.Test; 93 import org.junit.runner.RunWith; 94 import org.mockito.ArgumentCaptor; 95 import org.mockito.ArgumentMatcher; 96 import org.mockito.Mock; 97 import org.mockito.Mockito; 98 import org.mockito.MockitoAnnotations; 99 import org.mockito.verification.VerificationMode; 100 101 import java.util.Objects; 102 103 @SmallTest 104 @RunWith(AndroidJUnit4.class) 105 @SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service. 106 public class BuzzBeepBlinkTest extends UiServiceTestCase { 107 108 @Mock AudioManager mAudioManager; 109 @Mock Vibrator mVibrator; 110 @Mock android.media.IRingtonePlayer mRingtonePlayer; 111 @Mock LogicalLight mLight; 112 @Mock 113 NotificationManagerService.WorkerHandler mHandler; 114 @Mock 115 NotificationUsageStats mUsageStats; 116 @Mock 117 IAccessibilityManager mAccessibilityService; 118 @Mock 119 KeyguardManager mKeyguardManager; 120 NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); 121 private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( 122 1 << 30); 123 124 private NotificationManagerService mService; 125 private String mPkg = "com.android.server.notification"; 126 private int mId = 1001; 127 private int mOtherId = 1002; 128 private String mTag = null; 129 private int mUid = 1000; 130 private int mPid = 2000; 131 private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser()); 132 private NotificationChannel mChannel; 133 134 private VibrateRepeatMatcher mVibrateOnceMatcher = new VibrateRepeatMatcher(-1); 135 private VibrateRepeatMatcher mVibrateLoopMatcher = new VibrateRepeatMatcher(0); 136 137 private static final long[] CUSTOM_VIBRATION = new long[] { 138 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 139 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 140 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 }; 141 private static final Uri CUSTOM_SOUND = Settings.System.DEFAULT_ALARM_ALERT_URI; 142 private static final AudioAttributes CUSTOM_ATTRIBUTES = new AudioAttributes.Builder() 143 .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) 144 .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) 145 .build(); 146 private static final int CUSTOM_LIGHT_COLOR = Color.BLACK; 147 private static final int CUSTOM_LIGHT_ON = 10000; 148 private static final int CUSTOM_LIGHT_OFF = 10000; 149 private static final int MAX_VIBRATION_DELAY = 1000; 150 151 @Before setUp()152 public void setUp() throws Exception { 153 MockitoAnnotations.initMocks(this); 154 getContext().addMockSystemService(Vibrator.class, mVibrator); 155 156 when(mAudioManager.isAudioFocusExclusive()).thenReturn(false); 157 when(mAudioManager.getRingtonePlayer()).thenReturn(mRingtonePlayer); 158 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10); 159 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); 160 when(mAudioManager.getFocusRampTimeMs(anyInt(), any(AudioAttributes.class))).thenReturn(50); 161 when(mUsageStats.isAlertRateLimited(any())).thenReturn(false); 162 when(mVibrator.hasFrequencyControl()).thenReturn(false); 163 when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false); 164 165 long serviceReturnValue = IntPair.of( 166 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED, 167 AccessibilityEvent.TYPES_ALL_MASK); 168 when(mAccessibilityService.addClient(any(), anyInt())).thenReturn(serviceReturnValue); 169 AccessibilityManager accessibilityManager = 170 new AccessibilityManager(getContext(), Handler.getMain(), mAccessibilityService, 171 0, true); 172 verify(mAccessibilityService).addClient(any(IAccessibilityManagerClient.class), anyInt()); 173 assertTrue(accessibilityManager.isEnabled()); 174 175 mService = spy(new NotificationManagerService(getContext(), mNotificationRecordLogger, 176 mNotificationInstanceIdSequence)); 177 mService.setVibratorHelper(new VibratorHelper(getContext())); 178 mService.setAudioManager(mAudioManager); 179 mService.setSystemReady(true); 180 mService.setHandler(mHandler); 181 mService.setLights(mLight); 182 mService.setScreenOn(false); 183 mService.setUsageStats(mUsageStats); 184 mService.setAccessibilityManager(accessibilityManager); 185 mService.setKeyguardManager(mKeyguardManager); 186 mService.mScreenOn = false; 187 mService.mInCallStateOffHook = false; 188 mService.mNotificationPulseEnabled = true; 189 190 mChannel = new NotificationChannel("test", "test", IMPORTANCE_HIGH); 191 } 192 193 // 194 // Convenience functions for creating notification records 195 // 196 getNoisyOtherNotification()197 private NotificationRecord getNoisyOtherNotification() { 198 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */, 199 true /* noisy */, true /* buzzy*/, false /* lights */); 200 } 201 getBeepyNotification()202 private NotificationRecord getBeepyNotification() { 203 return getNotificationRecord(mId, false /* insistent */, false /* once */, 204 true /* noisy */, false /* buzzy*/, false /* lights */); 205 } 206 getBeepyOtherNotification()207 private NotificationRecord getBeepyOtherNotification() { 208 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */, 209 true /* noisy */, false /* buzzy*/, false /* lights */); 210 } 211 getBeepyOnceNotification()212 private NotificationRecord getBeepyOnceNotification() { 213 return getNotificationRecord(mId, false /* insistent */, true /* once */, 214 true /* noisy */, false /* buzzy*/, false /* lights */); 215 } 216 getQuietNotification()217 private NotificationRecord getQuietNotification() { 218 return getNotificationRecord(mId, false /* insistent */, true /* once */, 219 false /* noisy */, false /* buzzy*/, false /* lights */); 220 } 221 getQuietOtherNotification()222 private NotificationRecord getQuietOtherNotification() { 223 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */, 224 false /* noisy */, false /* buzzy*/, false /* lights */); 225 } 226 getQuietOnceNotification()227 private NotificationRecord getQuietOnceNotification() { 228 return getNotificationRecord(mId, false /* insistent */, true /* once */, 229 false /* noisy */, false /* buzzy*/, false /* lights */); 230 } 231 getInsistentBeepyNotification()232 private NotificationRecord getInsistentBeepyNotification() { 233 return getNotificationRecord(mId, true /* insistent */, false /* once */, 234 true /* noisy */, false /* buzzy*/, false /* lights */); 235 } 236 getInsistentBeepyOnceNotification()237 private NotificationRecord getInsistentBeepyOnceNotification() { 238 return getNotificationRecord(mId, true /* insistent */, true /* once */, 239 true /* noisy */, false /* buzzy*/, false /* lights */); 240 } 241 getInsistentBeepyLeanbackNotification()242 private NotificationRecord getInsistentBeepyLeanbackNotification() { 243 return getLeanbackNotificationRecord(mId, true /* insistent */, false /* once */, 244 true /* noisy */, false /* buzzy*/, false /* lights */); 245 } 246 getBuzzyNotification()247 private NotificationRecord getBuzzyNotification() { 248 return getNotificationRecord(mId, false /* insistent */, false /* once */, 249 false /* noisy */, true /* buzzy*/, false /* lights */); 250 } 251 getBuzzyOtherNotification()252 private NotificationRecord getBuzzyOtherNotification() { 253 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */, 254 false /* noisy */, true /* buzzy*/, false /* lights */); 255 } 256 getBuzzyOnceNotification()257 private NotificationRecord getBuzzyOnceNotification() { 258 return getNotificationRecord(mId, false /* insistent */, true /* once */, 259 false /* noisy */, true /* buzzy*/, false /* lights */); 260 } 261 getInsistentBuzzyNotification()262 private NotificationRecord getInsistentBuzzyNotification() { 263 return getNotificationRecord(mId, true /* insistent */, false /* once */, 264 false /* noisy */, true /* buzzy*/, false /* lights */); 265 } 266 getBuzzyBeepyNotification()267 private NotificationRecord getBuzzyBeepyNotification() { 268 return getNotificationRecord(mId, false /* insistent */, false /* once */, 269 true /* noisy */, true /* buzzy*/, false /* lights */); 270 } 271 getLightsNotification()272 private NotificationRecord getLightsNotification() { 273 return getNotificationRecord(mId, false /* insistent */, false /* once */, 274 false /* noisy */, false /* buzzy*/, true /* lights */); 275 } 276 getLightsOnceNotification()277 private NotificationRecord getLightsOnceNotification() { 278 return getNotificationRecord(mId, false /* insistent */, true /* once */, 279 false /* noisy */, false /* buzzy*/, true /* lights */); 280 } 281 getCallRecord(int id, NotificationChannel channel, boolean looping)282 private NotificationRecord getCallRecord(int id, NotificationChannel channel, boolean looping) { 283 final Builder builder = new Builder(getContext()) 284 .setContentTitle("foo") 285 .setSmallIcon(android.R.drawable.sym_def_app_icon) 286 .setPriority(Notification.PRIORITY_HIGH); 287 Notification n = builder.build(); 288 if (looping) { 289 n.flags |= Notification.FLAG_INSISTENT; 290 } 291 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid, 292 mPid, n, mUser, null, System.currentTimeMillis()); 293 NotificationRecord r = new NotificationRecord(getContext(), sbn, channel); 294 mService.addNotification(r); 295 296 return r; 297 } 298 getNotificationRecord(int id, boolean insistent, boolean once, boolean noisy, boolean buzzy, boolean lights)299 private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once, 300 boolean noisy, boolean buzzy, boolean lights) { 301 return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, buzzy, noisy, 302 lights, null, Notification.GROUP_ALERT_ALL, false); 303 } 304 getLeanbackNotificationRecord(int id, boolean insistent, boolean once, boolean noisy, boolean buzzy, boolean lights)305 private NotificationRecord getLeanbackNotificationRecord(int id, boolean insistent, 306 boolean once, 307 boolean noisy, boolean buzzy, boolean lights) { 308 return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, 309 true, 310 null, Notification.GROUP_ALERT_ALL, true); 311 } 312 getBeepyNotificationRecord(String groupKey, int groupAlertBehavior)313 private NotificationRecord getBeepyNotificationRecord(String groupKey, int groupAlertBehavior) { 314 return getNotificationRecord(mId, false, false, true, false, false, true, true, true, 315 groupKey, groupAlertBehavior, false); 316 } 317 getLightsNotificationRecord(String groupKey, int groupAlertBehavior)318 private NotificationRecord getLightsNotificationRecord(String groupKey, 319 int groupAlertBehavior) { 320 return getNotificationRecord(mId, false, false, false, false, true /*lights*/, true, 321 true, true, groupKey, groupAlertBehavior, false); 322 } 323 getNotificationRecord(int id, boolean insistent, boolean once, boolean noisy, boolean buzzy, boolean lights, boolean defaultVibration, boolean defaultSound, boolean defaultLights, String groupKey, int groupAlertBehavior, boolean isLeanback)324 private NotificationRecord getNotificationRecord(int id, 325 boolean insistent, boolean once, 326 boolean noisy, boolean buzzy, boolean lights, boolean defaultVibration, 327 boolean defaultSound, boolean defaultLights, String groupKey, int groupAlertBehavior, 328 boolean isLeanback) { 329 330 final Builder builder = new Builder(getContext()) 331 .setContentTitle("foo") 332 .setSmallIcon(android.R.drawable.sym_def_app_icon) 333 .setPriority(Notification.PRIORITY_HIGH) 334 .setOnlyAlertOnce(once); 335 336 int defaults = 0; 337 if (noisy) { 338 if (defaultSound) { 339 defaults |= Notification.DEFAULT_SOUND; 340 mChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI, 341 Notification.AUDIO_ATTRIBUTES_DEFAULT); 342 } else { 343 builder.setSound(CUSTOM_SOUND); 344 mChannel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES); 345 } 346 } else { 347 mChannel.setSound(null, null); 348 } 349 if (buzzy) { 350 if (defaultVibration) { 351 defaults |= Notification.DEFAULT_VIBRATE; 352 } else { 353 builder.setVibrate(CUSTOM_VIBRATION); 354 mChannel.setVibrationPattern(CUSTOM_VIBRATION); 355 } 356 mChannel.enableVibration(true); 357 } else { 358 mChannel.setVibrationPattern(null); 359 mChannel.enableVibration(false); 360 } 361 362 if (lights) { 363 if (defaultLights) { 364 defaults |= Notification.DEFAULT_LIGHTS; 365 } else { 366 builder.setLights(CUSTOM_LIGHT_COLOR, CUSTOM_LIGHT_ON, CUSTOM_LIGHT_OFF); 367 } 368 mChannel.enableLights(true); 369 } else { 370 mChannel.enableLights(false); 371 } 372 builder.setDefaults(defaults); 373 374 builder.setGroup(groupKey); 375 builder.setGroupAlertBehavior(groupAlertBehavior); 376 377 Notification n = builder.build(); 378 if (insistent) { 379 n.flags |= Notification.FLAG_INSISTENT; 380 } 381 382 Context context = spy(getContext()); 383 PackageManager packageManager = spy(context.getPackageManager()); 384 when(context.getPackageManager()).thenReturn(packageManager); 385 when(packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) 386 .thenReturn(isLeanback); 387 388 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid, 389 mPid, n, mUser, null, System.currentTimeMillis()); 390 NotificationRecord r = new NotificationRecord(context, sbn, mChannel); 391 mService.addNotification(r); 392 return r; 393 } 394 395 // 396 // Convenience functions for interacting with mocks 397 // 398 verifyNeverBeep()399 private void verifyNeverBeep() throws RemoteException { 400 verify(mRingtonePlayer, never()).playAsync(any(), any(), anyBoolean(), any()); 401 } 402 verifyBeepUnlooped()403 private void verifyBeepUnlooped() throws RemoteException { 404 verify(mRingtonePlayer, times(1)).playAsync(any(), any(), eq(false), any()); 405 } 406 verifyBeepLooped()407 private void verifyBeepLooped() throws RemoteException { 408 verify(mRingtonePlayer, times(1)).playAsync(any(), any(), eq(true), any()); 409 } 410 verifyBeep(int times)411 private void verifyBeep(int times) throws RemoteException { 412 verify(mRingtonePlayer, times(times)).playAsync(any(), any(), anyBoolean(), any()); 413 } 414 verifyNeverStopAudio()415 private void verifyNeverStopAudio() throws RemoteException { 416 verify(mRingtonePlayer, never()).stopAsync(); 417 } 418 verifyStopAudio()419 private void verifyStopAudio() throws RemoteException { 420 verify(mRingtonePlayer, times(1)).stopAsync(); 421 } 422 verifyNeverVibrate()423 private void verifyNeverVibrate() { 424 verify(mVibrator, never()).vibrate(anyInt(), anyString(), any(), anyString(), 425 any(VibrationAttributes.class)); 426 } 427 verifyVibrate()428 private void verifyVibrate() { 429 verifyVibrate(/* times= */ 1); 430 } 431 verifyVibrate(int times)432 private void verifyVibrate(int times) { 433 verifyVibrate(mVibrateOnceMatcher, times(times)); 434 } 435 verifyVibrateLooped()436 private void verifyVibrateLooped() { 437 verifyVibrate(mVibrateLoopMatcher, times(1)); 438 } 439 verifyDelayedVibrateLooped()440 private void verifyDelayedVibrateLooped() { 441 verifyVibrate(mVibrateLoopMatcher, timeout(MAX_VIBRATION_DELAY).times(1)); 442 } 443 verifyDelayedVibrate(VibrationEffect effect)444 private void verifyDelayedVibrate(VibrationEffect effect) { 445 verifyVibrate(argument -> Objects.equals(effect, argument), 446 timeout(MAX_VIBRATION_DELAY).times(1)); 447 } 448 verifyDelayedNeverVibrate()449 private void verifyDelayedNeverVibrate() { 450 verify(mVibrator, after(MAX_VIBRATION_DELAY).never()).vibrate(anyInt(), anyString(), any(), 451 anyString(), any(VibrationAttributes.class)); 452 } 453 verifyVibrate(ArgumentMatcher<VibrationEffect> effectMatcher, VerificationMode verification)454 private void verifyVibrate(ArgumentMatcher<VibrationEffect> effectMatcher, 455 VerificationMode verification) { 456 ArgumentCaptor<VibrationAttributes> captor = 457 ArgumentCaptor.forClass(VibrationAttributes.class); 458 verify(mVibrator, verification).vibrate(eq(Process.SYSTEM_UID), 459 eq(PackageManagerService.PLATFORM_PACKAGE_NAME), argThat(effectMatcher), 460 anyString(), captor.capture()); 461 assertEquals(0, (captor.getValue().getFlags() 462 & VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)); 463 } 464 verifyStopVibrate()465 private void verifyStopVibrate() { 466 int alarmClassUsageFilter = 467 VibrationAttributes.USAGE_CLASS_ALARM | ~VibrationAttributes.USAGE_CLASS_MASK; 468 verify(mVibrator, times(1)).cancel(eq(alarmClassUsageFilter)); 469 } 470 verifyNeverStopVibrate()471 private void verifyNeverStopVibrate() { 472 verify(mVibrator, never()).cancel(); 473 verify(mVibrator, never()).cancel(anyInt()); 474 } 475 verifyNeverLights()476 private void verifyNeverLights() { 477 verify(mLight, never()).setFlashing(anyInt(), anyInt(), anyInt(), anyInt()); 478 } 479 verifyLights()480 private void verifyLights() { 481 verify(mLight, times(1)).setFlashing(anyInt(), anyInt(), anyInt(), anyInt()); 482 } 483 484 // 485 // Tests 486 // 487 488 @Test testLights()489 public void testLights() throws Exception { 490 NotificationRecord r = getLightsNotification(); 491 r.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT); 492 493 mService.buzzBeepBlinkLocked(r); 494 495 verifyLights(); 496 assertTrue(r.isInterruptive()); 497 assertEquals(-1, r.getLastAudiblyAlertedMs()); 498 } 499 500 @Test testBeep()501 public void testBeep() throws Exception { 502 NotificationRecord r = getBeepyNotification(); 503 504 mService.buzzBeepBlinkLocked(r); 505 506 verifyBeepUnlooped(); 507 verifyNeverVibrate(); 508 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt()); 509 assertTrue(r.isInterruptive()); 510 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 511 } 512 513 @Test testLockedPrivateA11yRedaction()514 public void testLockedPrivateA11yRedaction() throws Exception { 515 NotificationRecord r = getBeepyNotification(); 516 r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE); 517 r.getNotification().visibility = Notification.VISIBILITY_PRIVATE; 518 when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true); 519 AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class); 520 when(accessibilityManager.isEnabled()).thenReturn(true); 521 mService.setAccessibilityManager(accessibilityManager); 522 523 mService.buzzBeepBlinkLocked(r); 524 525 ArgumentCaptor<AccessibilityEvent> eventCaptor = 526 ArgumentCaptor.forClass(AccessibilityEvent.class); 527 528 verify(accessibilityManager, times(1)) 529 .sendAccessibilityEvent(eventCaptor.capture()); 530 531 AccessibilityEvent event = eventCaptor.getValue(); 532 assertEquals(r.getNotification().publicVersion, event.getParcelableData()); 533 } 534 535 @Test testLockedOverridePrivateA11yRedaction()536 public void testLockedOverridePrivateA11yRedaction() throws Exception { 537 NotificationRecord r = getBeepyNotification(); 538 r.setPackageVisibilityOverride(Notification.VISIBILITY_PRIVATE); 539 r.getNotification().visibility = Notification.VISIBILITY_PUBLIC; 540 when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true); 541 AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class); 542 when(accessibilityManager.isEnabled()).thenReturn(true); 543 mService.setAccessibilityManager(accessibilityManager); 544 545 mService.buzzBeepBlinkLocked(r); 546 547 ArgumentCaptor<AccessibilityEvent> eventCaptor = 548 ArgumentCaptor.forClass(AccessibilityEvent.class); 549 550 verify(accessibilityManager, times(1)) 551 .sendAccessibilityEvent(eventCaptor.capture()); 552 553 AccessibilityEvent event = eventCaptor.getValue(); 554 assertEquals(r.getNotification().publicVersion, event.getParcelableData()); 555 } 556 557 @Test testLockedPublicA11yNoRedaction()558 public void testLockedPublicA11yNoRedaction() throws Exception { 559 NotificationRecord r = getBeepyNotification(); 560 r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE); 561 r.getNotification().visibility = Notification.VISIBILITY_PUBLIC; 562 when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true); 563 AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class); 564 when(accessibilityManager.isEnabled()).thenReturn(true); 565 mService.setAccessibilityManager(accessibilityManager); 566 567 mService.buzzBeepBlinkLocked(r); 568 569 ArgumentCaptor<AccessibilityEvent> eventCaptor = 570 ArgumentCaptor.forClass(AccessibilityEvent.class); 571 572 verify(accessibilityManager, times(1)) 573 .sendAccessibilityEvent(eventCaptor.capture()); 574 575 AccessibilityEvent event = eventCaptor.getValue(); 576 assertEquals(r.getNotification(), event.getParcelableData()); 577 } 578 579 @Test testUnlockedPrivateA11yNoRedaction()580 public void testUnlockedPrivateA11yNoRedaction() throws Exception { 581 NotificationRecord r = getBeepyNotification(); 582 r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE); 583 r.getNotification().visibility = Notification.VISIBILITY_PRIVATE; 584 when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false); 585 AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class); 586 when(accessibilityManager.isEnabled()).thenReturn(true); 587 mService.setAccessibilityManager(accessibilityManager); 588 589 mService.buzzBeepBlinkLocked(r); 590 591 ArgumentCaptor<AccessibilityEvent> eventCaptor = 592 ArgumentCaptor.forClass(AccessibilityEvent.class); 593 594 verify(accessibilityManager, times(1)) 595 .sendAccessibilityEvent(eventCaptor.capture()); 596 597 AccessibilityEvent event = eventCaptor.getValue(); 598 assertEquals(r.getNotification(), event.getParcelableData()); 599 } 600 601 @Test testBeepInsistently()602 public void testBeepInsistently() throws Exception { 603 NotificationRecord r = getInsistentBeepyNotification(); 604 605 mService.buzzBeepBlinkLocked(r); 606 607 verifyBeepLooped(); 608 assertTrue(r.isInterruptive()); 609 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 610 } 611 612 @Test testNoLeanbackBeep()613 public void testNoLeanbackBeep() throws Exception { 614 NotificationRecord r = getInsistentBeepyLeanbackNotification(); 615 616 mService.buzzBeepBlinkLocked(r); 617 618 verifyNeverBeep(); 619 assertFalse(r.isInterruptive()); 620 assertEquals(-1, r.getLastAudiblyAlertedMs()); 621 } 622 623 @Test testNoBeepForAutomotiveIfEffectsDisabled()624 public void testNoBeepForAutomotiveIfEffectsDisabled() throws Exception { 625 mService.setIsAutomotive(true); 626 mService.setNotificationEffectsEnabledForAutomotive(false); 627 628 NotificationRecord r = getBeepyNotification(); 629 r.setSystemImportance(NotificationManager.IMPORTANCE_HIGH); 630 631 mService.buzzBeepBlinkLocked(r); 632 633 verifyNeverBeep(); 634 assertFalse(r.isInterruptive()); 635 } 636 637 @Test testNoBeepForImportanceDefaultInAutomotiveIfEffectsEnabled()638 public void testNoBeepForImportanceDefaultInAutomotiveIfEffectsEnabled() throws Exception { 639 mService.setIsAutomotive(true); 640 mService.setNotificationEffectsEnabledForAutomotive(true); 641 642 NotificationRecord r = getBeepyNotification(); 643 r.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT); 644 645 mService.buzzBeepBlinkLocked(r); 646 647 verifyNeverBeep(); 648 assertFalse(r.isInterruptive()); 649 } 650 651 @Test testBeepForImportanceHighInAutomotiveIfEffectsEnabled()652 public void testBeepForImportanceHighInAutomotiveIfEffectsEnabled() throws Exception { 653 mService.setIsAutomotive(true); 654 mService.setNotificationEffectsEnabledForAutomotive(true); 655 656 NotificationRecord r = getBeepyNotification(); 657 r.setSystemImportance(NotificationManager.IMPORTANCE_HIGH); 658 659 mService.buzzBeepBlinkLocked(r); 660 661 verifyBeepUnlooped(); 662 assertTrue(r.isInterruptive()); 663 } 664 665 @Test testNoInterruptionForMin()666 public void testNoInterruptionForMin() throws Exception { 667 NotificationRecord r = getBeepyNotification(); 668 r.setSystemImportance(NotificationManager.IMPORTANCE_MIN); 669 670 mService.buzzBeepBlinkLocked(r); 671 672 verifyNeverBeep(); 673 verifyNeverVibrate(); 674 assertFalse(r.isInterruptive()); 675 assertEquals(-1, r.getLastAudiblyAlertedMs()); 676 } 677 678 @Test testNoInterruptionForIntercepted()679 public void testNoInterruptionForIntercepted() throws Exception { 680 NotificationRecord r = getBeepyNotification(); 681 r.setIntercepted(true); 682 683 mService.buzzBeepBlinkLocked(r); 684 685 verifyNeverBeep(); 686 verifyNeverVibrate(); 687 assertFalse(r.isInterruptive()); 688 assertEquals(-1, r.getLastAudiblyAlertedMs()); 689 } 690 691 @Test testBeepTwice()692 public void testBeepTwice() throws Exception { 693 NotificationRecord r = getBeepyNotification(); 694 695 // set up internal state 696 mService.buzzBeepBlinkLocked(r); 697 Mockito.reset(mRingtonePlayer); 698 699 // update should beep 700 r.isUpdate = true; 701 mService.buzzBeepBlinkLocked(r); 702 verifyBeepUnlooped(); 703 verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt()); 704 assertTrue(r.isInterruptive()); 705 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 706 } 707 708 @Test testHonorAlertOnlyOnceForBeep()709 public void testHonorAlertOnlyOnceForBeep() throws Exception { 710 NotificationRecord r = getBeepyNotification(); 711 NotificationRecord s = getBeepyOnceNotification(); 712 s.isUpdate = true; 713 714 // set up internal state 715 mService.buzzBeepBlinkLocked(r); 716 Mockito.reset(mRingtonePlayer); 717 718 // update should not beep 719 mService.buzzBeepBlinkLocked(s); 720 verifyNeverBeep(); 721 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt()); 722 } 723 724 @Test testNoisyUpdateDoesNotCancelAudio()725 public void testNoisyUpdateDoesNotCancelAudio() throws Exception { 726 NotificationRecord r = getBeepyNotification(); 727 728 mService.buzzBeepBlinkLocked(r); 729 r.isUpdate = true; 730 mService.buzzBeepBlinkLocked(r); 731 732 verifyNeverStopAudio(); 733 assertTrue(r.isInterruptive()); 734 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 735 } 736 737 @Test testNoisyOnceUpdateDoesNotCancelAudio()738 public void testNoisyOnceUpdateDoesNotCancelAudio() throws Exception { 739 NotificationRecord r = getBeepyNotification(); 740 NotificationRecord s = getBeepyOnceNotification(); 741 s.isUpdate = true; 742 743 mService.buzzBeepBlinkLocked(r); 744 mService.buzzBeepBlinkLocked(s); 745 746 verifyNeverStopAudio(); 747 assertTrue(r.isInterruptive()); 748 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 749 assertFalse(s.isInterruptive()); 750 assertEquals(-1, s.getLastAudiblyAlertedMs()); 751 } 752 753 /** 754 * Tests the case where the user re-posts a {@link Notification} with looping sound where 755 * {@link Notification.Builder#setOnlyAlertOnce(true)} has been called. This should silence 756 * the sound associated with the notification. 757 * @throws Exception 758 */ 759 @Test testNoisyOnceUpdateDoesCancelAudio()760 public void testNoisyOnceUpdateDoesCancelAudio() throws Exception { 761 NotificationRecord r = getInsistentBeepyNotification(); 762 NotificationRecord s = getInsistentBeepyOnceNotification(); 763 s.isUpdate = true; 764 765 mService.buzzBeepBlinkLocked(r); 766 mService.buzzBeepBlinkLocked(s); 767 768 verifyStopAudio(); 769 } 770 771 @Test testQuietUpdateDoesNotCancelAudioFromOther()772 public void testQuietUpdateDoesNotCancelAudioFromOther() throws Exception { 773 NotificationRecord r = getBeepyNotification(); 774 NotificationRecord s = getQuietNotification(); 775 s.isUpdate = true; 776 NotificationRecord other = getNoisyOtherNotification(); 777 778 // set up internal state 779 mService.buzzBeepBlinkLocked(r); 780 mService.buzzBeepBlinkLocked(other); // this takes the audio stream 781 Mockito.reset(mRingtonePlayer); 782 783 // should not stop noise, since we no longer own it 784 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream 785 verifyNeverStopAudio(); 786 assertTrue(other.isInterruptive()); 787 assertNotEquals(-1, other.getLastAudiblyAlertedMs()); 788 } 789 790 @Test testQuietInterloperDoesNotCancelAudio()791 public void testQuietInterloperDoesNotCancelAudio() throws Exception { 792 NotificationRecord r = getBeepyNotification(); 793 NotificationRecord other = getQuietOtherNotification(); 794 795 // set up internal state 796 mService.buzzBeepBlinkLocked(r); 797 Mockito.reset(mRingtonePlayer); 798 799 // should not stop noise, since it does not own it 800 mService.buzzBeepBlinkLocked(other); 801 verifyNeverStopAudio(); 802 } 803 804 @Test testQuietUpdateCancelsAudio()805 public void testQuietUpdateCancelsAudio() throws Exception { 806 NotificationRecord r = getBeepyNotification(); 807 NotificationRecord s = getQuietNotification(); 808 s.isUpdate = true; 809 810 // set up internal state 811 mService.buzzBeepBlinkLocked(r); 812 assertTrue(r.isInterruptive()); 813 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 814 Mockito.reset(mRingtonePlayer); 815 816 // quiet update should stop making noise 817 mService.buzzBeepBlinkLocked(s); 818 verifyStopAudio(); 819 assertFalse(s.isInterruptive()); 820 assertEquals(-1, s.getLastAudiblyAlertedMs()); 821 } 822 823 @Test testQuietOnceUpdateCancelsAudio()824 public void testQuietOnceUpdateCancelsAudio() throws Exception { 825 NotificationRecord r = getBeepyNotification(); 826 NotificationRecord s = getQuietOnceNotification(); 827 s.isUpdate = true; 828 829 // set up internal state 830 mService.buzzBeepBlinkLocked(r); 831 assertTrue(r.isInterruptive()); 832 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 833 Mockito.reset(mRingtonePlayer); 834 835 // stop making noise - this is a weird corner case, but quiet should override once 836 mService.buzzBeepBlinkLocked(s); 837 verifyStopAudio(); 838 assertFalse(s.isInterruptive()); 839 assertEquals(-1, s.getLastAudiblyAlertedMs()); 840 } 841 842 @Test testInCallNotification()843 public void testInCallNotification() throws Exception { 844 NotificationRecord r = getBeepyNotification(); 845 846 // set up internal state 847 mService.buzzBeepBlinkLocked(r); 848 Mockito.reset(mRingtonePlayer); 849 850 mService.mInCallStateOffHook = true; 851 mService.buzzBeepBlinkLocked(r); 852 853 verify(mService, times(1)).playInCallNotification(); 854 verifyNeverBeep(); // doesn't play normal beep 855 assertTrue(r.isInterruptive()); 856 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 857 } 858 859 @Test testNoDemoteSoundToVibrateIfVibrateGiven()860 public void testNoDemoteSoundToVibrateIfVibrateGiven() throws Exception { 861 NotificationRecord r = getBuzzyBeepyNotification(); 862 assertTrue(r.getSound() != null); 863 864 // the phone is quiet 865 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); 866 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0); 867 868 mService.buzzBeepBlinkLocked(r); 869 870 verifyDelayedVibrate(r.getVibration()); 871 assertTrue(r.isInterruptive()); 872 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 873 } 874 875 @Test testNoDemoteSoundToVibrateIfNonNotificationStream()876 public void testNoDemoteSoundToVibrateIfNonNotificationStream() throws Exception { 877 NotificationRecord r = getBeepyNotification(); 878 assertTrue(r.getSound() != null); 879 assertNull(r.getVibration()); 880 881 // the phone is quiet 882 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); 883 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(1); 884 885 mService.buzzBeepBlinkLocked(r); 886 887 verifyNeverVibrate(); 888 verifyBeepUnlooped(); 889 assertTrue(r.isInterruptive()); 890 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 891 } 892 893 @Test testDemoteSoundToVibrate()894 public void testDemoteSoundToVibrate() throws Exception { 895 NotificationRecord r = getBeepyNotification(); 896 assertTrue(r.getSound() != null); 897 assertNull(r.getVibration()); 898 899 // the phone is quiet 900 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); 901 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0); 902 903 mService.buzzBeepBlinkLocked(r); 904 905 verifyDelayedVibrate( 906 mService.getVibratorHelper().createFallbackVibration(/* insistent= */ false)); 907 verify(mRingtonePlayer, never()).playAsync 908 (anyObject(), anyObject(), anyBoolean(), anyObject()); 909 assertTrue(r.isInterruptive()); 910 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 911 } 912 913 @Test testDemoteInsistentSoundToVibrate()914 public void testDemoteInsistentSoundToVibrate() throws Exception { 915 NotificationRecord r = getInsistentBeepyNotification(); 916 assertTrue(r.getSound() != null); 917 assertNull(r.getVibration()); 918 919 // the phone is quiet 920 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0); 921 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); 922 923 mService.buzzBeepBlinkLocked(r); 924 925 verifyDelayedVibrateLooped(); 926 assertTrue(r.isInterruptive()); 927 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 928 } 929 930 @Test testVibrate()931 public void testVibrate() throws Exception { 932 NotificationRecord r = getBuzzyNotification(); 933 934 mService.buzzBeepBlinkLocked(r); 935 936 verifyNeverBeep(); 937 verifyVibrate(); 938 assertTrue(r.isInterruptive()); 939 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 940 } 941 942 @Test testInsistentVibrate()943 public void testInsistentVibrate() { 944 NotificationRecord r = getInsistentBuzzyNotification(); 945 946 mService.buzzBeepBlinkLocked(r); 947 verifyVibrateLooped(); 948 assertTrue(r.isInterruptive()); 949 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 950 } 951 952 @Test testVibrateTwice()953 public void testVibrateTwice() { 954 NotificationRecord r = getBuzzyNotification(); 955 956 // set up internal state 957 mService.buzzBeepBlinkLocked(r); 958 Mockito.reset(mVibrator); 959 960 // update should vibrate 961 r.isUpdate = true; 962 mService.buzzBeepBlinkLocked(r); 963 verifyVibrate(); 964 assertTrue(r.isInterruptive()); 965 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 966 } 967 968 @Test testPostSilently()969 public void testPostSilently() throws Exception { 970 NotificationRecord r = getBuzzyNotification(); 971 r.setPostSilently(true); 972 973 mService.buzzBeepBlinkLocked(r); 974 975 verifyNeverBeep(); 976 assertFalse(r.isInterruptive()); 977 assertEquals(-1, r.getLastAudiblyAlertedMs()); 978 } 979 980 @Test testGroupAlertSummarySilenceChild()981 public void testGroupAlertSummarySilenceChild() throws Exception { 982 NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY); 983 984 mService.buzzBeepBlinkLocked(child); 985 986 verifyNeverBeep(); 987 assertFalse(child.isInterruptive()); 988 assertEquals(-1, child.getLastAudiblyAlertedMs()); 989 } 990 991 @Test testGroupAlertSummaryNoSilenceSummary()992 public void testGroupAlertSummaryNoSilenceSummary() throws Exception { 993 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY); 994 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; 995 996 mService.buzzBeepBlinkLocked(summary); 997 998 verifyBeepUnlooped(); 999 // summaries are never interruptive for notification counts 1000 assertFalse(summary.isInterruptive()); 1001 assertNotEquals(-1, summary.getLastAudiblyAlertedMs()); 1002 } 1003 1004 @Test testGroupAlertSummaryNoSilenceNonGroupChild()1005 public void testGroupAlertSummaryNoSilenceNonGroupChild() throws Exception { 1006 NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_SUMMARY); 1007 1008 mService.buzzBeepBlinkLocked(nonGroup); 1009 1010 verifyBeepUnlooped(); 1011 assertTrue(nonGroup.isInterruptive()); 1012 assertNotEquals(-1, nonGroup.getLastAudiblyAlertedMs()); 1013 } 1014 1015 @Test testGroupAlertChildSilenceSummary()1016 public void testGroupAlertChildSilenceSummary() throws Exception { 1017 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN); 1018 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; 1019 1020 mService.buzzBeepBlinkLocked(summary); 1021 1022 verifyNeverBeep(); 1023 assertFalse(summary.isInterruptive()); 1024 assertEquals(-1, summary.getLastAudiblyAlertedMs()); 1025 } 1026 1027 @Test testGroupAlertChildNoSilenceChild()1028 public void testGroupAlertChildNoSilenceChild() throws Exception { 1029 NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN); 1030 1031 mService.buzzBeepBlinkLocked(child); 1032 1033 verifyBeepUnlooped(); 1034 assertTrue(child.isInterruptive()); 1035 assertNotEquals(-1, child.getLastAudiblyAlertedMs()); 1036 } 1037 1038 @Test testGroupAlertChildNoSilenceNonGroupSummary()1039 public void testGroupAlertChildNoSilenceNonGroupSummary() throws Exception { 1040 NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_CHILDREN); 1041 1042 mService.buzzBeepBlinkLocked(nonGroup); 1043 1044 verifyBeepUnlooped(); 1045 assertTrue(nonGroup.isInterruptive()); 1046 assertNotEquals(-1, nonGroup.getLastAudiblyAlertedMs()); 1047 } 1048 1049 @Test testGroupAlertAllNoSilenceGroup()1050 public void testGroupAlertAllNoSilenceGroup() throws Exception { 1051 NotificationRecord group = getBeepyNotificationRecord("a", GROUP_ALERT_ALL); 1052 1053 mService.buzzBeepBlinkLocked(group); 1054 1055 verifyBeepUnlooped(); 1056 assertTrue(group.isInterruptive()); 1057 assertNotEquals(-1, group.getLastAudiblyAlertedMs()); 1058 } 1059 1060 @Test testHonorAlertOnlyOnceForBuzz()1061 public void testHonorAlertOnlyOnceForBuzz() throws Exception { 1062 NotificationRecord r = getBuzzyNotification(); 1063 NotificationRecord s = getBuzzyOnceNotification(); 1064 s.isUpdate = true; 1065 1066 // set up internal state 1067 mService.buzzBeepBlinkLocked(r); 1068 Mockito.reset(mVibrator); 1069 assertTrue(r.isInterruptive()); 1070 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 1071 1072 // update should not beep 1073 mService.buzzBeepBlinkLocked(s); 1074 verifyNeverVibrate(); 1075 assertFalse(s.isInterruptive()); 1076 assertEquals(-1, s.getLastAudiblyAlertedMs()); 1077 } 1078 1079 @Test testNoisyUpdateDoesNotCancelVibrate()1080 public void testNoisyUpdateDoesNotCancelVibrate() throws Exception { 1081 NotificationRecord r = getBuzzyNotification(); 1082 1083 mService.buzzBeepBlinkLocked(r); 1084 r.isUpdate = true; 1085 mService.buzzBeepBlinkLocked(r); 1086 1087 verifyNeverStopVibrate(); 1088 assertTrue(r.isInterruptive()); 1089 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 1090 } 1091 1092 @Test testNoisyOnceUpdateDoesNotCancelVibrate()1093 public void testNoisyOnceUpdateDoesNotCancelVibrate() throws Exception { 1094 NotificationRecord r = getBuzzyNotification(); 1095 NotificationRecord s = getBuzzyOnceNotification(); 1096 s.isUpdate = true; 1097 1098 mService.buzzBeepBlinkLocked(r); 1099 mService.buzzBeepBlinkLocked(s); 1100 1101 verifyNeverStopVibrate(); 1102 assertTrue(r.isInterruptive()); 1103 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 1104 assertFalse(s.isInterruptive()); 1105 assertEquals(-1, s.getLastAudiblyAlertedMs()); 1106 } 1107 1108 @Test testQuietUpdateDoesNotCancelVibrateFromOther()1109 public void testQuietUpdateDoesNotCancelVibrateFromOther() throws Exception { 1110 NotificationRecord r = getBuzzyNotification(); 1111 NotificationRecord s = getQuietNotification(); 1112 s.isUpdate = true; 1113 NotificationRecord other = getNoisyOtherNotification(); 1114 1115 // set up internal state 1116 mService.buzzBeepBlinkLocked(r); 1117 mService.buzzBeepBlinkLocked(other); // this takes the vibrate stream 1118 Mockito.reset(mVibrator); 1119 1120 // should not stop vibrate, since we no longer own it 1121 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream 1122 verifyNeverStopVibrate(); 1123 assertTrue(r.isInterruptive()); 1124 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 1125 assertTrue(other.isInterruptive()); 1126 assertNotEquals(-1, other.getLastAudiblyAlertedMs()); 1127 assertFalse(s.isInterruptive()); 1128 assertEquals(-1, s.getLastAudiblyAlertedMs()); 1129 } 1130 1131 @Test testQuietInterloperDoesNotCancelVibrate()1132 public void testQuietInterloperDoesNotCancelVibrate() throws Exception { 1133 NotificationRecord r = getBuzzyNotification(); 1134 NotificationRecord other = getQuietOtherNotification(); 1135 1136 // set up internal state 1137 mService.buzzBeepBlinkLocked(r); 1138 Mockito.reset(mVibrator); 1139 1140 // should not stop noise, since it does not own it 1141 mService.buzzBeepBlinkLocked(other); 1142 verifyNeverStopVibrate(); 1143 assertFalse(other.isInterruptive()); 1144 assertEquals(-1, other.getLastAudiblyAlertedMs()); 1145 } 1146 1147 @Test testQuietUpdateCancelsVibrate()1148 public void testQuietUpdateCancelsVibrate() { 1149 NotificationRecord r = getBuzzyNotification(); 1150 NotificationRecord s = getQuietNotification(); 1151 s.isUpdate = true; 1152 1153 // set up internal state 1154 mService.buzzBeepBlinkLocked(r); 1155 verifyVibrate(); 1156 1157 // quiet update should stop making noise 1158 mService.buzzBeepBlinkLocked(s); 1159 verifyStopVibrate(); 1160 assertTrue(r.isInterruptive()); 1161 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 1162 assertFalse(s.isInterruptive()); 1163 assertEquals(-1, s.getLastAudiblyAlertedMs()); 1164 } 1165 1166 @Test testQuietOnceUpdateCancelVibrate()1167 public void testQuietOnceUpdateCancelVibrate() throws Exception { 1168 NotificationRecord r = getBuzzyNotification(); 1169 NotificationRecord s = getQuietOnceNotification(); 1170 s.isUpdate = true; 1171 1172 // set up internal state 1173 mService.buzzBeepBlinkLocked(r); 1174 verifyVibrate(); 1175 1176 // stop making noise - this is a weird corner case, but quiet should override once 1177 mService.buzzBeepBlinkLocked(s); 1178 verifyStopVibrate(); 1179 assertTrue(r.isInterruptive()); 1180 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 1181 assertFalse(s.isInterruptive()); 1182 assertEquals(-1, s.getLastAudiblyAlertedMs()); 1183 } 1184 1185 @Test testQuietUpdateCancelsDemotedVibrate()1186 public void testQuietUpdateCancelsDemotedVibrate() throws Exception { 1187 NotificationRecord r = getBeepyNotification(); 1188 NotificationRecord s = getQuietNotification(); 1189 1190 // the phone is quiet 1191 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0); 1192 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); 1193 1194 mService.buzzBeepBlinkLocked(r); 1195 verifyDelayedVibrate(mService.getVibratorHelper().createFallbackVibration(false)); 1196 1197 // quiet update should stop making noise 1198 mService.buzzBeepBlinkLocked(s); 1199 verifyStopVibrate(); 1200 assertTrue(r.isInterruptive()); 1201 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 1202 assertFalse(s.isInterruptive()); 1203 assertEquals(-1, s.getLastAudiblyAlertedMs()); 1204 } 1205 1206 @Test testEmptyUriSoundTreatedAsNoSound()1207 public void testEmptyUriSoundTreatedAsNoSound() throws Exception { 1208 NotificationChannel channel = new NotificationChannel("test", "test", IMPORTANCE_HIGH); 1209 channel.setSound(Uri.EMPTY, null); 1210 final Notification n = new Builder(getContext(), "test") 1211 .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); 1212 1213 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid, 1214 mPid, n, mUser, null, System.currentTimeMillis()); 1215 NotificationRecord r = new NotificationRecord(getContext(), sbn, channel); 1216 mService.addNotification(r); 1217 1218 mService.buzzBeepBlinkLocked(r); 1219 verifyNeverBeep(); 1220 assertFalse(r.isInterruptive()); 1221 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1222 } 1223 1224 @Test testRepeatedSoundOverLimitMuted()1225 public void testRepeatedSoundOverLimitMuted() throws Exception { 1226 when(mUsageStats.isAlertRateLimited(any())).thenReturn(true); 1227 1228 NotificationRecord r = getBeepyNotification(); 1229 1230 mService.buzzBeepBlinkLocked(r); 1231 verifyNeverBeep(); 1232 assertFalse(r.isInterruptive()); 1233 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1234 } 1235 1236 @Test testPostingSilentNotificationDoesNotAffectRateLimiting()1237 public void testPostingSilentNotificationDoesNotAffectRateLimiting() throws Exception { 1238 NotificationRecord r = getQuietNotification(); 1239 mService.buzzBeepBlinkLocked(r); 1240 1241 verify(mUsageStats, never()).isAlertRateLimited(any()); 1242 } 1243 1244 @Test testPostingGroupSuppressedDoesNotAffectRateLimiting()1245 public void testPostingGroupSuppressedDoesNotAffectRateLimiting() throws Exception { 1246 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN); 1247 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; 1248 1249 mService.buzzBeepBlinkLocked(summary); 1250 verify(mUsageStats, never()).isAlertRateLimited(any()); 1251 } 1252 1253 @Test testGroupSuppressionFailureDoesNotAffectRateLimiting()1254 public void testGroupSuppressionFailureDoesNotAffectRateLimiting() { 1255 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY); 1256 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; 1257 1258 mService.buzzBeepBlinkLocked(summary); 1259 verify(mUsageStats, times(1)).isAlertRateLimited(any()); 1260 } 1261 1262 @Test testCrossUserSoundMuted()1263 public void testCrossUserSoundMuted() throws Exception { 1264 final Notification n = new Builder(getContext(), "test") 1265 .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); 1266 1267 int userId = mUser.getIdentifier() + 1; 1268 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid, 1269 mPid, n, UserHandle.of(userId), null, System.currentTimeMillis()); 1270 NotificationRecord r = new NotificationRecord(getContext(), sbn, 1271 new NotificationChannel("test", "test", IMPORTANCE_HIGH)); 1272 1273 mService.buzzBeepBlinkLocked(r); 1274 verifyNeverBeep(); 1275 assertFalse(r.isInterruptive()); 1276 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1277 } 1278 1279 @Test testA11yMinInitialPost()1280 public void testA11yMinInitialPost() throws Exception { 1281 NotificationRecord r = getQuietNotification(); 1282 r.setSystemImportance(IMPORTANCE_MIN); 1283 mService.buzzBeepBlinkLocked(r); 1284 verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt()); 1285 } 1286 1287 @Test testA11yQuietInitialPost()1288 public void testA11yQuietInitialPost() throws Exception { 1289 NotificationRecord r = getQuietNotification(); 1290 mService.buzzBeepBlinkLocked(r); 1291 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt()); 1292 } 1293 1294 @Test testA11yQuietUpdate()1295 public void testA11yQuietUpdate() throws Exception { 1296 NotificationRecord r = getQuietNotification(); 1297 mService.buzzBeepBlinkLocked(r); 1298 r.isUpdate = true; 1299 mService.buzzBeepBlinkLocked(r); 1300 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt()); 1301 } 1302 1303 @Test testA11yCrossUserEventNotSent()1304 public void testA11yCrossUserEventNotSent() throws Exception { 1305 final Notification n = new Builder(getContext(), "test") 1306 .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); 1307 int userId = mUser.getIdentifier() + 1; 1308 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid, 1309 mPid, n, UserHandle.of(userId), null, System.currentTimeMillis()); 1310 NotificationRecord r = new NotificationRecord(getContext(), sbn, 1311 new NotificationChannel("test", "test", IMPORTANCE_HIGH)); 1312 1313 mService.buzzBeepBlinkLocked(r); 1314 1315 verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt()); 1316 } 1317 1318 @Test testLightsScreenOn()1319 public void testLightsScreenOn() { 1320 mService.mScreenOn = true; 1321 NotificationRecord r = getLightsNotification(); 1322 mService.buzzBeepBlinkLocked(r); 1323 verifyNeverLights(); 1324 assertTrue(r.isInterruptive()); 1325 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1326 } 1327 1328 @Test testLightsInCall()1329 public void testLightsInCall() { 1330 mService.mInCallStateOffHook = true; 1331 NotificationRecord r = getLightsNotification(); 1332 mService.buzzBeepBlinkLocked(r); 1333 verifyNeverLights(); 1334 assertFalse(r.isInterruptive()); 1335 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1336 } 1337 1338 @Test testLightsSilentUpdate()1339 public void testLightsSilentUpdate() { 1340 NotificationRecord r = getLightsOnceNotification(); 1341 mService.buzzBeepBlinkLocked(r); 1342 verifyLights(); 1343 assertTrue(r.isInterruptive()); 1344 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1345 1346 r = getLightsOnceNotification(); 1347 r.isUpdate = true; 1348 mService.buzzBeepBlinkLocked(r); 1349 // checks that lights happened once, i.e. this new call didn't trigger them again 1350 verifyLights(); 1351 assertFalse(r.isInterruptive()); 1352 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1353 } 1354 1355 @Test testLightsUnimportant()1356 public void testLightsUnimportant() { 1357 NotificationRecord r = getLightsNotification(); 1358 r.setSystemImportance(IMPORTANCE_LOW); 1359 mService.buzzBeepBlinkLocked(r); 1360 verifyNeverLights(); 1361 assertFalse(r.isInterruptive()); 1362 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1363 } 1364 1365 @Test testLightsNoLights()1366 public void testLightsNoLights() { 1367 NotificationRecord r = getQuietNotification(); 1368 mService.buzzBeepBlinkLocked(r); 1369 verifyNeverLights(); 1370 assertFalse(r.isInterruptive()); 1371 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1372 } 1373 1374 @Test testLightsNoLightOnDevice()1375 public void testLightsNoLightOnDevice() { 1376 mService.mHasLight = false; 1377 NotificationRecord r = getLightsNotification(); 1378 mService.buzzBeepBlinkLocked(r); 1379 verifyNeverLights(); 1380 assertFalse(r.isInterruptive()); 1381 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1382 } 1383 1384 @Test testLightsLightsOffGlobally()1385 public void testLightsLightsOffGlobally() { 1386 mService.mNotificationPulseEnabled = false; 1387 NotificationRecord r = getLightsNotification(); 1388 mService.buzzBeepBlinkLocked(r); 1389 verifyNeverLights(); 1390 assertFalse(r.isInterruptive()); 1391 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1392 } 1393 1394 @Test testLightsDndIntercepted()1395 public void testLightsDndIntercepted() { 1396 NotificationRecord r = getLightsNotification(); 1397 r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS); 1398 mService.buzzBeepBlinkLocked(r); 1399 verifyNeverLights(); 1400 assertFalse(r.isInterruptive()); 1401 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1402 } 1403 1404 @Test testGroupAlertSummaryNoLightsChild()1405 public void testGroupAlertSummaryNoLightsChild() { 1406 NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY); 1407 1408 mService.buzzBeepBlinkLocked(child); 1409 1410 verifyNeverLights(); 1411 assertFalse(child.isInterruptive()); 1412 assertEquals(-1, child.getLastAudiblyAlertedMs()); 1413 } 1414 1415 @Test testGroupAlertSummaryLightsSummary()1416 public void testGroupAlertSummaryLightsSummary() { 1417 NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY); 1418 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; 1419 1420 mService.buzzBeepBlinkLocked(summary); 1421 1422 verifyLights(); 1423 // summaries should never count for interruptiveness counts 1424 assertFalse(summary.isInterruptive()); 1425 assertEquals(-1, summary.getLastAudiblyAlertedMs()); 1426 } 1427 1428 @Test testGroupAlertSummaryLightsNonGroupChild()1429 public void testGroupAlertSummaryLightsNonGroupChild() { 1430 NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_SUMMARY); 1431 1432 mService.buzzBeepBlinkLocked(nonGroup); 1433 1434 verifyLights(); 1435 assertTrue(nonGroup.isInterruptive()); 1436 assertEquals(-1, nonGroup.getLastAudiblyAlertedMs()); 1437 } 1438 1439 @Test testGroupAlertChildNoLightsSummary()1440 public void testGroupAlertChildNoLightsSummary() { 1441 NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN); 1442 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; 1443 1444 mService.buzzBeepBlinkLocked(summary); 1445 1446 verifyNeverLights(); 1447 assertFalse(summary.isInterruptive()); 1448 assertEquals(-1, summary.getLastAudiblyAlertedMs()); 1449 } 1450 1451 @Test testGroupAlertChildLightsChild()1452 public void testGroupAlertChildLightsChild() { 1453 NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN); 1454 1455 mService.buzzBeepBlinkLocked(child); 1456 1457 verifyLights(); 1458 assertTrue(child.isInterruptive()); 1459 assertEquals(-1, child.getLastAudiblyAlertedMs()); 1460 } 1461 1462 @Test testGroupAlertChildLightsNonGroupSummary()1463 public void testGroupAlertChildLightsNonGroupSummary() { 1464 NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_CHILDREN); 1465 1466 mService.buzzBeepBlinkLocked(nonGroup); 1467 1468 verifyLights(); 1469 assertTrue(nonGroup.isInterruptive()); 1470 assertEquals(-1, nonGroup.getLastAudiblyAlertedMs()); 1471 } 1472 1473 @Test testGroupAlertAllLightsGroup()1474 public void testGroupAlertAllLightsGroup() { 1475 NotificationRecord group = getLightsNotificationRecord("a", GROUP_ALERT_ALL); 1476 1477 mService.buzzBeepBlinkLocked(group); 1478 1479 verifyLights(); 1480 assertTrue(group.isInterruptive()); 1481 assertEquals(-1, group.getLastAudiblyAlertedMs()); 1482 } 1483 1484 @Test testLightsCheckCurrentUser()1485 public void testLightsCheckCurrentUser() { 1486 final Notification n = new Builder(getContext(), "test") 1487 .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); 1488 int userId = mUser.getIdentifier() + 10; 1489 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid, 1490 mPid, n, UserHandle.of(userId), null, System.currentTimeMillis()); 1491 NotificationRecord r = new NotificationRecord(getContext(), sbn, 1492 new NotificationChannel("test", "test", IMPORTANCE_HIGH)); 1493 1494 mService.buzzBeepBlinkLocked(r); 1495 verifyNeverLights(); 1496 assertFalse(r.isInterruptive()); 1497 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1498 } 1499 1500 @Test testListenerHintCall()1501 public void testListenerHintCall() throws Exception { 1502 NotificationChannel ringtoneChannel = 1503 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1504 ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI, 1505 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1506 NotificationRecord r = getCallRecord(1, ringtoneChannel, true); 1507 1508 mService.setHints(NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS); 1509 1510 mService.buzzBeepBlinkLocked(r); 1511 1512 verifyNeverBeep(); 1513 } 1514 1515 @Test testListenerHintCall_notificationSound()1516 public void testListenerHintCall_notificationSound() throws Exception { 1517 NotificationRecord r = getBeepyNotification(); 1518 1519 mService.setHints(NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS); 1520 1521 mService.buzzBeepBlinkLocked(r); 1522 1523 verifyBeepUnlooped(); 1524 } 1525 1526 @Test testListenerHintNotification()1527 public void testListenerHintNotification() throws Exception { 1528 NotificationRecord r = getBeepyNotification(); 1529 1530 mService.setHints(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS); 1531 1532 mService.buzzBeepBlinkLocked(r); 1533 1534 verifyNeverBeep(); 1535 } 1536 1537 @Test testListenerHintBoth()1538 public void testListenerHintBoth() throws Exception { 1539 NotificationChannel ringtoneChannel = 1540 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1541 ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI, 1542 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1543 NotificationRecord r = getCallRecord(1, ringtoneChannel, true); 1544 NotificationRecord s = getBeepyNotification(); 1545 1546 mService.setHints(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS 1547 | NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS); 1548 1549 mService.buzzBeepBlinkLocked(r); 1550 mService.buzzBeepBlinkLocked(s); 1551 1552 verifyNeverBeep(); 1553 } 1554 1555 @Test testListenerHintNotification_callSound()1556 public void testListenerHintNotification_callSound() throws Exception { 1557 NotificationChannel ringtoneChannel = 1558 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1559 ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI, 1560 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1561 NotificationRecord r = getCallRecord(1, ringtoneChannel, true); 1562 1563 mService.setHints(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS); 1564 1565 mService.buzzBeepBlinkLocked(r); 1566 1567 verifyBeepLooped(); 1568 } 1569 1570 @Test testCannotInterruptRingtoneInsistentBeep()1571 public void testCannotInterruptRingtoneInsistentBeep() throws Exception { 1572 NotificationChannel ringtoneChannel = 1573 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1574 ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI, 1575 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1576 NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); 1577 mService.addNotification(ringtoneNotification); 1578 1579 mService.buzzBeepBlinkLocked(ringtoneNotification); 1580 verifyBeepLooped(); 1581 1582 NotificationRecord interrupter = getBeepyOtherNotification(); 1583 assertTrue(mService.shouldMuteNotificationLocked(interrupter)); 1584 mService.buzzBeepBlinkLocked(interrupter); 1585 1586 verifyBeep(1); 1587 1588 assertFalse(interrupter.isInterruptive()); 1589 assertEquals(-1, interrupter.getLastAudiblyAlertedMs()); 1590 } 1591 1592 @Test testRingtoneInsistentBeep_canUpdate()1593 public void testRingtoneInsistentBeep_canUpdate() throws Exception { 1594 NotificationChannel ringtoneChannel = 1595 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1596 ringtoneChannel.setSound(Uri.fromParts("a", "b", "c"), 1597 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1598 ringtoneChannel.enableVibration(true); 1599 NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); 1600 mService.addNotification(ringtoneNotification); 1601 assertFalse(mService.shouldMuteNotificationLocked(ringtoneNotification)); 1602 mService.buzzBeepBlinkLocked(ringtoneNotification); 1603 verifyBeepLooped(); 1604 verifyDelayedVibrateLooped(); 1605 Mockito.reset(mVibrator); 1606 Mockito.reset(mRingtonePlayer); 1607 1608 assertFalse(mService.shouldMuteNotificationLocked(ringtoneNotification)); 1609 mService.buzzBeepBlinkLocked(ringtoneNotification); 1610 1611 // beep wasn't reset 1612 verifyNeverBeep(); 1613 verifyNeverVibrate(); 1614 verifyNeverStopAudio(); 1615 verifyNeverStopVibrate(); 1616 } 1617 1618 @Test testRingtoneInsistentBeep_clearEffectsStopsSoundAndVibration()1619 public void testRingtoneInsistentBeep_clearEffectsStopsSoundAndVibration() throws Exception { 1620 NotificationChannel ringtoneChannel = 1621 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1622 ringtoneChannel.setSound(Uri.fromParts("a", "b", "c"), 1623 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1624 ringtoneChannel.enableVibration(true); 1625 NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); 1626 mService.addNotification(ringtoneNotification); 1627 assertFalse(mService.shouldMuteNotificationLocked(ringtoneNotification)); 1628 mService.buzzBeepBlinkLocked(ringtoneNotification); 1629 verifyBeepLooped(); 1630 verifyDelayedVibrateLooped(); 1631 1632 mService.clearSoundLocked(); 1633 mService.clearVibrateLocked(); 1634 1635 verifyStopAudio(); 1636 verifyStopVibrate(); 1637 } 1638 1639 @Test testRingtoneInsistentBeep_neverVibratesWhenEffectsClearedBeforeDelay()1640 public void testRingtoneInsistentBeep_neverVibratesWhenEffectsClearedBeforeDelay() 1641 throws Exception { 1642 NotificationChannel ringtoneChannel = 1643 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1644 ringtoneChannel.setSound(Uri.fromParts("a", "b", "c"), 1645 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1646 ringtoneChannel.enableVibration(true); 1647 NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); 1648 mService.addNotification(ringtoneNotification); 1649 assertFalse(mService.shouldMuteNotificationLocked(ringtoneNotification)); 1650 mService.buzzBeepBlinkLocked(ringtoneNotification); 1651 verifyBeepLooped(); 1652 verifyNeverVibrate(); 1653 1654 mService.clearSoundLocked(); 1655 mService.clearVibrateLocked(); 1656 1657 verifyStopAudio(); 1658 verifyDelayedNeverVibrate(); 1659 } 1660 1661 @Test testCannotInterruptRingtoneInsistentBuzz()1662 public void testCannotInterruptRingtoneInsistentBuzz() { 1663 NotificationChannel ringtoneChannel = 1664 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1665 ringtoneChannel.setSound(Uri.EMPTY, 1666 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1667 ringtoneChannel.enableVibration(true); 1668 NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); 1669 assertFalse(mService.shouldMuteNotificationLocked(ringtoneNotification)); 1670 1671 mService.buzzBeepBlinkLocked(ringtoneNotification); 1672 verifyVibrateLooped(); 1673 1674 NotificationRecord interrupter = getBuzzyOtherNotification(); 1675 assertTrue(mService.shouldMuteNotificationLocked(interrupter)); 1676 mService.buzzBeepBlinkLocked(interrupter); 1677 1678 verifyVibrate(1); 1679 1680 assertFalse(interrupter.isInterruptive()); 1681 assertEquals(-1, interrupter.getLastAudiblyAlertedMs()); 1682 } 1683 1684 @Test testCanInterruptRingtoneNonInsistentBeep()1685 public void testCanInterruptRingtoneNonInsistentBeep() throws Exception { 1686 NotificationChannel ringtoneChannel = 1687 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1688 ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI, 1689 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1690 NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, false); 1691 1692 mService.buzzBeepBlinkLocked(ringtoneNotification); 1693 verifyBeepUnlooped(); 1694 1695 NotificationRecord interrupter = getBeepyOtherNotification(); 1696 mService.buzzBeepBlinkLocked(interrupter); 1697 1698 verifyBeep(2); 1699 1700 assertTrue(interrupter.isInterruptive()); 1701 } 1702 1703 @Test testCanInterruptRingtoneNonInsistentBuzz()1704 public void testCanInterruptRingtoneNonInsistentBuzz() { 1705 NotificationChannel ringtoneChannel = 1706 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1707 ringtoneChannel.setSound(null, 1708 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1709 ringtoneChannel.enableVibration(true); 1710 NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, false); 1711 1712 mService.buzzBeepBlinkLocked(ringtoneNotification); 1713 verifyVibrate(); 1714 1715 NotificationRecord interrupter = getBuzzyOtherNotification(); 1716 mService.buzzBeepBlinkLocked(interrupter); 1717 1718 verifyVibrate(2); 1719 1720 assertTrue(interrupter.isInterruptive()); 1721 } 1722 1723 @Test testRingtoneInsistentBeep_doesNotBlockFutureSoundsOnceStopped()1724 public void testRingtoneInsistentBeep_doesNotBlockFutureSoundsOnceStopped() throws Exception { 1725 NotificationChannel ringtoneChannel = 1726 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1727 ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI, 1728 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1729 NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); 1730 1731 mService.buzzBeepBlinkLocked(ringtoneNotification); 1732 verifyBeepLooped(); 1733 1734 mService.clearSoundLocked(); 1735 1736 NotificationRecord interrupter = getBeepyOtherNotification(); 1737 mService.buzzBeepBlinkLocked(interrupter); 1738 1739 verifyBeep(2); 1740 1741 assertTrue(interrupter.isInterruptive()); 1742 } 1743 1744 @Test testRingtoneInsistentBuzz_doesNotBlockFutureSoundsOnceStopped()1745 public void testRingtoneInsistentBuzz_doesNotBlockFutureSoundsOnceStopped() { 1746 NotificationChannel ringtoneChannel = 1747 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1748 ringtoneChannel.setSound(null, 1749 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); 1750 ringtoneChannel.enableVibration(true); 1751 NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); 1752 1753 mService.buzzBeepBlinkLocked(ringtoneNotification); 1754 verifyVibrateLooped(); 1755 1756 mService.clearVibrateLocked(); 1757 1758 NotificationRecord interrupter = getBuzzyOtherNotification(); 1759 mService.buzzBeepBlinkLocked(interrupter); 1760 1761 verifyVibrate(2); 1762 1763 assertTrue(interrupter.isInterruptive()); 1764 } 1765 1766 @Test testCanInterruptNonRingtoneInsistentBeep()1767 public void testCanInterruptNonRingtoneInsistentBeep() throws Exception { 1768 NotificationChannel fakeRingtoneChannel = 1769 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1770 NotificationRecord ringtoneNotification = getCallRecord(1, fakeRingtoneChannel, true); 1771 1772 mService.buzzBeepBlinkLocked(ringtoneNotification); 1773 verifyBeepLooped(); 1774 1775 NotificationRecord interrupter = getBeepyOtherNotification(); 1776 mService.buzzBeepBlinkLocked(interrupter); 1777 1778 verifyBeep(2); 1779 1780 assertTrue(interrupter.isInterruptive()); 1781 } 1782 1783 @Test testCanInterruptNonRingtoneInsistentBuzz()1784 public void testCanInterruptNonRingtoneInsistentBuzz() { 1785 NotificationChannel fakeRingtoneChannel = 1786 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); 1787 fakeRingtoneChannel.enableVibration(true); 1788 fakeRingtoneChannel.setSound(null, 1789 new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION).build()); 1790 NotificationRecord ringtoneNotification = getCallRecord(1, fakeRingtoneChannel, true); 1791 1792 mService.buzzBeepBlinkLocked(ringtoneNotification); 1793 1794 NotificationRecord interrupter = getBuzzyOtherNotification(); 1795 mService.buzzBeepBlinkLocked(interrupter); 1796 1797 verifyVibrate(2); 1798 1799 assertTrue(interrupter.isInterruptive()); 1800 } 1801 1802 @Test testBubbleSuppressedNotificationDoesntMakeSound()1803 public void testBubbleSuppressedNotificationDoesntMakeSound() { 1804 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder( 1805 mock(PendingIntent.class), mock(Icon.class)) 1806 .build(); 1807 1808 NotificationRecord record = getBuzzyNotification(); 1809 metadata.setFlags(Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 1810 record.getNotification().setBubbleMetadata(metadata); 1811 record.setAllowBubble(true); 1812 record.getNotification().flags |= FLAG_BUBBLE; 1813 record.isUpdate = true; 1814 record.setInterruptive(false); 1815 1816 mService.buzzBeepBlinkLocked(record); 1817 verifyNeverVibrate(); 1818 } 1819 1820 @Test testOverflowBubbleSuppressedNotificationDoesntMakeSound()1821 public void testOverflowBubbleSuppressedNotificationDoesntMakeSound() { 1822 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder( 1823 mock(PendingIntent.class), mock(Icon.class)) 1824 .build(); 1825 1826 NotificationRecord record = getBuzzyNotification(); 1827 metadata.setFlags(Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 1828 record.getNotification().setBubbleMetadata(metadata); 1829 record.setFlagBubbleRemoved(true); 1830 record.setAllowBubble(true); 1831 record.isUpdate = true; 1832 record.setInterruptive(false); 1833 1834 mService.buzzBeepBlinkLocked(record); 1835 verifyNeverVibrate(); 1836 } 1837 1838 @Test testBubbleUpdateMakesSound()1839 public void testBubbleUpdateMakesSound() { 1840 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder( 1841 mock(PendingIntent.class), mock(Icon.class)) 1842 .build(); 1843 1844 NotificationRecord record = getBuzzyNotification(); 1845 record.getNotification().setBubbleMetadata(metadata); 1846 record.setAllowBubble(true); 1847 record.getNotification().flags |= FLAG_BUBBLE; 1848 record.isUpdate = true; 1849 record.setInterruptive(true); 1850 1851 mService.buzzBeepBlinkLocked(record); 1852 verifyVibrate(1); 1853 } 1854 1855 @Test testNewBubbleSuppressedNotifMakesSound()1856 public void testNewBubbleSuppressedNotifMakesSound() { 1857 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder( 1858 mock(PendingIntent.class), mock(Icon.class)) 1859 .build(); 1860 1861 NotificationRecord record = getBuzzyNotification(); 1862 metadata.setFlags(Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); 1863 record.getNotification().setBubbleMetadata(metadata); 1864 record.setAllowBubble(true); 1865 record.getNotification().flags |= FLAG_BUBBLE; 1866 record.isUpdate = false; 1867 record.setInterruptive(true); 1868 1869 mService.buzzBeepBlinkLocked(record); 1870 verifyVibrate(1); 1871 } 1872 1873 @Test testStartFlashNotificationEvent_receiveBeepyNotification()1874 public void testStartFlashNotificationEvent_receiveBeepyNotification() throws Exception { 1875 NotificationRecord r = getBeepyNotification(); 1876 1877 mService.buzzBeepBlinkLocked(r); 1878 1879 verifyBeepUnlooped(); 1880 verifyNeverVibrate(); 1881 verify(mAccessibilityService).startFlashNotificationEvent(any(), anyInt(), 1882 eq(r.getSbn().getPackageName())); 1883 assertTrue(r.isInterruptive()); 1884 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 1885 } 1886 1887 @Test testStartFlashNotificationEvent_receiveBuzzyNotification()1888 public void testStartFlashNotificationEvent_receiveBuzzyNotification() throws Exception { 1889 NotificationRecord r = getBuzzyNotification(); 1890 1891 mService.buzzBeepBlinkLocked(r); 1892 1893 verifyNeverBeep(); 1894 verifyVibrate(); 1895 verify(mAccessibilityService).startFlashNotificationEvent(any(), anyInt(), 1896 eq(r.getSbn().getPackageName())); 1897 assertTrue(r.isInterruptive()); 1898 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 1899 } 1900 1901 @Test testStartFlashNotificationEvent_receiveBuzzyBeepyNotification()1902 public void testStartFlashNotificationEvent_receiveBuzzyBeepyNotification() throws Exception { 1903 NotificationRecord r = getBuzzyBeepyNotification(); 1904 1905 mService.buzzBeepBlinkLocked(r); 1906 1907 verifyBeepUnlooped(); 1908 verifyDelayedVibrate(r.getVibration()); 1909 verify(mAccessibilityService).startFlashNotificationEvent(any(), anyInt(), 1910 eq(r.getSbn().getPackageName())); 1911 assertTrue(r.isInterruptive()); 1912 assertNotEquals(-1, r.getLastAudiblyAlertedMs()); 1913 } 1914 1915 @Test testStartFlashNotificationEvent_receiveBuzzyBeepyNotification_ringerModeSilent()1916 public void testStartFlashNotificationEvent_receiveBuzzyBeepyNotification_ringerModeSilent() 1917 throws Exception { 1918 NotificationRecord r = getBuzzyBeepyNotification(); 1919 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT); 1920 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0); 1921 1922 mService.buzzBeepBlinkLocked(r); 1923 1924 verifyNeverBeep(); 1925 verifyNeverVibrate(); 1926 verify(mAccessibilityService).startFlashNotificationEvent(any(), anyInt(), 1927 eq(r.getSbn().getPackageName())); 1928 assertFalse(r.isInterruptive()); 1929 assertEquals(-1, r.getLastAudiblyAlertedMs()); 1930 } 1931 1932 static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> { 1933 private final int mRepeatIndex; 1934 VibrateRepeatMatcher(int repeatIndex)1935 VibrateRepeatMatcher(int repeatIndex) { 1936 mRepeatIndex = repeatIndex; 1937 } 1938 1939 @Override matches(VibrationEffect actual)1940 public boolean matches(VibrationEffect actual) { 1941 if (actual instanceof VibrationEffect.Composed 1942 && ((VibrationEffect.Composed) actual).getRepeatIndex() == mRepeatIndex) { 1943 return true; 1944 } 1945 // All non-waveform effects are essentially one shots. 1946 return mRepeatIndex == -1; 1947 } 1948 1949 @Override toString()1950 public String toString() { 1951 return "repeatIndex=" + mRepeatIndex; 1952 } 1953 } 1954 } 1955