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