blob: b6af5504f75175510132be02d29b99dfc57d66ea [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;
Julia Reynolds9aee2842019-01-03 14:35:38 -050061import android.service.notification.NotificationListenerService;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070062import android.service.notification.StatusBarNotification;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070063import 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
Brett Chabot8091d9e2019-02-26 14:52:33 -080069import androidx.test.runner.AndroidJUnit4;
70
Julia Reynolds94187562017-10-10 13:58:49 -040071import com.android.internal.util.IntPair;
Jason Monk74f5e362017-12-06 08:56:33 -050072import com.android.server.UiServiceTestCase;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070073import com.android.server.lights.Light;
74
75import org.junit.Before;
76import org.junit.Test;
77import org.junit.runner.RunWith;
78import org.mockito.ArgumentMatcher;
79import org.mockito.Mock;
80import org.mockito.Mockito;
81import org.mockito.MockitoAnnotations;
82
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -040083@SmallTest
84@RunWith(AndroidJUnit4.class)
Jason Monk74f5e362017-12-06 08:56:33 -050085public class BuzzBeepBlinkTest extends UiServiceTestCase {
Chris Wren93bb8b82016-03-29 14:35:05 -040086
87 @Mock AudioManager mAudioManager;
88 @Mock Vibrator mVibrator;
89 @Mock android.media.IRingtonePlayer mRingtonePlayer;
Julia Reynoldsb5e44b72016-08-16 15:00:25 -040090 @Mock Light mLight;
Julia Reynoldseb3dca72017-07-11 10:39:58 -040091 @Mock
92 NotificationManagerService.WorkerHandler mHandler;
Julia Reynolds76c096d2017-06-19 08:16:04 -040093 @Mock
94 NotificationUsageStats mUsageStats;
Julia Reynolds94187562017-10-10 13:58:49 -040095 @Mock
96 IAccessibilityManager mAccessibilityService;
Chris Wren93bb8b82016-03-29 14:35:05 -040097
98 private NotificationManagerService mService;
99 private String mPkg = "com.android.server.notification";
100 private int mId = 1001;
101 private int mOtherId = 1002;
102 private String mTag = null;
103 private int mUid = 1000;
104 private int mPid = 2000;
Chris Wren93bb8b82016-03-29 14:35:05 -0400105 private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
106
Michael Wright71216972017-01-31 18:33:54 +0000107 private VibrateRepeatMatcher mVibrateOnceMatcher = new VibrateRepeatMatcher(-1);
108 private VibrateRepeatMatcher mVibrateLoopMatcher = new VibrateRepeatMatcher(0);
109
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400110 private static final long[] CUSTOM_VIBRATION = new long[] {
111 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
112 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
113 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 };
114 private static final Uri CUSTOM_SOUND = Settings.System.DEFAULT_ALARM_ALERT_URI;
Julia Reynolds619a69f2017-01-27 15:11:38 -0500115 private static final AudioAttributes CUSTOM_ATTRIBUTES = new AudioAttributes.Builder()
116 .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
Julia Reynolds9aee2842019-01-03 14:35:38 -0500117 .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
Julia Reynolds619a69f2017-01-27 15:11:38 -0500118 .build();
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400119 private static final int CUSTOM_LIGHT_COLOR = Color.BLACK;
120 private static final int CUSTOM_LIGHT_ON = 10000;
121 private static final int CUSTOM_LIGHT_OFF = 10000;
Michael Wright71216972017-01-31 18:33:54 +0000122 private static final long[] FALLBACK_VIBRATION_PATTERN = new long[] {100, 100, 100};
123 private static final VibrationEffect FALLBACK_VIBRATION =
124 VibrationEffect.createWaveform(FALLBACK_VIBRATION_PATTERN, -1);
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700125 private static final int MAX_VIBRATION_DELAY = 1000;
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400126
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400127 @Before
Julia Reynolds94187562017-10-10 13:58:49 -0400128 public void setUp() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400129 MockitoAnnotations.initMocks(this);
130
131 when(mAudioManager.isAudioFocusExclusive()).thenReturn(false);
132 when(mAudioManager.getRingtonePlayer()).thenReturn(mRingtonePlayer);
133 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
134 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynolds76c096d2017-06-19 08:16:04 -0400135 when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
136
Julia Reynolds94187562017-10-10 13:58:49 -0400137 long serviceReturnValue = IntPair.of(
138 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED,
139 AccessibilityEvent.TYPES_ALL_MASK);
140 when(mAccessibilityService.addClient(any(), anyInt())).thenReturn(serviceReturnValue);
141 AccessibilityManager accessibilityManager =
142 new AccessibilityManager(Handler.getMain(), mAccessibilityService, 0);
143 verify(mAccessibilityService).addClient(any(IAccessibilityManagerClient.class), anyInt());
144 assertTrue(accessibilityManager.isEnabled());
145
146 mService = spy(new NotificationManagerService(getContext()));
Chris Wren93bb8b82016-03-29 14:35:05 -0400147 mService.setAudioManager(mAudioManager);
148 mService.setVibrator(mVibrator);
149 mService.setSystemReady(true);
150 mService.setHandler(mHandler);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400151 mService.setLights(mLight);
152 mService.setScreenOn(false);
Michael Wright71216972017-01-31 18:33:54 +0000153 mService.setFallbackVibrationPattern(FALLBACK_VIBRATION_PATTERN);
Julia Reynolds76c096d2017-06-19 08:16:04 -0400154 mService.setUsageStats(mUsageStats);
Julia Reynolds94187562017-10-10 13:58:49 -0400155 mService.setAccessibilityManager(accessibilityManager);
Julia Reynolds54369232018-07-03 10:43:35 -0400156 mService.mScreenOn = false;
157 mService.mInCall = false;
158 mService.mNotificationPulseEnabled = true;
Chris Wren93bb8b82016-03-29 14:35:05 -0400159 }
160
161 //
162 // Convenience functions for creating notification records
163 //
164
165 private NotificationRecord getNoisyOtherNotification() {
166 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400167 true /* noisy */, true /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400168 }
169
170 private NotificationRecord getBeepyNotification() {
171 return getNotificationRecord(mId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400172 true /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400173 }
174
175 private NotificationRecord getBeepyOnceNotification() {
176 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400177 true /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400178 }
179
180 private NotificationRecord getQuietNotification() {
181 return getNotificationRecord(mId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400182 false /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400183 }
184
185 private NotificationRecord getQuietOtherNotification() {
186 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400187 false /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400188 }
189
190 private NotificationRecord getQuietOnceNotification() {
191 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400192 false /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400193 }
194
195 private NotificationRecord getInsistentBeepyNotification() {
196 return getNotificationRecord(mId, true /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400197 true /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400198 }
199
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700200 private NotificationRecord getInsistentBeepyLeanbackNotification() {
201 return getLeanbackNotificationRecord(mId, true /* insistent */, false /* once */,
202 true /* noisy */, false /* buzzy*/, false /* lights */);
203 }
204
Chris Wren93bb8b82016-03-29 14:35:05 -0400205 private NotificationRecord getBuzzyNotification() {
206 return getNotificationRecord(mId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400207 false /* noisy */, true /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400208 }
209
210 private NotificationRecord getBuzzyOnceNotification() {
211 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400212 false /* noisy */, true /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400213 }
214
215 private NotificationRecord getInsistentBuzzyNotification() {
216 return getNotificationRecord(mId, true /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400217 false /* noisy */, true /* buzzy*/, false /* lights */);
218 }
219
Julia Reynolds0c299d42016-11-15 14:37:04 -0500220 private NotificationRecord getBuzzyBeepyNotification() {
221 return getNotificationRecord(mId, false /* insistent */, false /* once */,
222 true /* noisy */, true /* buzzy*/, false /* lights */);
223 }
224
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400225 private NotificationRecord getLightsNotification() {
Julia Reynolds54369232018-07-03 10:43:35 -0400226 return getNotificationRecord(mId, false /* insistent */, false /* once */,
227 false /* noisy */, false /* buzzy*/, true /* lights */);
228 }
229
230 private NotificationRecord getLightsOnceNotification() {
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400231 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynolds54369232018-07-03 10:43:35 -0400232 false /* noisy */, false /* buzzy*/, true /* lights */);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400233 }
234
Julia Reynolds9aee2842019-01-03 14:35:38 -0500235 private NotificationRecord getCallRecord(int id, boolean insistent) {
236 return getNotificationRecord(id, false, false /* once */, true /* noisy */,
237 false /* buzzy */, false /* lights */, false /* default vib */,
238 false /* default sound */, false /* default lights */, "",
239 Notification.GROUP_ALERT_ALL, false);
Chris Wren93bb8b82016-03-29 14:35:05 -0400240 }
241
242 private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400243 boolean noisy, boolean buzzy, boolean lights) {
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400244 return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, true,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700245 null, Notification.GROUP_ALERT_ALL, false);
246 }
247
248 private NotificationRecord getLeanbackNotificationRecord(int id, boolean insistent, boolean once,
249 boolean noisy, boolean buzzy, boolean lights) {
250 return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, true,
251 null, Notification.GROUP_ALERT_ALL, true);
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400252 }
253
254 private NotificationRecord getBeepyNotificationRecord(String groupKey, int groupAlertBehavior) {
255 return getNotificationRecord(mId, false, false, true, false, false, true, true, true,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700256 groupKey, groupAlertBehavior, false);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400257 }
258
Julia Reynolds54369232018-07-03 10:43:35 -0400259 private NotificationRecord getLightsNotificationRecord(String groupKey,
260 int groupAlertBehavior) {
261 return getNotificationRecord(mId, false, false, false, false, true /*lights*/, true, true,
262 true, groupKey, groupAlertBehavior, false);
263 }
264
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400265 private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
266 boolean noisy, boolean buzzy, boolean lights, boolean defaultVibration,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700267 boolean defaultSound, boolean defaultLights, String groupKey, int groupAlertBehavior,
268 boolean isLeanback) {
Julia Reynolds0c299d42016-11-15 14:37:04 -0500269 NotificationChannel channel =
Julia Reynoldsca80d162017-04-23 12:39:32 -0400270 new NotificationChannel("test", "test", IMPORTANCE_HIGH);
Chris Wren93bb8b82016-03-29 14:35:05 -0400271 final Builder builder = new Builder(getContext())
272 .setContentTitle("foo")
273 .setSmallIcon(android.R.drawable.sym_def_app_icon)
274 .setPriority(Notification.PRIORITY_HIGH)
275 .setOnlyAlertOnce(once);
276
277 int defaults = 0;
278 if (noisy) {
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400279 if (defaultSound) {
280 defaults |= Notification.DEFAULT_SOUND;
Julia Reynolds619a69f2017-01-27 15:11:38 -0500281 channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
282 Notification.AUDIO_ATTRIBUTES_DEFAULT);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400283 } else {
284 builder.setSound(CUSTOM_SOUND);
Julia Reynolds619a69f2017-01-27 15:11:38 -0500285 channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400286 }
Julia Reynolds184b86d2017-04-12 13:27:58 -0400287 } else {
288 channel.setSound(null, null);
Chris Wren93bb8b82016-03-29 14:35:05 -0400289 }
290 if (buzzy) {
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400291 if (defaultVibration) {
292 defaults |= Notification.DEFAULT_VIBRATE;
293 } else {
294 builder.setVibrate(CUSTOM_VIBRATION);
Julia Reynoldsf57de462016-11-23 11:31:46 -0500295 channel.setVibrationPattern(CUSTOM_VIBRATION);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400296 }
Julia Reynoldsf57de462016-11-23 11:31:46 -0500297 channel.enableVibration(true);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400298 }
299 if (lights) {
300 if (defaultLights) {
301 defaults |= Notification.DEFAULT_LIGHTS;
302 } else {
303 builder.setLights(CUSTOM_LIGHT_COLOR, CUSTOM_LIGHT_ON, CUSTOM_LIGHT_OFF);
304 }
Julia Reynolds529e3322017-02-06 08:33:01 -0500305 channel.enableLights(true);
Chris Wren93bb8b82016-03-29 14:35:05 -0400306 }
307 builder.setDefaults(defaults);
308
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400309 builder.setGroup(groupKey);
310 builder.setGroupAlertBehavior(groupAlertBehavior);
311
Chris Wren93bb8b82016-03-29 14:35:05 -0400312 Notification n = builder.build();
313 if (insistent) {
314 n.flags |= Notification.FLAG_INSISTENT;
315 }
Julia Reynolds0c299d42016-11-15 14:37:04 -0500316
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700317 Context context = spy(getContext());
318 PackageManager packageManager = spy(context.getPackageManager());
319 when(context.getPackageManager()).thenReturn(packageManager);
320 when(packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
321 .thenReturn(isLeanback);
322
Julia Reynolds924eed12017-01-19 09:52:07 -0500323 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid,
Julia Reynolds423b9fc2016-11-09 09:51:08 -0500324 mPid, n, mUser, null, System.currentTimeMillis());
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700325 NotificationRecord r = new NotificationRecord(context, sbn, channel);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400326 mService.addNotification(r);
327 return r;
Chris Wren93bb8b82016-03-29 14:35:05 -0400328 }
329
330 //
331 // Convenience functions for interacting with mocks
332 //
333
334 private void verifyNeverBeep() throws RemoteException {
335 verify(mRingtonePlayer, never()).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
336 anyBoolean(), (AudioAttributes) anyObject());
337 }
338
339 private void verifyBeep() throws RemoteException {
340 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
341 eq(true), (AudioAttributes) anyObject());
342 }
343
344 private void verifyBeepLooped() throws RemoteException {
345 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
346 eq(false), (AudioAttributes) anyObject());
347 }
348
349 private void verifyNeverStopAudio() throws RemoteException {
350 verify(mRingtonePlayer, never()).stopAsync();
351 }
352
353 private void verifyStopAudio() throws RemoteException {
354 verify(mRingtonePlayer, times(1)).stopAsync();
355 }
356
357 private void verifyNeverVibrate() {
Michael Wright71216972017-01-31 18:33:54 +0000358 verify(mVibrator, never()).vibrate(anyInt(), anyString(), (VibrationEffect) anyObject(),
359 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400360 }
361
362 private void verifyVibrate() {
Michael Wright71216972017-01-31 18:33:54 +0000363 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateOnceMatcher),
364 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400365 }
366
367 private void verifyVibrateLooped() {
Michael Wright71216972017-01-31 18:33:54 +0000368 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateLoopMatcher),
369 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400370 }
371
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700372 private void verifyDelayedVibrateLooped() {
373 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
374 argThat(mVibrateLoopMatcher), (AudioAttributes) anyObject());
375 }
376
Chris Wren93bb8b82016-03-29 14:35:05 -0400377 private void verifyStopVibrate() {
378 verify(mVibrator, times(1)).cancel();
379 }
380
381 private void verifyNeverStopVibrate() throws RemoteException {
382 verify(mVibrator, never()).cancel();
383 }
384
Julia Reynolds54369232018-07-03 10:43:35 -0400385 private void verifyNeverLights() {
386 verify(mLight, never()).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
387 }
388
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400389 private void verifyLights() {
Julia Reynolds033a4122017-01-31 16:50:38 -0500390 verify(mLight, times(1)).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400391 }
392
393 private void verifyCustomLights() {
Julia Reynolds033a4122017-01-31 16:50:38 -0500394 verify(mLight, times(1)).setFlashing(
395 eq(CUSTOM_LIGHT_COLOR), anyInt(), eq(CUSTOM_LIGHT_ON), eq(CUSTOM_LIGHT_OFF));
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400396 }
397
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400398 //
399 // Tests
400 //
401
402 @Test
403 public void testLights() throws Exception {
404 NotificationRecord r = getLightsNotification();
405 r.setImportance(NotificationManager.IMPORTANCE_DEFAULT, "for testing");
406
407 mService.buzzBeepBlinkLocked(r);
408
409 verifyLights();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500410 assertTrue(r.isInterruptive());
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400411 }
412
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400413 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400414 public void testBeep() throws Exception {
415 NotificationRecord r = getBeepyNotification();
416
417 mService.buzzBeepBlinkLocked(r);
418
419 verifyBeepLooped();
420 verifyNeverVibrate();
Julia Reynolds94187562017-10-10 13:58:49 -0400421 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500422 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400423 }
424
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400425 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400426 public void testBeepInsistently() throws Exception {
427 NotificationRecord r = getInsistentBeepyNotification();
428
429 mService.buzzBeepBlinkLocked(r);
430
431 verifyBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500432 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400433 }
434
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400435 @Test
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700436 public void testNoLeanbackBeep() throws Exception {
437 NotificationRecord r = getInsistentBeepyLeanbackNotification();
438
439 mService.buzzBeepBlinkLocked(r);
440
441 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500442 assertFalse(r.isInterruptive());
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700443 }
444
445 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400446 public void testNoInterruptionForMin() throws Exception {
447 NotificationRecord r = getBeepyNotification();
Julia Reynolds85769912016-10-25 09:08:57 -0400448 r.setImportance(NotificationManager.IMPORTANCE_MIN, "foo");
Chris Wren93bb8b82016-03-29 14:35:05 -0400449
450 mService.buzzBeepBlinkLocked(r);
451
452 verifyNeverBeep();
453 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500454 assertFalse(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400455 }
456
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400457 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400458 public void testNoInterruptionForIntercepted() throws Exception {
459 NotificationRecord r = getBeepyNotification();
460 r.setIntercepted(true);
461
462 mService.buzzBeepBlinkLocked(r);
463
464 verifyNeverBeep();
465 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500466 assertFalse(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400467 }
468
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400469 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400470 public void testBeepTwice() throws Exception {
471 NotificationRecord r = getBeepyNotification();
472
473 // set up internal state
474 mService.buzzBeepBlinkLocked(r);
475 Mockito.reset(mRingtonePlayer);
476
477 // update should beep
478 r.isUpdate = true;
479 mService.buzzBeepBlinkLocked(r);
480 verifyBeepLooped();
Julia Reynolds94187562017-10-10 13:58:49 -0400481 verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500482 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400483 }
484
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400485 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400486 public void testHonorAlertOnlyOnceForBeep() throws Exception {
487 NotificationRecord r = getBeepyNotification();
488 NotificationRecord s = getBeepyOnceNotification();
489 s.isUpdate = true;
490
491 // set up internal state
492 mService.buzzBeepBlinkLocked(r);
493 Mockito.reset(mRingtonePlayer);
494
495 // update should not beep
496 mService.buzzBeepBlinkLocked(s);
497 verifyNeverBeep();
Julia Reynolds94187562017-10-10 13:58:49 -0400498 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
Chris Wren93bb8b82016-03-29 14:35:05 -0400499 }
500
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400501 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400502 public void testNoisyUpdateDoesNotCancelAudio() throws Exception {
503 NotificationRecord r = getBeepyNotification();
504
505 mService.buzzBeepBlinkLocked(r);
506 r.isUpdate = true;
507 mService.buzzBeepBlinkLocked(r);
508
509 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500510 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400511 }
512
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400513 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400514 public void testNoisyOnceUpdateDoesNotCancelAudio() throws Exception {
515 NotificationRecord r = getBeepyNotification();
516 NotificationRecord s = getBeepyOnceNotification();
517 s.isUpdate = true;
518
519 mService.buzzBeepBlinkLocked(r);
520 mService.buzzBeepBlinkLocked(s);
521
522 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500523 assertTrue(r.isInterruptive());
524 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400525 }
526
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400527 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400528 public void testQuietUpdateDoesNotCancelAudioFromOther() throws Exception {
529 NotificationRecord r = getBeepyNotification();
530 NotificationRecord s = getQuietNotification();
531 s.isUpdate = true;
532 NotificationRecord other = getNoisyOtherNotification();
533
534 // set up internal state
535 mService.buzzBeepBlinkLocked(r);
536 mService.buzzBeepBlinkLocked(other); // this takes the audio stream
537 Mockito.reset(mRingtonePlayer);
538
539 // should not stop noise, since we no longer own it
540 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
541 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500542 assertTrue(other.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400543 }
544
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400545 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400546 public void testQuietInterloperDoesNotCancelAudio() throws Exception {
547 NotificationRecord r = getBeepyNotification();
548 NotificationRecord other = getQuietOtherNotification();
549
550 // set up internal state
551 mService.buzzBeepBlinkLocked(r);
552 Mockito.reset(mRingtonePlayer);
553
554 // should not stop noise, since it does not own it
555 mService.buzzBeepBlinkLocked(other);
556 verifyNeverStopAudio();
557 }
558
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400559 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400560 public void testQuietUpdateCancelsAudio() throws Exception {
561 NotificationRecord r = getBeepyNotification();
562 NotificationRecord s = getQuietNotification();
563 s.isUpdate = true;
564
565 // set up internal state
566 mService.buzzBeepBlinkLocked(r);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500567 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400568 Mockito.reset(mRingtonePlayer);
569
570 // quiet update should stop making noise
571 mService.buzzBeepBlinkLocked(s);
572 verifyStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500573 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400574 }
575
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400576 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400577 public void testQuietOnceUpdateCancelsAudio() throws Exception {
578 NotificationRecord r = getBeepyNotification();
579 NotificationRecord s = getQuietOnceNotification();
580 s.isUpdate = true;
581
582 // set up internal state
583 mService.buzzBeepBlinkLocked(r);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500584 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400585 Mockito.reset(mRingtonePlayer);
586
587 // stop making noise - this is a weird corner case, but quiet should override once
588 mService.buzzBeepBlinkLocked(s);
589 verifyStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500590 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400591 }
592
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400593 @Test
Beverly5d463b62017-07-26 14:13:40 -0400594 public void testInCallNotification() throws Exception {
595 NotificationRecord r = getBeepyNotification();
596
597 // set up internal state
598 mService.buzzBeepBlinkLocked(r);
599 Mockito.reset(mRingtonePlayer);
600
601 mService.mInCall = true;
602 mService.buzzBeepBlinkLocked(r);
603
Julia Reynolds94187562017-10-10 13:58:49 -0400604 verify(mService, times(1)).playInCallNotification();
Beverly5d463b62017-07-26 14:13:40 -0400605 verifyNeverBeep(); // doesn't play normal beep
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500606 assertTrue(r.isInterruptive());
Beverly5d463b62017-07-26 14:13:40 -0400607 }
608
609 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500610 public void testNoDemoteSoundToVibrateIfVibrateGiven() throws Exception {
611 NotificationRecord r = getBuzzyBeepyNotification();
612 assertTrue(r.getSound() != null);
Chris Wren93bb8b82016-03-29 14:35:05 -0400613
614 // the phone is quiet
Chris Wren93bb8b82016-03-29 14:35:05 -0400615 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
Julia Reynolds85896572017-09-20 12:54:52 -0400616 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
Chris Wren93bb8b82016-03-29 14:35:05 -0400617
618 mService.buzzBeepBlinkLocked(r);
619
Michael Wright71216972017-01-31 18:33:54 +0000620 VibrationEffect effect = VibrationEffect.createWaveform(r.getVibration(), -1);
621
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700622 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
623 eq(effect), (AudioAttributes) anyObject());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500624 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400625 }
626
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400627 @Test
Julia Reynolds85896572017-09-20 12:54:52 -0400628 public void testNoDemoteSoundToVibrateIfNonNotificationStream() throws Exception {
629 NotificationRecord r = getBeepyNotification();
630 assertTrue(r.getSound() != null);
631 assertNull(r.getVibration());
632
633 // the phone is quiet
634 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
635 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(1);
636
637 mService.buzzBeepBlinkLocked(r);
638
639 verifyNeverVibrate();
640 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500641 assertTrue(r.isInterruptive());
Julia Reynolds85896572017-09-20 12:54:52 -0400642 }
643
644 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500645 public void testDemoteSoundToVibrate() throws Exception {
646 NotificationRecord r = getBeepyNotification();
647 assertTrue(r.getSound() != null);
648 assertNull(r.getVibration());
649
650 // the phone is quiet
651 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
Julia Reynolds85896572017-09-20 12:54:52 -0400652 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500653
654 mService.buzzBeepBlinkLocked(r);
655
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700656 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
657 eq(FALLBACK_VIBRATION), (AudioAttributes) anyObject());
Julia Reynolds619a69f2017-01-27 15:11:38 -0500658 verify(mRingtonePlayer, never()).playAsync
659 (anyObject(), anyObject(), anyBoolean(), anyObject());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500660 assertTrue(r.isInterruptive());
Julia Reynolds0c299d42016-11-15 14:37:04 -0500661 }
662
663 @Test
664 public void testDemoteInsistentSoundToVibrate() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400665 NotificationRecord r = getInsistentBeepyNotification();
Julia Reynolds0c299d42016-11-15 14:37:04 -0500666 assertTrue(r.getSound() != null);
667 assertNull(r.getVibration());
Chris Wren93bb8b82016-03-29 14:35:05 -0400668
669 // the phone is quiet
670 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
671 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
672
673 mService.buzzBeepBlinkLocked(r);
674
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700675 verifyDelayedVibrateLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500676 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400677 }
678
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400679 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400680 public void testVibrate() throws Exception {
681 NotificationRecord r = getBuzzyNotification();
682
683 mService.buzzBeepBlinkLocked(r);
684
685 verifyNeverBeep();
686 verifyVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500687 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400688 }
689
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400690 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500691 public void testInsistentVibrate() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400692 NotificationRecord r = getInsistentBuzzyNotification();
693
694 mService.buzzBeepBlinkLocked(r);
695 verifyVibrateLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500696 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400697 }
698
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400699 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500700 public void testVibrateTwice() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400701 NotificationRecord r = getBuzzyNotification();
702
703 // set up internal state
704 mService.buzzBeepBlinkLocked(r);
705 Mockito.reset(mVibrator);
706
707 // update should vibrate
708 r.isUpdate = true;
709 mService.buzzBeepBlinkLocked(r);
710 verifyVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500711 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400712 }
713
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400714 @Test
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400715 public void testGroupAlertSummarySilenceChild() throws Exception {
716 NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
717
718 mService.buzzBeepBlinkLocked(child);
719
720 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500721 assertFalse(child.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400722 }
723
724 @Test
725 public void testGroupAlertSummaryNoSilenceSummary() throws Exception {
726 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
727 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
728
729 mService.buzzBeepBlinkLocked(summary);
730
731 verifyBeepLooped();
Julia Reynolds54369232018-07-03 10:43:35 -0400732 // summaries are never interruptive for notification counts
733 assertFalse(summary.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400734 }
735
736 @Test
737 public void testGroupAlertSummaryNoSilenceNonGroupChild() throws Exception {
738 NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_SUMMARY);
739
740 mService.buzzBeepBlinkLocked(nonGroup);
741
742 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500743 assertTrue(nonGroup.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400744 }
745
746 @Test
747 public void testGroupAlertChildSilenceSummary() throws Exception {
748 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
749 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
750
751 mService.buzzBeepBlinkLocked(summary);
752
753 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500754 assertFalse(summary.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400755 }
756
757 @Test
758 public void testGroupAlertChildNoSilenceChild() throws Exception {
759 NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
760
761 mService.buzzBeepBlinkLocked(child);
762
763 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500764 assertTrue(child.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400765 }
766
767 @Test
768 public void testGroupAlertChildNoSilenceNonGroupSummary() throws Exception {
769 NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_CHILDREN);
770
771 mService.buzzBeepBlinkLocked(nonGroup);
772
773 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500774 assertTrue(nonGroup.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400775 }
776
777 @Test
778 public void testGroupAlertAllNoSilenceGroup() throws Exception {
779 NotificationRecord group = getBeepyNotificationRecord("a", GROUP_ALERT_ALL);
780
781 mService.buzzBeepBlinkLocked(group);
782
783 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500784 assertTrue(group.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400785 }
786
787 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400788 public void testHonorAlertOnlyOnceForBuzz() throws Exception {
789 NotificationRecord r = getBuzzyNotification();
790 NotificationRecord s = getBuzzyOnceNotification();
791 s.isUpdate = true;
792
793 // set up internal state
794 mService.buzzBeepBlinkLocked(r);
795 Mockito.reset(mVibrator);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500796 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400797
798 // update should not beep
799 mService.buzzBeepBlinkLocked(s);
800 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500801 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400802 }
803
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400804 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400805 public void testNoisyUpdateDoesNotCancelVibrate() throws Exception {
806 NotificationRecord r = getBuzzyNotification();
807
808 mService.buzzBeepBlinkLocked(r);
809 r.isUpdate = true;
810 mService.buzzBeepBlinkLocked(r);
811
812 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500813 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400814 }
815
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400816 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400817 public void testNoisyOnceUpdateDoesNotCancelVibrate() throws Exception {
818 NotificationRecord r = getBuzzyNotification();
819 NotificationRecord s = getBuzzyOnceNotification();
820 s.isUpdate = true;
821
822 mService.buzzBeepBlinkLocked(r);
823 mService.buzzBeepBlinkLocked(s);
824
825 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500826 assertTrue(r.isInterruptive());
827 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400828 }
829
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400830 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400831 public void testQuietUpdateDoesNotCancelVibrateFromOther() throws Exception {
832 NotificationRecord r = getBuzzyNotification();
833 NotificationRecord s = getQuietNotification();
834 s.isUpdate = true;
835 NotificationRecord other = getNoisyOtherNotification();
836
837 // set up internal state
838 mService.buzzBeepBlinkLocked(r);
839 mService.buzzBeepBlinkLocked(other); // this takes the vibrate stream
840 Mockito.reset(mVibrator);
841
842 // should not stop vibrate, since we no longer own it
843 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
844 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500845 assertTrue(r.isInterruptive());
846 assertTrue(other.isInterruptive());
847 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400848 }
849
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400850 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400851 public void testQuietInterloperDoesNotCancelVibrate() throws Exception {
852 NotificationRecord r = getBuzzyNotification();
853 NotificationRecord other = getQuietOtherNotification();
854
855 // set up internal state
856 mService.buzzBeepBlinkLocked(r);
857 Mockito.reset(mVibrator);
858
859 // should not stop noise, since it does not own it
860 mService.buzzBeepBlinkLocked(other);
861 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500862 assertFalse(other.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400863 }
864
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400865 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500866 public void testQuietUpdateCancelsVibrate() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400867 NotificationRecord r = getBuzzyNotification();
868 NotificationRecord s = getQuietNotification();
869 s.isUpdate = true;
870
871 // set up internal state
872 mService.buzzBeepBlinkLocked(r);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500873 verifyVibrate();
Chris Wren93bb8b82016-03-29 14:35:05 -0400874
875 // quiet update should stop making noise
876 mService.buzzBeepBlinkLocked(s);
877 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500878 assertTrue(r.isInterruptive());
879 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400880 }
881
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400882 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500883 public void testQuietOnceUpdateCancelVibrate() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400884 NotificationRecord r = getBuzzyNotification();
885 NotificationRecord s = getQuietOnceNotification();
886 s.isUpdate = true;
887
888 // set up internal state
889 mService.buzzBeepBlinkLocked(r);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500890 verifyVibrate();
Chris Wren93bb8b82016-03-29 14:35:05 -0400891
892 // stop making noise - this is a weird corner case, but quiet should override once
893 mService.buzzBeepBlinkLocked(s);
894 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500895 assertTrue(r.isInterruptive());
896 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400897 }
898
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400899 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400900 public void testQuietUpdateCancelsDemotedVibrate() throws Exception {
901 NotificationRecord r = getBeepyNotification();
902 NotificationRecord s = getQuietNotification();
903
904 // the phone is quiet
905 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
906 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
907
908 mService.buzzBeepBlinkLocked(r);
909
910 // quiet update should stop making noise
911 mService.buzzBeepBlinkLocked(s);
912 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500913 assertTrue(r.isInterruptive());
914 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400915 }
Michael Wright71216972017-01-31 18:33:54 +0000916
Julia Reynoldsca80d162017-04-23 12:39:32 -0400917 @Test
Seungho Lee0e97ae62018-10-31 21:49:09 +0900918 public void testCanceledNoisyNeverVibrate() throws Exception {
919 NotificationRecord r = getBuzzyBeepyNotification();
920
921 final int waitMs = mAudioManager.getFocusRampTimeMs(
922 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
923 r.getAudioAttributes());
924
925 mService.buzzBeepBlinkLocked(r);
926 mService.clearNotifications();
927
928 verifyNeverVibrate();
929 Thread.sleep(waitMs);
930 verifyNeverVibrate();
931 }
932
933 @Test
Julia Reynoldsca80d162017-04-23 12:39:32 -0400934 public void testEmptyUriSoundTreatedAsNoSound() throws Exception {
935 NotificationChannel channel = new NotificationChannel("test", "test", IMPORTANCE_HIGH);
936 channel.setSound(Uri.EMPTY, null);
937 final Notification n = new Builder(getContext(), "test")
938 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
939
940 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
941 mPid, n, mUser, null, System.currentTimeMillis());
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000942 NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
Julia Reynoldsca80d162017-04-23 12:39:32 -0400943 mService.addNotification(r);
944
945 mService.buzzBeepBlinkLocked(r);
Julia Reynoldsca80d162017-04-23 12:39:32 -0400946 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500947 assertFalse(r.isInterruptive());
Julia Reynoldsca80d162017-04-23 12:39:32 -0400948 }
949
Julia Reynolds76c096d2017-06-19 08:16:04 -0400950 @Test
951 public void testRepeatedSoundOverLimitMuted() throws Exception {
952 when(mUsageStats.isAlertRateLimited(any())).thenReturn(true);
953
954 NotificationRecord r = getBeepyNotification();
955
956 mService.buzzBeepBlinkLocked(r);
957 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500958 assertFalse(r.isInterruptive());
Julia Reynolds76c096d2017-06-19 08:16:04 -0400959 }
960
961 @Test
962 public void testPostingSilentNotificationDoesNotAffectRateLimiting() throws Exception {
963 NotificationRecord r = getQuietNotification();
964 mService.buzzBeepBlinkLocked(r);
965
966 verify(mUsageStats, never()).isAlertRateLimited(any());
967 }
968
969 @Test
Julia Reynolds65b85cf2017-07-20 09:19:20 -0400970 public void testPostingGroupSuppressedDoesNotAffectRateLimiting() throws Exception {
971 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
972 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
973
974 mService.buzzBeepBlinkLocked(summary);
Julia Reynolds65b85cf2017-07-20 09:19:20 -0400975 verify(mUsageStats, never()).isAlertRateLimited(any());
976 }
977
978 @Test
Julia Reynolds79dfdd62018-04-17 15:36:33 -0400979 public void testGroupSuppressionFailureDoesNotAffectRateLimiting() {
980 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
981 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
982
983 mService.buzzBeepBlinkLocked(summary);
984 verify(mUsageStats, times(1)).isAlertRateLimited(any());
985 }
986
987 @Test
Julia Reynolds76c096d2017-06-19 08:16:04 -0400988 public void testCrossUserSoundMuted() throws Exception {
989 final Notification n = new Builder(getContext(), "test")
990 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
991
992 int userId = mUser.getIdentifier() + 1;
993 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
994 mPid, n, UserHandle.of(userId), null, System.currentTimeMillis());
995 NotificationRecord r = new NotificationRecord(getContext(), sbn,
996 new NotificationChannel("test", "test", IMPORTANCE_HIGH));
997
998 mService.buzzBeepBlinkLocked(r);
999 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -05001000 assertFalse(r.isInterruptive());
Julia Reynolds76c096d2017-06-19 08:16:04 -04001001 }
1002
Julia Reynolds94187562017-10-10 13:58:49 -04001003 @Test
1004 public void testA11yMinInitialPost() throws Exception {
1005 NotificationRecord r = getQuietNotification();
1006 r.setImportance(IMPORTANCE_MIN, "");
1007 mService.buzzBeepBlinkLocked(r);
1008 verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt());
1009 }
1010
1011 @Test
1012 public void testA11yQuietInitialPost() throws Exception {
1013 NotificationRecord r = getQuietNotification();
1014 mService.buzzBeepBlinkLocked(r);
1015 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
1016 }
1017
1018 @Test
1019 public void testA11yQuietUpdate() throws Exception {
1020 NotificationRecord r = getQuietNotification();
1021 mService.buzzBeepBlinkLocked(r);
1022 r.isUpdate = true;
1023 mService.buzzBeepBlinkLocked(r);
1024 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
1025 }
1026
Julia Reynolds54369232018-07-03 10:43:35 -04001027 @Test
1028 public void testLightsScreenOn() {
1029 mService.mScreenOn = true;
1030 NotificationRecord r = getLightsNotification();
1031 mService.buzzBeepBlinkLocked(r);
1032 verifyNeverLights();
1033 assertFalse(r.isInterruptive());
1034 }
1035
1036 @Test
1037 public void testLightsInCall() {
1038 mService.mInCall = true;
1039 NotificationRecord r = getLightsNotification();
1040 mService.buzzBeepBlinkLocked(r);
1041 verifyNeverLights();
1042 assertFalse(r.isInterruptive());
1043 }
1044
1045 @Test
1046 public void testLightsSilentUpdate() {
1047 NotificationRecord r = getLightsOnceNotification();
1048 mService.buzzBeepBlinkLocked(r);
1049 verifyLights();
1050 assertTrue(r.isInterruptive());
1051
1052 r = getLightsOnceNotification();
1053 r.isUpdate = true;
1054 mService.buzzBeepBlinkLocked(r);
1055 // checks that lights happened once, i.e. this new call didn't trigger them again
1056 verifyLights();
1057 assertFalse(r.isInterruptive());
1058 }
1059
1060 @Test
1061 public void testLightsUnimportant() {
1062 NotificationRecord r = getLightsNotification();
1063 r.setImportance(IMPORTANCE_LOW, "testing");
1064 mService.buzzBeepBlinkLocked(r);
1065 verifyNeverLights();
1066 assertFalse(r.isInterruptive());
1067 }
1068
1069 @Test
1070 public void testLightsNoLights() {
1071 NotificationRecord r = getQuietNotification();
1072 mService.buzzBeepBlinkLocked(r);
1073 verifyNeverLights();
1074 assertFalse(r.isInterruptive());
1075 }
1076
1077 @Test
1078 public void testLightsNoLightOnDevice() {
1079 mService.mHasLight = false;
1080 NotificationRecord r = getLightsNotification();
1081 mService.buzzBeepBlinkLocked(r);
1082 verifyNeverLights();
1083 assertFalse(r.isInterruptive());
1084 }
1085
1086 @Test
1087 public void testLightsLightsOffGlobally() {
1088 mService.mNotificationPulseEnabled = false;
1089 NotificationRecord r = getLightsNotification();
1090 mService.buzzBeepBlinkLocked(r);
1091 verifyNeverLights();
1092 assertFalse(r.isInterruptive());
1093 }
1094
1095 @Test
1096 public void testLightsDndIntercepted() {
1097 NotificationRecord r = getLightsNotification();
1098 r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS);
1099 mService.buzzBeepBlinkLocked(r);
1100 verifyNeverLights();
1101 assertFalse(r.isInterruptive());
1102 }
1103
1104 @Test
1105 public void testGroupAlertSummaryNoLightsChild() {
1106 NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
1107
1108 mService.buzzBeepBlinkLocked(child);
1109
1110 verifyNeverLights();
1111 assertFalse(child.isInterruptive());
1112 }
1113
1114 @Test
1115 public void testGroupAlertSummaryLightsSummary() {
1116 NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
1117 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
1118
1119 mService.buzzBeepBlinkLocked(summary);
1120
1121 verifyLights();
1122 // summaries should never count for interruptiveness counts
1123 assertFalse(summary.isInterruptive());
1124 }
1125
1126 @Test
1127 public void testGroupAlertSummaryLightsNonGroupChild() {
1128 NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_SUMMARY);
1129
1130 mService.buzzBeepBlinkLocked(nonGroup);
1131
1132 verifyLights();
1133 assertTrue(nonGroup.isInterruptive());
1134 }
1135
1136 @Test
1137 public void testGroupAlertChildNoLightsSummary() {
1138 NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
1139 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
1140
1141 mService.buzzBeepBlinkLocked(summary);
1142
1143 verifyNeverLights();
1144 assertFalse(summary.isInterruptive());
1145 }
1146
1147 @Test
1148 public void testGroupAlertChildLightsChild() {
1149 NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
1150
1151 mService.buzzBeepBlinkLocked(child);
1152
1153 verifyLights();
1154 assertTrue(child.isInterruptive());
1155 }
1156
1157 @Test
1158 public void testGroupAlertChildLightsNonGroupSummary() {
1159 NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_CHILDREN);
1160
1161 mService.buzzBeepBlinkLocked(nonGroup);
1162
1163 verifyLights();
1164 assertTrue(nonGroup.isInterruptive());
1165 }
1166
1167 @Test
1168 public void testGroupAlertAllLightsGroup() {
1169 NotificationRecord group = getLightsNotificationRecord("a", GROUP_ALERT_ALL);
1170
1171 mService.buzzBeepBlinkLocked(group);
1172
1173 verifyLights();
1174 assertTrue(group.isInterruptive());
1175 }
1176
Michael Wright71216972017-01-31 18:33:54 +00001177 static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
1178 private final int mRepeatIndex;
1179
1180 VibrateRepeatMatcher(int repeatIndex) {
1181 mRepeatIndex = repeatIndex;
1182 }
1183
1184 @Override
1185 public boolean matches(VibrationEffect actual) {
1186 if (actual instanceof VibrationEffect.Waveform &&
1187 ((VibrationEffect.Waveform) actual).getRepeatIndex() == mRepeatIndex) {
1188 return true;
1189 }
1190 // All non-waveform effects are essentially one shots.
1191 return mRepeatIndex == -1;
1192 }
1193
1194 @Override
1195 public String toString() {
1196 return "repeatIndex=" + mRepeatIndex;
1197 }
1198 }
Chris Wren93bb8b82016-03-29 14:35:05 -04001199}