blob: bdba3d5cd6779f9ac3131c1c1e26453e676d350b [file] [log] [blame]
Chris Wren93bb8b82016-03-29 14:35:05 -04001/*
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 */
16package com.android.server.notification;
17
Julia Reynoldsa79c3712017-04-21 10:29:57 -040018import static android.app.Notification.GROUP_ALERT_ALL;
19import static android.app.Notification.GROUP_ALERT_CHILDREN;
20import static android.app.Notification.GROUP_ALERT_SUMMARY;
Julia Reynoldsca80d162017-04-23 12:39:32 -040021import static android.app.NotificationManager.IMPORTANCE_HIGH;
Julia Reynolds54369232018-07-03 10:43:35 -040022import static android.app.NotificationManager.IMPORTANCE_LOW;
Julia Reynolds94187562017-10-10 13:58:49 -040023import static android.app.NotificationManager.IMPORTANCE_MIN;
Julia Reynolds54369232018-07-03 10:43:35 -040024import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
Julia Reynoldsca80d162017-04-23 12:39:32 -040025
Julia Reynolds1fac86e2018-03-07 08:30:37 -050026import static junit.framework.Assert.assertFalse;
Julia Reynolds0c299d42016-11-15 14:37:04 -050027import static junit.framework.Assert.assertNull;
28import static junit.framework.Assert.assertTrue;
29
Julia Reynolds76c096d2017-06-19 08:16:04 -040030import static org.mockito.Matchers.any;
Chris Wren93bb8b82016-03-29 14:35:05 -040031import static org.mockito.Matchers.anyBoolean;
32import static org.mockito.Matchers.anyInt;
33import static org.mockito.Matchers.anyObject;
34import static org.mockito.Matchers.anyString;
Michael Wright71216972017-01-31 18:33:54 +000035import static org.mockito.Matchers.argThat;
Chris Wren93bb8b82016-03-29 14:35:05 -040036import static org.mockito.Matchers.eq;
37import static org.mockito.Mockito.never;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070038import static org.mockito.Mockito.spy;
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -070039import static org.mockito.Mockito.timeout;
Chris Wren93bb8b82016-03-29 14:35:05 -040040import static org.mockito.Mockito.times;
41import static org.mockito.Mockito.verify;
42import static org.mockito.Mockito.when;
43
Tony Mantlerab55f0f2017-06-16 10:50:00 -070044import android.app.ActivityManager;
45import android.app.Notification;
46import android.app.Notification.Builder;
47import android.app.NotificationChannel;
48import android.app.NotificationManager;
49import android.content.Context;
50import android.content.pm.PackageManager;
51import android.graphics.Color;
52import android.media.AudioAttributes;
53import android.media.AudioManager;
54import android.net.Uri;
55import android.os.Handler;
56import android.os.RemoteException;
57import android.os.UserHandle;
58import android.os.VibrationEffect;
59import android.os.Vibrator;
60import android.provider.Settings;
61import android.service.notification.StatusBarNotification;
62import android.support.test.runner.AndroidJUnit4;
63import android.test.suitebuilder.annotation.SmallTest;
Julia Reynolds94187562017-10-10 13:58:49 -040064import android.view.accessibility.AccessibilityEvent;
65import android.view.accessibility.AccessibilityManager;
66import android.view.accessibility.IAccessibilityManager;
67import android.view.accessibility.IAccessibilityManagerClient;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070068
Julia Reynolds94187562017-10-10 13:58:49 -040069import com.android.internal.util.IntPair;
Jason Monk74f5e362017-12-06 08:56:33 -050070import com.android.server.UiServiceTestCase;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070071import com.android.server.lights.Light;
72
73import org.junit.Before;
74import org.junit.Test;
75import org.junit.runner.RunWith;
76import org.mockito.ArgumentMatcher;
77import org.mockito.Mock;
78import org.mockito.Mockito;
79import org.mockito.MockitoAnnotations;
80
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -040081@SmallTest
82@RunWith(AndroidJUnit4.class)
Jason Monk74f5e362017-12-06 08:56:33 -050083public class BuzzBeepBlinkTest extends UiServiceTestCase {
Chris Wren93bb8b82016-03-29 14:35:05 -040084
85 @Mock AudioManager mAudioManager;
86 @Mock Vibrator mVibrator;
87 @Mock android.media.IRingtonePlayer mRingtonePlayer;
Julia Reynoldsb5e44b72016-08-16 15:00:25 -040088 @Mock Light mLight;
Julia Reynoldseb3dca72017-07-11 10:39:58 -040089 @Mock
90 NotificationManagerService.WorkerHandler mHandler;
Julia Reynolds76c096d2017-06-19 08:16:04 -040091 @Mock
92 NotificationUsageStats mUsageStats;
Julia Reynolds94187562017-10-10 13:58:49 -040093 @Mock
94 IAccessibilityManager mAccessibilityService;
Chris Wren93bb8b82016-03-29 14:35:05 -040095
96 private NotificationManagerService mService;
97 private String mPkg = "com.android.server.notification";
98 private int mId = 1001;
99 private int mOtherId = 1002;
100 private String mTag = null;
101 private int mUid = 1000;
102 private int mPid = 2000;
Chris Wren93bb8b82016-03-29 14:35:05 -0400103 private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
104
Michael Wright71216972017-01-31 18:33:54 +0000105 private VibrateRepeatMatcher mVibrateOnceMatcher = new VibrateRepeatMatcher(-1);
106 private VibrateRepeatMatcher mVibrateLoopMatcher = new VibrateRepeatMatcher(0);
107
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400108 private static final long[] CUSTOM_VIBRATION = new long[] {
109 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
110 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
111 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 };
112 private static final Uri CUSTOM_SOUND = Settings.System.DEFAULT_ALARM_ALERT_URI;
Julia Reynolds619a69f2017-01-27 15:11:38 -0500113 private static final AudioAttributes CUSTOM_ATTRIBUTES = new AudioAttributes.Builder()
114 .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
115 .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
116 .build();
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400117 private static final int CUSTOM_LIGHT_COLOR = Color.BLACK;
118 private static final int CUSTOM_LIGHT_ON = 10000;
119 private static final int CUSTOM_LIGHT_OFF = 10000;
Michael Wright71216972017-01-31 18:33:54 +0000120 private static final long[] FALLBACK_VIBRATION_PATTERN = new long[] {100, 100, 100};
121 private static final VibrationEffect FALLBACK_VIBRATION =
122 VibrationEffect.createWaveform(FALLBACK_VIBRATION_PATTERN, -1);
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700123 private static final int MAX_VIBRATION_DELAY = 1000;
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400124
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400125 @Before
Julia Reynolds94187562017-10-10 13:58:49 -0400126 public void setUp() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400127 MockitoAnnotations.initMocks(this);
128
129 when(mAudioManager.isAudioFocusExclusive()).thenReturn(false);
130 when(mAudioManager.getRingtonePlayer()).thenReturn(mRingtonePlayer);
131 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
132 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynolds76c096d2017-06-19 08:16:04 -0400133 when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
134
Julia Reynolds94187562017-10-10 13:58:49 -0400135 long serviceReturnValue = IntPair.of(
136 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED,
137 AccessibilityEvent.TYPES_ALL_MASK);
138 when(mAccessibilityService.addClient(any(), anyInt())).thenReturn(serviceReturnValue);
139 AccessibilityManager accessibilityManager =
140 new AccessibilityManager(Handler.getMain(), mAccessibilityService, 0);
141 verify(mAccessibilityService).addClient(any(IAccessibilityManagerClient.class), anyInt());
142 assertTrue(accessibilityManager.isEnabled());
143
144 mService = spy(new NotificationManagerService(getContext()));
Chris Wren93bb8b82016-03-29 14:35:05 -0400145 mService.setAudioManager(mAudioManager);
146 mService.setVibrator(mVibrator);
147 mService.setSystemReady(true);
148 mService.setHandler(mHandler);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400149 mService.setLights(mLight);
150 mService.setScreenOn(false);
Michael Wright71216972017-01-31 18:33:54 +0000151 mService.setFallbackVibrationPattern(FALLBACK_VIBRATION_PATTERN);
Julia Reynolds76c096d2017-06-19 08:16:04 -0400152 mService.setUsageStats(mUsageStats);
Julia Reynolds94187562017-10-10 13:58:49 -0400153 mService.setAccessibilityManager(accessibilityManager);
Julia Reynolds54369232018-07-03 10:43:35 -0400154 mService.mScreenOn = false;
155 mService.mInCall = false;
156 mService.mNotificationPulseEnabled = true;
Chris Wren93bb8b82016-03-29 14:35:05 -0400157 }
158
159 //
160 // Convenience functions for creating notification records
161 //
162
163 private NotificationRecord getNoisyOtherNotification() {
164 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400165 true /* noisy */, true /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400166 }
167
168 private NotificationRecord getBeepyNotification() {
169 return getNotificationRecord(mId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400170 true /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400171 }
172
173 private NotificationRecord getBeepyOnceNotification() {
174 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400175 true /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400176 }
177
178 private NotificationRecord getQuietNotification() {
179 return getNotificationRecord(mId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400180 false /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400181 }
182
183 private NotificationRecord getQuietOtherNotification() {
184 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400185 false /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400186 }
187
188 private NotificationRecord getQuietOnceNotification() {
189 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400190 false /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400191 }
192
193 private NotificationRecord getInsistentBeepyNotification() {
194 return getNotificationRecord(mId, true /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400195 true /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400196 }
197
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700198 private NotificationRecord getInsistentBeepyLeanbackNotification() {
199 return getLeanbackNotificationRecord(mId, true /* insistent */, false /* once */,
200 true /* noisy */, false /* buzzy*/, false /* lights */);
201 }
202
Chris Wren93bb8b82016-03-29 14:35:05 -0400203 private NotificationRecord getBuzzyNotification() {
204 return getNotificationRecord(mId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400205 false /* noisy */, true /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400206 }
207
208 private NotificationRecord getBuzzyOnceNotification() {
209 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400210 false /* noisy */, true /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400211 }
212
213 private NotificationRecord getInsistentBuzzyNotification() {
214 return getNotificationRecord(mId, true /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400215 false /* noisy */, true /* buzzy*/, false /* lights */);
216 }
217
Julia Reynolds0c299d42016-11-15 14:37:04 -0500218 private NotificationRecord getBuzzyBeepyNotification() {
219 return getNotificationRecord(mId, false /* insistent */, false /* once */,
220 true /* noisy */, true /* buzzy*/, false /* lights */);
221 }
222
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400223 private NotificationRecord getLightsNotification() {
Julia Reynolds54369232018-07-03 10:43:35 -0400224 return getNotificationRecord(mId, false /* insistent */, false /* once */,
225 false /* noisy */, false /* buzzy*/, true /* lights */);
226 }
227
228 private NotificationRecord getLightsOnceNotification() {
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400229 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynolds54369232018-07-03 10:43:35 -0400230 false /* noisy */, false /* buzzy*/, true /* lights */);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400231 }
232
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400233 private NotificationRecord getCustomLightsNotification() {
234 return getNotificationRecord(mId, false /* insistent */, true /* once */,
235 false /* noisy */, true /* buzzy*/, true /* lights */,
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400236 true /* defaultVibration */, true /* defaultSound */, false /* defaultLights */,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700237 null, Notification.GROUP_ALERT_ALL, false);
Chris Wren93bb8b82016-03-29 14:35:05 -0400238 }
239
240 private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400241 boolean noisy, boolean buzzy, boolean lights) {
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400242 return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, true,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700243 null, Notification.GROUP_ALERT_ALL, false);
244 }
245
246 private NotificationRecord getLeanbackNotificationRecord(int id, boolean insistent, boolean once,
247 boolean noisy, boolean buzzy, boolean lights) {
248 return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, true,
249 null, Notification.GROUP_ALERT_ALL, true);
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400250 }
251
252 private NotificationRecord getBeepyNotificationRecord(String groupKey, int groupAlertBehavior) {
253 return getNotificationRecord(mId, false, false, true, false, false, true, true, true,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700254 groupKey, groupAlertBehavior, false);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400255 }
256
Julia Reynolds54369232018-07-03 10:43:35 -0400257 private NotificationRecord getLightsNotificationRecord(String groupKey,
258 int groupAlertBehavior) {
259 return getNotificationRecord(mId, false, false, false, false, true /*lights*/, true, true,
260 true, groupKey, groupAlertBehavior, false);
261 }
262
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400263 private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
264 boolean noisy, boolean buzzy, boolean lights, boolean defaultVibration,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700265 boolean defaultSound, boolean defaultLights, String groupKey, int groupAlertBehavior,
266 boolean isLeanback) {
Julia Reynolds0c299d42016-11-15 14:37:04 -0500267 NotificationChannel channel =
Julia Reynoldsca80d162017-04-23 12:39:32 -0400268 new NotificationChannel("test", "test", IMPORTANCE_HIGH);
Chris Wren93bb8b82016-03-29 14:35:05 -0400269 final Builder builder = new Builder(getContext())
270 .setContentTitle("foo")
271 .setSmallIcon(android.R.drawable.sym_def_app_icon)
272 .setPriority(Notification.PRIORITY_HIGH)
273 .setOnlyAlertOnce(once);
274
275 int defaults = 0;
276 if (noisy) {
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400277 if (defaultSound) {
278 defaults |= Notification.DEFAULT_SOUND;
Julia Reynolds619a69f2017-01-27 15:11:38 -0500279 channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
280 Notification.AUDIO_ATTRIBUTES_DEFAULT);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400281 } else {
282 builder.setSound(CUSTOM_SOUND);
Julia Reynolds619a69f2017-01-27 15:11:38 -0500283 channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400284 }
Julia Reynolds184b86d2017-04-12 13:27:58 -0400285 } else {
286 channel.setSound(null, null);
Chris Wren93bb8b82016-03-29 14:35:05 -0400287 }
288 if (buzzy) {
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400289 if (defaultVibration) {
290 defaults |= Notification.DEFAULT_VIBRATE;
291 } else {
292 builder.setVibrate(CUSTOM_VIBRATION);
Julia Reynoldsf57de462016-11-23 11:31:46 -0500293 channel.setVibrationPattern(CUSTOM_VIBRATION);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400294 }
Julia Reynoldsf57de462016-11-23 11:31:46 -0500295 channel.enableVibration(true);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400296 }
297 if (lights) {
298 if (defaultLights) {
299 defaults |= Notification.DEFAULT_LIGHTS;
300 } else {
301 builder.setLights(CUSTOM_LIGHT_COLOR, CUSTOM_LIGHT_ON, CUSTOM_LIGHT_OFF);
302 }
Julia Reynolds529e3322017-02-06 08:33:01 -0500303 channel.enableLights(true);
Chris Wren93bb8b82016-03-29 14:35:05 -0400304 }
305 builder.setDefaults(defaults);
306
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400307 builder.setGroup(groupKey);
308 builder.setGroupAlertBehavior(groupAlertBehavior);
309
Chris Wren93bb8b82016-03-29 14:35:05 -0400310 Notification n = builder.build();
311 if (insistent) {
312 n.flags |= Notification.FLAG_INSISTENT;
313 }
Julia Reynolds0c299d42016-11-15 14:37:04 -0500314
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700315 Context context = spy(getContext());
316 PackageManager packageManager = spy(context.getPackageManager());
317 when(context.getPackageManager()).thenReturn(packageManager);
318 when(packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
319 .thenReturn(isLeanback);
320
Julia Reynolds924eed12017-01-19 09:52:07 -0500321 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid,
Julia Reynolds423b9fc2016-11-09 09:51:08 -0500322 mPid, n, mUser, null, System.currentTimeMillis());
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700323 NotificationRecord r = new NotificationRecord(context, sbn, channel);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400324 mService.addNotification(r);
325 return r;
Chris Wren93bb8b82016-03-29 14:35:05 -0400326 }
327
328 //
329 // Convenience functions for interacting with mocks
330 //
331
332 private void verifyNeverBeep() throws RemoteException {
333 verify(mRingtonePlayer, never()).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
334 anyBoolean(), (AudioAttributes) anyObject());
335 }
336
337 private void verifyBeep() throws RemoteException {
338 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
339 eq(true), (AudioAttributes) anyObject());
340 }
341
342 private void verifyBeepLooped() throws RemoteException {
343 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
344 eq(false), (AudioAttributes) anyObject());
345 }
346
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400347 private void verifyCustomBeep() throws RemoteException {
348 verify(mRingtonePlayer, times(1)).playAsync(eq(CUSTOM_SOUND), (UserHandle) anyObject(),
349 eq(false), (AudioAttributes) anyObject());
350 }
351
Chris Wren93bb8b82016-03-29 14:35:05 -0400352 private void verifyNeverStopAudio() throws RemoteException {
353 verify(mRingtonePlayer, never()).stopAsync();
354 }
355
356 private void verifyStopAudio() throws RemoteException {
357 verify(mRingtonePlayer, times(1)).stopAsync();
358 }
359
360 private void verifyNeverVibrate() {
Michael Wright71216972017-01-31 18:33:54 +0000361 verify(mVibrator, never()).vibrate(anyInt(), anyString(), (VibrationEffect) anyObject(),
362 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400363 }
364
365 private void verifyVibrate() {
Michael Wright71216972017-01-31 18:33:54 +0000366 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateOnceMatcher),
367 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400368 }
369
370 private void verifyVibrateLooped() {
Michael Wright71216972017-01-31 18:33:54 +0000371 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateLoopMatcher),
372 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400373 }
374
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700375 private void verifyDelayedVibrateLooped() {
376 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
377 argThat(mVibrateLoopMatcher), (AudioAttributes) anyObject());
378 }
379
Chris Wren93bb8b82016-03-29 14:35:05 -0400380 private void verifyStopVibrate() {
381 verify(mVibrator, times(1)).cancel();
382 }
383
384 private void verifyNeverStopVibrate() throws RemoteException {
385 verify(mVibrator, never()).cancel();
386 }
387
Julia Reynolds54369232018-07-03 10:43:35 -0400388 private void verifyNeverLights() {
389 verify(mLight, never()).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
390 }
391
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400392 private void verifyLights() {
Julia Reynolds033a4122017-01-31 16:50:38 -0500393 verify(mLight, times(1)).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400394 }
395
396 private void verifyCustomLights() {
Julia Reynolds033a4122017-01-31 16:50:38 -0500397 verify(mLight, times(1)).setFlashing(
398 eq(CUSTOM_LIGHT_COLOR), anyInt(), eq(CUSTOM_LIGHT_ON), eq(CUSTOM_LIGHT_OFF));
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400399 }
400
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400401 //
402 // Tests
403 //
404
405 @Test
406 public void testLights() throws Exception {
407 NotificationRecord r = getLightsNotification();
408 r.setImportance(NotificationManager.IMPORTANCE_DEFAULT, "for testing");
409
410 mService.buzzBeepBlinkLocked(r);
411
412 verifyLights();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500413 assertTrue(r.isInterruptive());
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400414 }
415
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400416 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400417 public void testBeep() throws Exception {
418 NotificationRecord r = getBeepyNotification();
419
420 mService.buzzBeepBlinkLocked(r);
421
422 verifyBeepLooped();
423 verifyNeverVibrate();
Julia Reynolds94187562017-10-10 13:58:49 -0400424 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500425 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400426 }
427
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400428 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400429 public void testBeepInsistently() throws Exception {
430 NotificationRecord r = getInsistentBeepyNotification();
431
432 mService.buzzBeepBlinkLocked(r);
433
434 verifyBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500435 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400436 }
437
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400438 @Test
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700439 public void testNoLeanbackBeep() throws Exception {
440 NotificationRecord r = getInsistentBeepyLeanbackNotification();
441
442 mService.buzzBeepBlinkLocked(r);
443
444 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500445 assertFalse(r.isInterruptive());
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700446 }
447
448 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400449 public void testNoInterruptionForMin() throws Exception {
450 NotificationRecord r = getBeepyNotification();
Julia Reynolds85769912016-10-25 09:08:57 -0400451 r.setImportance(NotificationManager.IMPORTANCE_MIN, "foo");
Chris Wren93bb8b82016-03-29 14:35:05 -0400452
453 mService.buzzBeepBlinkLocked(r);
454
455 verifyNeverBeep();
456 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500457 assertFalse(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400458 }
459
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400460 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400461 public void testNoInterruptionForIntercepted() throws Exception {
462 NotificationRecord r = getBeepyNotification();
463 r.setIntercepted(true);
464
465 mService.buzzBeepBlinkLocked(r);
466
467 verifyNeverBeep();
468 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500469 assertFalse(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400470 }
471
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400472 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400473 public void testBeepTwice() throws Exception {
474 NotificationRecord r = getBeepyNotification();
475
476 // set up internal state
477 mService.buzzBeepBlinkLocked(r);
478 Mockito.reset(mRingtonePlayer);
479
480 // update should beep
481 r.isUpdate = true;
482 mService.buzzBeepBlinkLocked(r);
483 verifyBeepLooped();
Julia Reynolds94187562017-10-10 13:58:49 -0400484 verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500485 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400486 }
487
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400488 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400489 public void testHonorAlertOnlyOnceForBeep() throws Exception {
490 NotificationRecord r = getBeepyNotification();
491 NotificationRecord s = getBeepyOnceNotification();
492 s.isUpdate = true;
493
494 // set up internal state
495 mService.buzzBeepBlinkLocked(r);
496 Mockito.reset(mRingtonePlayer);
497
498 // update should not beep
499 mService.buzzBeepBlinkLocked(s);
500 verifyNeverBeep();
Julia Reynolds94187562017-10-10 13:58:49 -0400501 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
Chris Wren93bb8b82016-03-29 14:35:05 -0400502 }
503
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400504 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400505 public void testNoisyUpdateDoesNotCancelAudio() throws Exception {
506 NotificationRecord r = getBeepyNotification();
507
508 mService.buzzBeepBlinkLocked(r);
509 r.isUpdate = true;
510 mService.buzzBeepBlinkLocked(r);
511
512 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500513 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400514 }
515
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400516 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400517 public void testNoisyOnceUpdateDoesNotCancelAudio() throws Exception {
518 NotificationRecord r = getBeepyNotification();
519 NotificationRecord s = getBeepyOnceNotification();
520 s.isUpdate = true;
521
522 mService.buzzBeepBlinkLocked(r);
523 mService.buzzBeepBlinkLocked(s);
524
525 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500526 assertTrue(r.isInterruptive());
527 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400528 }
529
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400530 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400531 public void testQuietUpdateDoesNotCancelAudioFromOther() throws Exception {
532 NotificationRecord r = getBeepyNotification();
533 NotificationRecord s = getQuietNotification();
534 s.isUpdate = true;
535 NotificationRecord other = getNoisyOtherNotification();
536
537 // set up internal state
538 mService.buzzBeepBlinkLocked(r);
539 mService.buzzBeepBlinkLocked(other); // this takes the audio stream
540 Mockito.reset(mRingtonePlayer);
541
542 // should not stop noise, since we no longer own it
543 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
544 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500545 assertTrue(other.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400546 }
547
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400548 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400549 public void testQuietInterloperDoesNotCancelAudio() throws Exception {
550 NotificationRecord r = getBeepyNotification();
551 NotificationRecord other = getQuietOtherNotification();
552
553 // set up internal state
554 mService.buzzBeepBlinkLocked(r);
555 Mockito.reset(mRingtonePlayer);
556
557 // should not stop noise, since it does not own it
558 mService.buzzBeepBlinkLocked(other);
559 verifyNeverStopAudio();
560 }
561
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400562 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400563 public void testQuietUpdateCancelsAudio() throws Exception {
564 NotificationRecord r = getBeepyNotification();
565 NotificationRecord s = getQuietNotification();
566 s.isUpdate = true;
567
568 // set up internal state
569 mService.buzzBeepBlinkLocked(r);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500570 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400571 Mockito.reset(mRingtonePlayer);
572
573 // quiet update should stop making noise
574 mService.buzzBeepBlinkLocked(s);
575 verifyStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500576 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400577 }
578
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400579 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400580 public void testQuietOnceUpdateCancelsAudio() throws Exception {
581 NotificationRecord r = getBeepyNotification();
582 NotificationRecord s = getQuietOnceNotification();
583 s.isUpdate = true;
584
585 // set up internal state
586 mService.buzzBeepBlinkLocked(r);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500587 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400588 Mockito.reset(mRingtonePlayer);
589
590 // stop making noise - this is a weird corner case, but quiet should override once
591 mService.buzzBeepBlinkLocked(s);
592 verifyStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500593 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400594 }
595
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400596 @Test
Beverly5d463b62017-07-26 14:13:40 -0400597 public void testInCallNotification() throws Exception {
598 NotificationRecord r = getBeepyNotification();
599
600 // set up internal state
601 mService.buzzBeepBlinkLocked(r);
602 Mockito.reset(mRingtonePlayer);
603
604 mService.mInCall = true;
605 mService.buzzBeepBlinkLocked(r);
606
Julia Reynolds94187562017-10-10 13:58:49 -0400607 verify(mService, times(1)).playInCallNotification();
Beverly5d463b62017-07-26 14:13:40 -0400608 verifyNeverBeep(); // doesn't play normal beep
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500609 assertTrue(r.isInterruptive());
Beverly5d463b62017-07-26 14:13:40 -0400610 }
611
612 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500613 public void testNoDemoteSoundToVibrateIfVibrateGiven() throws Exception {
614 NotificationRecord r = getBuzzyBeepyNotification();
615 assertTrue(r.getSound() != null);
Chris Wren93bb8b82016-03-29 14:35:05 -0400616
617 // the phone is quiet
Chris Wren93bb8b82016-03-29 14:35:05 -0400618 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
Julia Reynolds85896572017-09-20 12:54:52 -0400619 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
Chris Wren93bb8b82016-03-29 14:35:05 -0400620
621 mService.buzzBeepBlinkLocked(r);
622
Michael Wright71216972017-01-31 18:33:54 +0000623 VibrationEffect effect = VibrationEffect.createWaveform(r.getVibration(), -1);
624
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700625 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
626 eq(effect), (AudioAttributes) anyObject());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500627 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400628 }
629
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400630 @Test
Julia Reynolds85896572017-09-20 12:54:52 -0400631 public void testNoDemoteSoundToVibrateIfNonNotificationStream() throws Exception {
632 NotificationRecord r = getBeepyNotification();
633 assertTrue(r.getSound() != null);
634 assertNull(r.getVibration());
635
636 // the phone is quiet
637 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
638 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(1);
639
640 mService.buzzBeepBlinkLocked(r);
641
642 verifyNeverVibrate();
643 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500644 assertTrue(r.isInterruptive());
Julia Reynolds85896572017-09-20 12:54:52 -0400645 }
646
647 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500648 public void testDemoteSoundToVibrate() throws Exception {
649 NotificationRecord r = getBeepyNotification();
650 assertTrue(r.getSound() != null);
651 assertNull(r.getVibration());
652
653 // the phone is quiet
654 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
Julia Reynolds85896572017-09-20 12:54:52 -0400655 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500656
657 mService.buzzBeepBlinkLocked(r);
658
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700659 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
660 eq(FALLBACK_VIBRATION), (AudioAttributes) anyObject());
Julia Reynolds619a69f2017-01-27 15:11:38 -0500661 verify(mRingtonePlayer, never()).playAsync
662 (anyObject(), anyObject(), anyBoolean(), anyObject());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500663 assertTrue(r.isInterruptive());
Julia Reynolds0c299d42016-11-15 14:37:04 -0500664 }
665
666 @Test
667 public void testDemoteInsistentSoundToVibrate() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400668 NotificationRecord r = getInsistentBeepyNotification();
Julia Reynolds0c299d42016-11-15 14:37:04 -0500669 assertTrue(r.getSound() != null);
670 assertNull(r.getVibration());
Chris Wren93bb8b82016-03-29 14:35:05 -0400671
672 // the phone is quiet
673 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
674 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
675
676 mService.buzzBeepBlinkLocked(r);
677
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700678 verifyDelayedVibrateLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500679 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400680 }
681
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400682 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400683 public void testVibrate() throws Exception {
684 NotificationRecord r = getBuzzyNotification();
685
686 mService.buzzBeepBlinkLocked(r);
687
688 verifyNeverBeep();
689 verifyVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500690 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400691 }
692
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400693 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500694 public void testInsistentVibrate() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400695 NotificationRecord r = getInsistentBuzzyNotification();
696
697 mService.buzzBeepBlinkLocked(r);
698 verifyVibrateLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500699 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400700 }
701
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400702 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500703 public void testVibrateTwice() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400704 NotificationRecord r = getBuzzyNotification();
705
706 // set up internal state
707 mService.buzzBeepBlinkLocked(r);
708 Mockito.reset(mVibrator);
709
710 // update should vibrate
711 r.isUpdate = true;
712 mService.buzzBeepBlinkLocked(r);
713 verifyVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500714 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400715 }
716
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400717 @Test
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400718 public void testGroupAlertSummarySilenceChild() throws Exception {
719 NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
720
721 mService.buzzBeepBlinkLocked(child);
722
723 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500724 assertFalse(child.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400725 }
726
727 @Test
728 public void testGroupAlertSummaryNoSilenceSummary() throws Exception {
729 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
730 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
731
732 mService.buzzBeepBlinkLocked(summary);
733
734 verifyBeepLooped();
Julia Reynolds54369232018-07-03 10:43:35 -0400735 // summaries are never interruptive for notification counts
736 assertFalse(summary.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400737 }
738
739 @Test
740 public void testGroupAlertSummaryNoSilenceNonGroupChild() throws Exception {
741 NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_SUMMARY);
742
743 mService.buzzBeepBlinkLocked(nonGroup);
744
745 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500746 assertTrue(nonGroup.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400747 }
748
749 @Test
750 public void testGroupAlertChildSilenceSummary() throws Exception {
751 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
752 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
753
754 mService.buzzBeepBlinkLocked(summary);
755
756 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500757 assertFalse(summary.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400758 }
759
760 @Test
761 public void testGroupAlertChildNoSilenceChild() throws Exception {
762 NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
763
764 mService.buzzBeepBlinkLocked(child);
765
766 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500767 assertTrue(child.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400768 }
769
770 @Test
771 public void testGroupAlertChildNoSilenceNonGroupSummary() throws Exception {
772 NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_CHILDREN);
773
774 mService.buzzBeepBlinkLocked(nonGroup);
775
776 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500777 assertTrue(nonGroup.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400778 }
779
780 @Test
781 public void testGroupAlertAllNoSilenceGroup() throws Exception {
782 NotificationRecord group = getBeepyNotificationRecord("a", GROUP_ALERT_ALL);
783
784 mService.buzzBeepBlinkLocked(group);
785
786 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500787 assertTrue(group.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400788 }
789
790 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400791 public void testHonorAlertOnlyOnceForBuzz() throws Exception {
792 NotificationRecord r = getBuzzyNotification();
793 NotificationRecord s = getBuzzyOnceNotification();
794 s.isUpdate = true;
795
796 // set up internal state
797 mService.buzzBeepBlinkLocked(r);
798 Mockito.reset(mVibrator);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500799 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400800
801 // update should not beep
802 mService.buzzBeepBlinkLocked(s);
803 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500804 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400805 }
806
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400807 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400808 public void testNoisyUpdateDoesNotCancelVibrate() throws Exception {
809 NotificationRecord r = getBuzzyNotification();
810
811 mService.buzzBeepBlinkLocked(r);
812 r.isUpdate = true;
813 mService.buzzBeepBlinkLocked(r);
814
815 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500816 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400817 }
818
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400819 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400820 public void testNoisyOnceUpdateDoesNotCancelVibrate() throws Exception {
821 NotificationRecord r = getBuzzyNotification();
822 NotificationRecord s = getBuzzyOnceNotification();
823 s.isUpdate = true;
824
825 mService.buzzBeepBlinkLocked(r);
826 mService.buzzBeepBlinkLocked(s);
827
828 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500829 assertTrue(r.isInterruptive());
830 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400831 }
832
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400833 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400834 public void testQuietUpdateDoesNotCancelVibrateFromOther() throws Exception {
835 NotificationRecord r = getBuzzyNotification();
836 NotificationRecord s = getQuietNotification();
837 s.isUpdate = true;
838 NotificationRecord other = getNoisyOtherNotification();
839
840 // set up internal state
841 mService.buzzBeepBlinkLocked(r);
842 mService.buzzBeepBlinkLocked(other); // this takes the vibrate stream
843 Mockito.reset(mVibrator);
844
845 // should not stop vibrate, since we no longer own it
846 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
847 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500848 assertTrue(r.isInterruptive());
849 assertTrue(other.isInterruptive());
850 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400851 }
852
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400853 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400854 public void testQuietInterloperDoesNotCancelVibrate() throws Exception {
855 NotificationRecord r = getBuzzyNotification();
856 NotificationRecord other = getQuietOtherNotification();
857
858 // set up internal state
859 mService.buzzBeepBlinkLocked(r);
860 Mockito.reset(mVibrator);
861
862 // should not stop noise, since it does not own it
863 mService.buzzBeepBlinkLocked(other);
864 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500865 assertFalse(other.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400866 }
867
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400868 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500869 public void testQuietUpdateCancelsVibrate() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400870 NotificationRecord r = getBuzzyNotification();
871 NotificationRecord s = getQuietNotification();
872 s.isUpdate = true;
873
874 // set up internal state
875 mService.buzzBeepBlinkLocked(r);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500876 verifyVibrate();
Chris Wren93bb8b82016-03-29 14:35:05 -0400877
878 // quiet update should stop making noise
879 mService.buzzBeepBlinkLocked(s);
880 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500881 assertTrue(r.isInterruptive());
882 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400883 }
884
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400885 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500886 public void testQuietOnceUpdateCancelVibrate() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400887 NotificationRecord r = getBuzzyNotification();
888 NotificationRecord s = getQuietOnceNotification();
889 s.isUpdate = true;
890
891 // set up internal state
892 mService.buzzBeepBlinkLocked(r);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500893 verifyVibrate();
Chris Wren93bb8b82016-03-29 14:35:05 -0400894
895 // stop making noise - this is a weird corner case, but quiet should override once
896 mService.buzzBeepBlinkLocked(s);
897 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500898 assertTrue(r.isInterruptive());
899 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400900 }
901
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400902 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400903 public void testQuietUpdateCancelsDemotedVibrate() throws Exception {
904 NotificationRecord r = getBeepyNotification();
905 NotificationRecord s = getQuietNotification();
906
907 // the phone is quiet
908 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
909 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
910
911 mService.buzzBeepBlinkLocked(r);
912
913 // quiet update should stop making noise
914 mService.buzzBeepBlinkLocked(s);
915 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500916 assertTrue(r.isInterruptive());
917 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400918 }
Michael Wright71216972017-01-31 18:33:54 +0000919
Julia Reynoldsca80d162017-04-23 12:39:32 -0400920 @Test
921 public void testEmptyUriSoundTreatedAsNoSound() throws Exception {
922 NotificationChannel channel = new NotificationChannel("test", "test", IMPORTANCE_HIGH);
923 channel.setSound(Uri.EMPTY, null);
924 final Notification n = new Builder(getContext(), "test")
925 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
926
927 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
928 mPid, n, mUser, null, System.currentTimeMillis());
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000929 NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
Julia Reynoldsca80d162017-04-23 12:39:32 -0400930 mService.addNotification(r);
931
932 mService.buzzBeepBlinkLocked(r);
Julia Reynoldsca80d162017-04-23 12:39:32 -0400933 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500934 assertFalse(r.isInterruptive());
Julia Reynoldsca80d162017-04-23 12:39:32 -0400935 }
936
Julia Reynolds76c096d2017-06-19 08:16:04 -0400937 @Test
938 public void testRepeatedSoundOverLimitMuted() throws Exception {
939 when(mUsageStats.isAlertRateLimited(any())).thenReturn(true);
940
941 NotificationRecord r = getBeepyNotification();
942
943 mService.buzzBeepBlinkLocked(r);
944 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500945 assertFalse(r.isInterruptive());
Julia Reynolds76c096d2017-06-19 08:16:04 -0400946 }
947
948 @Test
949 public void testPostingSilentNotificationDoesNotAffectRateLimiting() throws Exception {
950 NotificationRecord r = getQuietNotification();
951 mService.buzzBeepBlinkLocked(r);
952
953 verify(mUsageStats, never()).isAlertRateLimited(any());
954 }
955
956 @Test
Julia Reynolds65b85cf2017-07-20 09:19:20 -0400957 public void testPostingGroupSuppressedDoesNotAffectRateLimiting() throws Exception {
958 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
959 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
960
961 mService.buzzBeepBlinkLocked(summary);
Julia Reynolds65b85cf2017-07-20 09:19:20 -0400962 verify(mUsageStats, never()).isAlertRateLimited(any());
963 }
964
965 @Test
Julia Reynolds79dfdd62018-04-17 15:36:33 -0400966 public void testGroupSuppressionFailureDoesNotAffectRateLimiting() {
967 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
968 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
969
970 mService.buzzBeepBlinkLocked(summary);
971 verify(mUsageStats, times(1)).isAlertRateLimited(any());
972 }
973
974 @Test
Julia Reynolds76c096d2017-06-19 08:16:04 -0400975 public void testCrossUserSoundMuted() throws Exception {
976 final Notification n = new Builder(getContext(), "test")
977 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
978
979 int userId = mUser.getIdentifier() + 1;
980 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
981 mPid, n, UserHandle.of(userId), null, System.currentTimeMillis());
982 NotificationRecord r = new NotificationRecord(getContext(), sbn,
983 new NotificationChannel("test", "test", IMPORTANCE_HIGH));
984
985 mService.buzzBeepBlinkLocked(r);
986 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500987 assertFalse(r.isInterruptive());
Julia Reynolds76c096d2017-06-19 08:16:04 -0400988 }
989
Julia Reynolds94187562017-10-10 13:58:49 -0400990 @Test
991 public void testA11yMinInitialPost() throws Exception {
992 NotificationRecord r = getQuietNotification();
993 r.setImportance(IMPORTANCE_MIN, "");
994 mService.buzzBeepBlinkLocked(r);
995 verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt());
996 }
997
998 @Test
999 public void testA11yQuietInitialPost() throws Exception {
1000 NotificationRecord r = getQuietNotification();
1001 mService.buzzBeepBlinkLocked(r);
1002 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
1003 }
1004
1005 @Test
1006 public void testA11yQuietUpdate() throws Exception {
1007 NotificationRecord r = getQuietNotification();
1008 mService.buzzBeepBlinkLocked(r);
1009 r.isUpdate = true;
1010 mService.buzzBeepBlinkLocked(r);
1011 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
1012 }
1013
Julia Reynolds54369232018-07-03 10:43:35 -04001014 @Test
1015 public void testLightsScreenOn() {
1016 mService.mScreenOn = true;
1017 NotificationRecord r = getLightsNotification();
1018 mService.buzzBeepBlinkLocked(r);
1019 verifyNeverLights();
1020 assertFalse(r.isInterruptive());
1021 }
1022
1023 @Test
1024 public void testLightsInCall() {
1025 mService.mInCall = true;
1026 NotificationRecord r = getLightsNotification();
1027 mService.buzzBeepBlinkLocked(r);
1028 verifyNeverLights();
1029 assertFalse(r.isInterruptive());
1030 }
1031
1032 @Test
1033 public void testLightsSilentUpdate() {
1034 NotificationRecord r = getLightsOnceNotification();
1035 mService.buzzBeepBlinkLocked(r);
1036 verifyLights();
1037 assertTrue(r.isInterruptive());
1038
1039 r = getLightsOnceNotification();
1040 r.isUpdate = true;
1041 mService.buzzBeepBlinkLocked(r);
1042 // checks that lights happened once, i.e. this new call didn't trigger them again
1043 verifyLights();
1044 assertFalse(r.isInterruptive());
1045 }
1046
1047 @Test
1048 public void testLightsUnimportant() {
1049 NotificationRecord r = getLightsNotification();
1050 r.setImportance(IMPORTANCE_LOW, "testing");
1051 mService.buzzBeepBlinkLocked(r);
1052 verifyNeverLights();
1053 assertFalse(r.isInterruptive());
1054 }
1055
1056 @Test
1057 public void testLightsNoLights() {
1058 NotificationRecord r = getQuietNotification();
1059 mService.buzzBeepBlinkLocked(r);
1060 verifyNeverLights();
1061 assertFalse(r.isInterruptive());
1062 }
1063
1064 @Test
1065 public void testLightsNoLightOnDevice() {
1066 mService.mHasLight = false;
1067 NotificationRecord r = getLightsNotification();
1068 mService.buzzBeepBlinkLocked(r);
1069 verifyNeverLights();
1070 assertFalse(r.isInterruptive());
1071 }
1072
1073 @Test
1074 public void testLightsLightsOffGlobally() {
1075 mService.mNotificationPulseEnabled = false;
1076 NotificationRecord r = getLightsNotification();
1077 mService.buzzBeepBlinkLocked(r);
1078 verifyNeverLights();
1079 assertFalse(r.isInterruptive());
1080 }
1081
1082 @Test
1083 public void testLightsDndIntercepted() {
1084 NotificationRecord r = getLightsNotification();
1085 r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS);
1086 mService.buzzBeepBlinkLocked(r);
1087 verifyNeverLights();
1088 assertFalse(r.isInterruptive());
1089 }
1090
1091 @Test
1092 public void testGroupAlertSummaryNoLightsChild() {
1093 NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
1094
1095 mService.buzzBeepBlinkLocked(child);
1096
1097 verifyNeverLights();
1098 assertFalse(child.isInterruptive());
1099 }
1100
1101 @Test
1102 public void testGroupAlertSummaryLightsSummary() {
1103 NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
1104 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
1105
1106 mService.buzzBeepBlinkLocked(summary);
1107
1108 verifyLights();
1109 // summaries should never count for interruptiveness counts
1110 assertFalse(summary.isInterruptive());
1111 }
1112
1113 @Test
1114 public void testGroupAlertSummaryLightsNonGroupChild() {
1115 NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_SUMMARY);
1116
1117 mService.buzzBeepBlinkLocked(nonGroup);
1118
1119 verifyLights();
1120 assertTrue(nonGroup.isInterruptive());
1121 }
1122
1123 @Test
1124 public void testGroupAlertChildNoLightsSummary() {
1125 NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
1126 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
1127
1128 mService.buzzBeepBlinkLocked(summary);
1129
1130 verifyNeverLights();
1131 assertFalse(summary.isInterruptive());
1132 }
1133
1134 @Test
1135 public void testGroupAlertChildLightsChild() {
1136 NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
1137
1138 mService.buzzBeepBlinkLocked(child);
1139
1140 verifyLights();
1141 assertTrue(child.isInterruptive());
1142 }
1143
1144 @Test
1145 public void testGroupAlertChildLightsNonGroupSummary() {
1146 NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_CHILDREN);
1147
1148 mService.buzzBeepBlinkLocked(nonGroup);
1149
1150 verifyLights();
1151 assertTrue(nonGroup.isInterruptive());
1152 }
1153
1154 @Test
1155 public void testGroupAlertAllLightsGroup() {
1156 NotificationRecord group = getLightsNotificationRecord("a", GROUP_ALERT_ALL);
1157
1158 mService.buzzBeepBlinkLocked(group);
1159
1160 verifyLights();
1161 assertTrue(group.isInterruptive());
1162 }
1163
Michael Wright71216972017-01-31 18:33:54 +00001164 static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
1165 private final int mRepeatIndex;
1166
1167 VibrateRepeatMatcher(int repeatIndex) {
1168 mRepeatIndex = repeatIndex;
1169 }
1170
1171 @Override
1172 public boolean matches(VibrationEffect actual) {
1173 if (actual instanceof VibrationEffect.Waveform &&
1174 ((VibrationEffect.Waveform) actual).getRepeatIndex() == mRepeatIndex) {
1175 return true;
1176 }
1177 // All non-waveform effects are essentially one shots.
1178 return mRepeatIndex == -1;
1179 }
1180
1181 @Override
1182 public String toString() {
1183 return "repeatIndex=" + mRepeatIndex;
1184 }
1185 }
Chris Wren93bb8b82016-03-29 14:35:05 -04001186}