blob: c602804a57a92e3713459ad27fddd2f6f9926be3 [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;
63import android.support.test.runner.AndroidJUnit4;
64import android.test.suitebuilder.annotation.SmallTest;
Julia Reynolds94187562017-10-10 13:58:49 -040065import android.view.accessibility.AccessibilityEvent;
66import android.view.accessibility.AccessibilityManager;
67import android.view.accessibility.IAccessibilityManager;
68import android.view.accessibility.IAccessibilityManagerClient;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070069
Julia Reynolds94187562017-10-10 13:58:49 -040070import com.android.internal.util.IntPair;
Jason Monk74f5e362017-12-06 08:56:33 -050071import com.android.server.UiServiceTestCase;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070072import com.android.server.lights.Light;
73
74import org.junit.Before;
75import org.junit.Test;
76import org.junit.runner.RunWith;
77import org.mockito.ArgumentMatcher;
78import org.mockito.Mock;
79import org.mockito.Mockito;
80import org.mockito.MockitoAnnotations;
81
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -040082@SmallTest
83@RunWith(AndroidJUnit4.class)
Jason Monk74f5e362017-12-06 08:56:33 -050084public class BuzzBeepBlinkTest extends UiServiceTestCase {
Chris Wren93bb8b82016-03-29 14:35:05 -040085
86 @Mock AudioManager mAudioManager;
87 @Mock Vibrator mVibrator;
88 @Mock android.media.IRingtonePlayer mRingtonePlayer;
Julia Reynoldsb5e44b72016-08-16 15:00:25 -040089 @Mock Light mLight;
Julia Reynoldseb3dca72017-07-11 10:39:58 -040090 @Mock
91 NotificationManagerService.WorkerHandler mHandler;
Julia Reynolds76c096d2017-06-19 08:16:04 -040092 @Mock
93 NotificationUsageStats mUsageStats;
Julia Reynolds94187562017-10-10 13:58:49 -040094 @Mock
95 IAccessibilityManager mAccessibilityService;
Chris Wren93bb8b82016-03-29 14:35:05 -040096
97 private NotificationManagerService mService;
98 private String mPkg = "com.android.server.notification";
99 private int mId = 1001;
100 private int mOtherId = 1002;
101 private String mTag = null;
102 private int mUid = 1000;
103 private int mPid = 2000;
Chris Wren93bb8b82016-03-29 14:35:05 -0400104 private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
105
Michael Wright71216972017-01-31 18:33:54 +0000106 private VibrateRepeatMatcher mVibrateOnceMatcher = new VibrateRepeatMatcher(-1);
107 private VibrateRepeatMatcher mVibrateLoopMatcher = new VibrateRepeatMatcher(0);
108
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400109 private static final long[] CUSTOM_VIBRATION = new long[] {
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 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 };
113 private static final Uri CUSTOM_SOUND = Settings.System.DEFAULT_ALARM_ALERT_URI;
Julia Reynolds619a69f2017-01-27 15:11:38 -0500114 private static final AudioAttributes CUSTOM_ATTRIBUTES = new AudioAttributes.Builder()
115 .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
Julia Reynolds9aee2842019-01-03 14:35:38 -0500116 .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
Julia Reynolds619a69f2017-01-27 15:11:38 -0500117 .build();
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400118 private static final int CUSTOM_LIGHT_COLOR = Color.BLACK;
119 private static final int CUSTOM_LIGHT_ON = 10000;
120 private static final int CUSTOM_LIGHT_OFF = 10000;
Michael Wright71216972017-01-31 18:33:54 +0000121 private static final long[] FALLBACK_VIBRATION_PATTERN = new long[] {100, 100, 100};
122 private static final VibrationEffect FALLBACK_VIBRATION =
123 VibrationEffect.createWaveform(FALLBACK_VIBRATION_PATTERN, -1);
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700124 private static final int MAX_VIBRATION_DELAY = 1000;
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400125
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400126 @Before
Julia Reynolds94187562017-10-10 13:58:49 -0400127 public void setUp() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400128 MockitoAnnotations.initMocks(this);
129
130 when(mAudioManager.isAudioFocusExclusive()).thenReturn(false);
131 when(mAudioManager.getRingtonePlayer()).thenReturn(mRingtonePlayer);
132 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
133 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynolds76c096d2017-06-19 08:16:04 -0400134 when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
135
Julia Reynolds94187562017-10-10 13:58:49 -0400136 long serviceReturnValue = IntPair.of(
137 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED,
138 AccessibilityEvent.TYPES_ALL_MASK);
139 when(mAccessibilityService.addClient(any(), anyInt())).thenReturn(serviceReturnValue);
140 AccessibilityManager accessibilityManager =
141 new AccessibilityManager(Handler.getMain(), mAccessibilityService, 0);
142 verify(mAccessibilityService).addClient(any(IAccessibilityManagerClient.class), anyInt());
143 assertTrue(accessibilityManager.isEnabled());
144
145 mService = spy(new NotificationManagerService(getContext()));
Chris Wren93bb8b82016-03-29 14:35:05 -0400146 mService.setAudioManager(mAudioManager);
147 mService.setVibrator(mVibrator);
148 mService.setSystemReady(true);
149 mService.setHandler(mHandler);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400150 mService.setLights(mLight);
151 mService.setScreenOn(false);
Michael Wright71216972017-01-31 18:33:54 +0000152 mService.setFallbackVibrationPattern(FALLBACK_VIBRATION_PATTERN);
Julia Reynolds76c096d2017-06-19 08:16:04 -0400153 mService.setUsageStats(mUsageStats);
Julia Reynolds94187562017-10-10 13:58:49 -0400154 mService.setAccessibilityManager(accessibilityManager);
Julia Reynolds54369232018-07-03 10:43:35 -0400155 mService.mScreenOn = false;
156 mService.mInCall = false;
157 mService.mNotificationPulseEnabled = true;
Chris Wren93bb8b82016-03-29 14:35:05 -0400158 }
159
160 //
161 // Convenience functions for creating notification records
162 //
163
164 private NotificationRecord getNoisyOtherNotification() {
165 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400166 true /* noisy */, true /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400167 }
168
169 private NotificationRecord getBeepyNotification() {
170 return getNotificationRecord(mId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400171 true /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400172 }
173
174 private NotificationRecord getBeepyOnceNotification() {
175 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400176 true /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400177 }
178
179 private NotificationRecord getQuietNotification() {
180 return getNotificationRecord(mId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400181 false /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400182 }
183
184 private NotificationRecord getQuietOtherNotification() {
185 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400186 false /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400187 }
188
189 private NotificationRecord getQuietOnceNotification() {
190 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400191 false /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400192 }
193
194 private NotificationRecord getInsistentBeepyNotification() {
195 return getNotificationRecord(mId, true /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400196 true /* noisy */, false /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400197 }
198
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700199 private NotificationRecord getInsistentBeepyLeanbackNotification() {
200 return getLeanbackNotificationRecord(mId, true /* insistent */, false /* once */,
201 true /* noisy */, false /* buzzy*/, false /* lights */);
202 }
203
Chris Wren93bb8b82016-03-29 14:35:05 -0400204 private NotificationRecord getBuzzyNotification() {
205 return getNotificationRecord(mId, false /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400206 false /* noisy */, true /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400207 }
208
209 private NotificationRecord getBuzzyOnceNotification() {
210 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400211 false /* noisy */, true /* buzzy*/, false /* lights */);
Chris Wren93bb8b82016-03-29 14:35:05 -0400212 }
213
214 private NotificationRecord getInsistentBuzzyNotification() {
215 return getNotificationRecord(mId, true /* insistent */, false /* once */,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400216 false /* noisy */, true /* buzzy*/, false /* lights */);
217 }
218
Julia Reynolds0c299d42016-11-15 14:37:04 -0500219 private NotificationRecord getBuzzyBeepyNotification() {
220 return getNotificationRecord(mId, false /* insistent */, false /* once */,
221 true /* noisy */, true /* buzzy*/, false /* lights */);
222 }
223
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400224 private NotificationRecord getLightsNotification() {
Julia Reynolds54369232018-07-03 10:43:35 -0400225 return getNotificationRecord(mId, false /* insistent */, false /* once */,
226 false /* noisy */, false /* buzzy*/, true /* lights */);
227 }
228
229 private NotificationRecord getLightsOnceNotification() {
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400230 return getNotificationRecord(mId, false /* insistent */, true /* once */,
Julia Reynolds54369232018-07-03 10:43:35 -0400231 false /* noisy */, false /* buzzy*/, true /* lights */);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400232 }
233
Julia Reynolds9aee2842019-01-03 14:35:38 -0500234 private NotificationRecord getCallRecord(int id, boolean insistent) {
235 return getNotificationRecord(id, false, false /* once */, true /* noisy */,
236 false /* buzzy */, false /* lights */, false /* default vib */,
237 false /* default sound */, false /* default lights */, "",
238 Notification.GROUP_ALERT_ALL, false);
Chris Wren93bb8b82016-03-29 14:35:05 -0400239 }
240
241 private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400242 boolean noisy, boolean buzzy, boolean lights) {
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400243 return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, true,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700244 null, Notification.GROUP_ALERT_ALL, false);
245 }
246
247 private NotificationRecord getLeanbackNotificationRecord(int id, boolean insistent, boolean once,
248 boolean noisy, boolean buzzy, boolean lights) {
249 return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, true,
250 null, Notification.GROUP_ALERT_ALL, true);
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400251 }
252
253 private NotificationRecord getBeepyNotificationRecord(String groupKey, int groupAlertBehavior) {
254 return getNotificationRecord(mId, false, false, true, false, false, true, true, true,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700255 groupKey, groupAlertBehavior, false);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400256 }
257
Julia Reynolds54369232018-07-03 10:43:35 -0400258 private NotificationRecord getLightsNotificationRecord(String groupKey,
259 int groupAlertBehavior) {
260 return getNotificationRecord(mId, false, false, false, false, true /*lights*/, true, true,
261 true, groupKey, groupAlertBehavior, false);
262 }
263
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400264 private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
265 boolean noisy, boolean buzzy, boolean lights, boolean defaultVibration,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700266 boolean defaultSound, boolean defaultLights, String groupKey, int groupAlertBehavior,
267 boolean isLeanback) {
Julia Reynolds0c299d42016-11-15 14:37:04 -0500268 NotificationChannel channel =
Julia Reynoldsca80d162017-04-23 12:39:32 -0400269 new NotificationChannel("test", "test", IMPORTANCE_HIGH);
Chris Wren93bb8b82016-03-29 14:35:05 -0400270 final Builder builder = new Builder(getContext())
271 .setContentTitle("foo")
272 .setSmallIcon(android.R.drawable.sym_def_app_icon)
273 .setPriority(Notification.PRIORITY_HIGH)
274 .setOnlyAlertOnce(once);
275
276 int defaults = 0;
277 if (noisy) {
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400278 if (defaultSound) {
279 defaults |= Notification.DEFAULT_SOUND;
Julia Reynolds619a69f2017-01-27 15:11:38 -0500280 channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
281 Notification.AUDIO_ATTRIBUTES_DEFAULT);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400282 } else {
283 builder.setSound(CUSTOM_SOUND);
Julia Reynolds619a69f2017-01-27 15:11:38 -0500284 channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400285 }
Julia Reynolds184b86d2017-04-12 13:27:58 -0400286 } else {
287 channel.setSound(null, null);
Chris Wren93bb8b82016-03-29 14:35:05 -0400288 }
289 if (buzzy) {
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400290 if (defaultVibration) {
291 defaults |= Notification.DEFAULT_VIBRATE;
292 } else {
293 builder.setVibrate(CUSTOM_VIBRATION);
Julia Reynoldsf57de462016-11-23 11:31:46 -0500294 channel.setVibrationPattern(CUSTOM_VIBRATION);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400295 }
Julia Reynoldsf57de462016-11-23 11:31:46 -0500296 channel.enableVibration(true);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400297 }
298 if (lights) {
299 if (defaultLights) {
300 defaults |= Notification.DEFAULT_LIGHTS;
301 } else {
302 builder.setLights(CUSTOM_LIGHT_COLOR, CUSTOM_LIGHT_ON, CUSTOM_LIGHT_OFF);
303 }
Julia Reynolds529e3322017-02-06 08:33:01 -0500304 channel.enableLights(true);
Chris Wren93bb8b82016-03-29 14:35:05 -0400305 }
306 builder.setDefaults(defaults);
307
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400308 builder.setGroup(groupKey);
309 builder.setGroupAlertBehavior(groupAlertBehavior);
310
Chris Wren93bb8b82016-03-29 14:35:05 -0400311 Notification n = builder.build();
312 if (insistent) {
313 n.flags |= Notification.FLAG_INSISTENT;
314 }
Julia Reynolds0c299d42016-11-15 14:37:04 -0500315
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700316 Context context = spy(getContext());
317 PackageManager packageManager = spy(context.getPackageManager());
318 when(context.getPackageManager()).thenReturn(packageManager);
319 when(packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
320 .thenReturn(isLeanback);
321
Julia Reynolds924eed12017-01-19 09:52:07 -0500322 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid,
Julia Reynolds423b9fc2016-11-09 09:51:08 -0500323 mPid, n, mUser, null, System.currentTimeMillis());
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700324 NotificationRecord r = new NotificationRecord(context, sbn, channel);
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400325 mService.addNotification(r);
326 return r;
Chris Wren93bb8b82016-03-29 14:35:05 -0400327 }
328
329 //
330 // Convenience functions for interacting with mocks
331 //
332
333 private void verifyNeverBeep() throws RemoteException {
334 verify(mRingtonePlayer, never()).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
335 anyBoolean(), (AudioAttributes) anyObject());
336 }
337
338 private void verifyBeep() throws RemoteException {
339 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
340 eq(true), (AudioAttributes) anyObject());
341 }
342
343 private void verifyBeepLooped() throws RemoteException {
344 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
345 eq(false), (AudioAttributes) anyObject());
346 }
347
348 private void verifyNeverStopAudio() throws RemoteException {
349 verify(mRingtonePlayer, never()).stopAsync();
350 }
351
352 private void verifyStopAudio() throws RemoteException {
353 verify(mRingtonePlayer, times(1)).stopAsync();
354 }
355
356 private void verifyNeverVibrate() {
Michael Wright71216972017-01-31 18:33:54 +0000357 verify(mVibrator, never()).vibrate(anyInt(), anyString(), (VibrationEffect) anyObject(),
358 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400359 }
360
361 private void verifyVibrate() {
Michael Wright71216972017-01-31 18:33:54 +0000362 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateOnceMatcher),
363 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400364 }
365
366 private void verifyVibrateLooped() {
Michael Wright71216972017-01-31 18:33:54 +0000367 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateLoopMatcher),
368 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400369 }
370
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700371 private void verifyDelayedVibrateLooped() {
372 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
373 argThat(mVibrateLoopMatcher), (AudioAttributes) anyObject());
374 }
375
Chris Wren93bb8b82016-03-29 14:35:05 -0400376 private void verifyStopVibrate() {
377 verify(mVibrator, times(1)).cancel();
378 }
379
380 private void verifyNeverStopVibrate() throws RemoteException {
381 verify(mVibrator, never()).cancel();
382 }
383
Julia Reynolds54369232018-07-03 10:43:35 -0400384 private void verifyNeverLights() {
385 verify(mLight, never()).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
386 }
387
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400388 private void verifyLights() {
Julia Reynolds033a4122017-01-31 16:50:38 -0500389 verify(mLight, times(1)).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400390 }
391
392 private void verifyCustomLights() {
Julia Reynolds033a4122017-01-31 16:50:38 -0500393 verify(mLight, times(1)).setFlashing(
394 eq(CUSTOM_LIGHT_COLOR), anyInt(), eq(CUSTOM_LIGHT_ON), eq(CUSTOM_LIGHT_OFF));
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400395 }
396
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400397 //
398 // Tests
399 //
400
401 @Test
402 public void testLights() throws Exception {
403 NotificationRecord r = getLightsNotification();
404 r.setImportance(NotificationManager.IMPORTANCE_DEFAULT, "for testing");
405
406 mService.buzzBeepBlinkLocked(r);
407
408 verifyLights();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500409 assertTrue(r.isInterruptive());
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400410 }
411
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400412 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400413 public void testBeep() throws Exception {
414 NotificationRecord r = getBeepyNotification();
415
416 mService.buzzBeepBlinkLocked(r);
417
418 verifyBeepLooped();
419 verifyNeverVibrate();
Julia Reynolds94187562017-10-10 13:58:49 -0400420 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500421 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400422 }
423
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400424 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400425 public void testBeepInsistently() throws Exception {
426 NotificationRecord r = getInsistentBeepyNotification();
427
428 mService.buzzBeepBlinkLocked(r);
429
430 verifyBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500431 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400432 }
433
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400434 @Test
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700435 public void testNoLeanbackBeep() throws Exception {
436 NotificationRecord r = getInsistentBeepyLeanbackNotification();
437
438 mService.buzzBeepBlinkLocked(r);
439
440 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500441 assertFalse(r.isInterruptive());
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700442 }
443
444 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400445 public void testNoInterruptionForMin() throws Exception {
446 NotificationRecord r = getBeepyNotification();
Julia Reynolds85769912016-10-25 09:08:57 -0400447 r.setImportance(NotificationManager.IMPORTANCE_MIN, "foo");
Chris Wren93bb8b82016-03-29 14:35:05 -0400448
449 mService.buzzBeepBlinkLocked(r);
450
451 verifyNeverBeep();
452 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500453 assertFalse(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400454 }
455
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400456 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400457 public void testNoInterruptionForIntercepted() throws Exception {
458 NotificationRecord r = getBeepyNotification();
459 r.setIntercepted(true);
460
461 mService.buzzBeepBlinkLocked(r);
462
463 verifyNeverBeep();
464 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500465 assertFalse(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400466 }
467
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400468 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400469 public void testBeepTwice() throws Exception {
470 NotificationRecord r = getBeepyNotification();
471
472 // set up internal state
473 mService.buzzBeepBlinkLocked(r);
474 Mockito.reset(mRingtonePlayer);
475
476 // update should beep
477 r.isUpdate = true;
478 mService.buzzBeepBlinkLocked(r);
479 verifyBeepLooped();
Julia Reynolds94187562017-10-10 13:58:49 -0400480 verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500481 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400482 }
483
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400484 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400485 public void testHonorAlertOnlyOnceForBeep() throws Exception {
486 NotificationRecord r = getBeepyNotification();
487 NotificationRecord s = getBeepyOnceNotification();
488 s.isUpdate = true;
489
490 // set up internal state
491 mService.buzzBeepBlinkLocked(r);
492 Mockito.reset(mRingtonePlayer);
493
494 // update should not beep
495 mService.buzzBeepBlinkLocked(s);
496 verifyNeverBeep();
Julia Reynolds94187562017-10-10 13:58:49 -0400497 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
Chris Wren93bb8b82016-03-29 14:35:05 -0400498 }
499
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400500 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400501 public void testNoisyUpdateDoesNotCancelAudio() throws Exception {
502 NotificationRecord r = getBeepyNotification();
503
504 mService.buzzBeepBlinkLocked(r);
505 r.isUpdate = true;
506 mService.buzzBeepBlinkLocked(r);
507
508 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500509 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400510 }
511
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400512 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400513 public void testNoisyOnceUpdateDoesNotCancelAudio() throws Exception {
514 NotificationRecord r = getBeepyNotification();
515 NotificationRecord s = getBeepyOnceNotification();
516 s.isUpdate = true;
517
518 mService.buzzBeepBlinkLocked(r);
519 mService.buzzBeepBlinkLocked(s);
520
521 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500522 assertTrue(r.isInterruptive());
523 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400524 }
525
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400526 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400527 public void testQuietUpdateDoesNotCancelAudioFromOther() throws Exception {
528 NotificationRecord r = getBeepyNotification();
529 NotificationRecord s = getQuietNotification();
530 s.isUpdate = true;
531 NotificationRecord other = getNoisyOtherNotification();
532
533 // set up internal state
534 mService.buzzBeepBlinkLocked(r);
535 mService.buzzBeepBlinkLocked(other); // this takes the audio stream
536 Mockito.reset(mRingtonePlayer);
537
538 // should not stop noise, since we no longer own it
539 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
540 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500541 assertTrue(other.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400542 }
543
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400544 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400545 public void testQuietInterloperDoesNotCancelAudio() throws Exception {
546 NotificationRecord r = getBeepyNotification();
547 NotificationRecord other = getQuietOtherNotification();
548
549 // set up internal state
550 mService.buzzBeepBlinkLocked(r);
551 Mockito.reset(mRingtonePlayer);
552
553 // should not stop noise, since it does not own it
554 mService.buzzBeepBlinkLocked(other);
555 verifyNeverStopAudio();
556 }
557
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400558 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400559 public void testQuietUpdateCancelsAudio() throws Exception {
560 NotificationRecord r = getBeepyNotification();
561 NotificationRecord s = getQuietNotification();
562 s.isUpdate = true;
563
564 // set up internal state
565 mService.buzzBeepBlinkLocked(r);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500566 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400567 Mockito.reset(mRingtonePlayer);
568
569 // quiet update should stop making noise
570 mService.buzzBeepBlinkLocked(s);
571 verifyStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500572 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400573 }
574
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400575 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400576 public void testQuietOnceUpdateCancelsAudio() throws Exception {
577 NotificationRecord r = getBeepyNotification();
578 NotificationRecord s = getQuietOnceNotification();
579 s.isUpdate = true;
580
581 // set up internal state
582 mService.buzzBeepBlinkLocked(r);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500583 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400584 Mockito.reset(mRingtonePlayer);
585
586 // stop making noise - this is a weird corner case, but quiet should override once
587 mService.buzzBeepBlinkLocked(s);
588 verifyStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500589 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400590 }
591
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400592 @Test
Beverly5d463b62017-07-26 14:13:40 -0400593 public void testInCallNotification() throws Exception {
594 NotificationRecord r = getBeepyNotification();
595
596 // set up internal state
597 mService.buzzBeepBlinkLocked(r);
598 Mockito.reset(mRingtonePlayer);
599
600 mService.mInCall = true;
601 mService.buzzBeepBlinkLocked(r);
602
Julia Reynolds94187562017-10-10 13:58:49 -0400603 verify(mService, times(1)).playInCallNotification();
Beverly5d463b62017-07-26 14:13:40 -0400604 verifyNeverBeep(); // doesn't play normal beep
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500605 assertTrue(r.isInterruptive());
Beverly5d463b62017-07-26 14:13:40 -0400606 }
607
608 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500609 public void testNoDemoteSoundToVibrateIfVibrateGiven() throws Exception {
610 NotificationRecord r = getBuzzyBeepyNotification();
611 assertTrue(r.getSound() != null);
Chris Wren93bb8b82016-03-29 14:35:05 -0400612
613 // the phone is quiet
Chris Wren93bb8b82016-03-29 14:35:05 -0400614 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
Julia Reynolds85896572017-09-20 12:54:52 -0400615 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
Chris Wren93bb8b82016-03-29 14:35:05 -0400616
617 mService.buzzBeepBlinkLocked(r);
618
Michael Wright71216972017-01-31 18:33:54 +0000619 VibrationEffect effect = VibrationEffect.createWaveform(r.getVibration(), -1);
620
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700621 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
622 eq(effect), (AudioAttributes) anyObject());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500623 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400624 }
625
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400626 @Test
Julia Reynolds85896572017-09-20 12:54:52 -0400627 public void testNoDemoteSoundToVibrateIfNonNotificationStream() throws Exception {
628 NotificationRecord r = getBeepyNotification();
629 assertTrue(r.getSound() != null);
630 assertNull(r.getVibration());
631
632 // the phone is quiet
633 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
634 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(1);
635
636 mService.buzzBeepBlinkLocked(r);
637
638 verifyNeverVibrate();
639 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500640 assertTrue(r.isInterruptive());
Julia Reynolds85896572017-09-20 12:54:52 -0400641 }
642
643 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500644 public void testDemoteSoundToVibrate() throws Exception {
645 NotificationRecord r = getBeepyNotification();
646 assertTrue(r.getSound() != null);
647 assertNull(r.getVibration());
648
649 // the phone is quiet
650 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
Julia Reynolds85896572017-09-20 12:54:52 -0400651 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500652
653 mService.buzzBeepBlinkLocked(r);
654
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700655 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
656 eq(FALLBACK_VIBRATION), (AudioAttributes) anyObject());
Julia Reynolds619a69f2017-01-27 15:11:38 -0500657 verify(mRingtonePlayer, never()).playAsync
658 (anyObject(), anyObject(), anyBoolean(), anyObject());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500659 assertTrue(r.isInterruptive());
Julia Reynolds0c299d42016-11-15 14:37:04 -0500660 }
661
662 @Test
663 public void testDemoteInsistentSoundToVibrate() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400664 NotificationRecord r = getInsistentBeepyNotification();
Julia Reynolds0c299d42016-11-15 14:37:04 -0500665 assertTrue(r.getSound() != null);
666 assertNull(r.getVibration());
Chris Wren93bb8b82016-03-29 14:35:05 -0400667
668 // the phone is quiet
669 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
670 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
671
672 mService.buzzBeepBlinkLocked(r);
673
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700674 verifyDelayedVibrateLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500675 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400676 }
677
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400678 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400679 public void testVibrate() throws Exception {
680 NotificationRecord r = getBuzzyNotification();
681
682 mService.buzzBeepBlinkLocked(r);
683
684 verifyNeverBeep();
685 verifyVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500686 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400687 }
688
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400689 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500690 public void testInsistentVibrate() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400691 NotificationRecord r = getInsistentBuzzyNotification();
692
693 mService.buzzBeepBlinkLocked(r);
694 verifyVibrateLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500695 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400696 }
697
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400698 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500699 public void testVibrateTwice() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400700 NotificationRecord r = getBuzzyNotification();
701
702 // set up internal state
703 mService.buzzBeepBlinkLocked(r);
704 Mockito.reset(mVibrator);
705
706 // update should vibrate
707 r.isUpdate = true;
708 mService.buzzBeepBlinkLocked(r);
709 verifyVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500710 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400711 }
712
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400713 @Test
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400714 public void testGroupAlertSummarySilenceChild() throws Exception {
715 NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
716
717 mService.buzzBeepBlinkLocked(child);
718
719 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500720 assertFalse(child.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400721 }
722
723 @Test
724 public void testGroupAlertSummaryNoSilenceSummary() throws Exception {
725 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
726 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
727
728 mService.buzzBeepBlinkLocked(summary);
729
730 verifyBeepLooped();
Julia Reynolds54369232018-07-03 10:43:35 -0400731 // summaries are never interruptive for notification counts
732 assertFalse(summary.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400733 }
734
735 @Test
736 public void testGroupAlertSummaryNoSilenceNonGroupChild() throws Exception {
737 NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_SUMMARY);
738
739 mService.buzzBeepBlinkLocked(nonGroup);
740
741 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500742 assertTrue(nonGroup.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400743 }
744
745 @Test
746 public void testGroupAlertChildSilenceSummary() throws Exception {
747 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
748 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
749
750 mService.buzzBeepBlinkLocked(summary);
751
752 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500753 assertFalse(summary.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400754 }
755
756 @Test
757 public void testGroupAlertChildNoSilenceChild() throws Exception {
758 NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
759
760 mService.buzzBeepBlinkLocked(child);
761
762 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500763 assertTrue(child.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400764 }
765
766 @Test
767 public void testGroupAlertChildNoSilenceNonGroupSummary() throws Exception {
768 NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_CHILDREN);
769
770 mService.buzzBeepBlinkLocked(nonGroup);
771
772 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500773 assertTrue(nonGroup.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400774 }
775
776 @Test
777 public void testGroupAlertAllNoSilenceGroup() throws Exception {
778 NotificationRecord group = getBeepyNotificationRecord("a", GROUP_ALERT_ALL);
779
780 mService.buzzBeepBlinkLocked(group);
781
782 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500783 assertTrue(group.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400784 }
785
786 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400787 public void testHonorAlertOnlyOnceForBuzz() throws Exception {
788 NotificationRecord r = getBuzzyNotification();
789 NotificationRecord s = getBuzzyOnceNotification();
790 s.isUpdate = true;
791
792 // set up internal state
793 mService.buzzBeepBlinkLocked(r);
794 Mockito.reset(mVibrator);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500795 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400796
797 // update should not beep
798 mService.buzzBeepBlinkLocked(s);
799 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500800 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400801 }
802
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400803 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400804 public void testNoisyUpdateDoesNotCancelVibrate() throws Exception {
805 NotificationRecord r = getBuzzyNotification();
806
807 mService.buzzBeepBlinkLocked(r);
808 r.isUpdate = true;
809 mService.buzzBeepBlinkLocked(r);
810
811 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500812 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400813 }
814
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400815 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400816 public void testNoisyOnceUpdateDoesNotCancelVibrate() throws Exception {
817 NotificationRecord r = getBuzzyNotification();
818 NotificationRecord s = getBuzzyOnceNotification();
819 s.isUpdate = true;
820
821 mService.buzzBeepBlinkLocked(r);
822 mService.buzzBeepBlinkLocked(s);
823
824 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500825 assertTrue(r.isInterruptive());
826 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400827 }
828
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400829 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400830 public void testQuietUpdateDoesNotCancelVibrateFromOther() throws Exception {
831 NotificationRecord r = getBuzzyNotification();
832 NotificationRecord s = getQuietNotification();
833 s.isUpdate = true;
834 NotificationRecord other = getNoisyOtherNotification();
835
836 // set up internal state
837 mService.buzzBeepBlinkLocked(r);
838 mService.buzzBeepBlinkLocked(other); // this takes the vibrate stream
839 Mockito.reset(mVibrator);
840
841 // should not stop vibrate, since we no longer own it
842 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
843 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500844 assertTrue(r.isInterruptive());
845 assertTrue(other.isInterruptive());
846 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400847 }
848
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400849 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400850 public void testQuietInterloperDoesNotCancelVibrate() throws Exception {
851 NotificationRecord r = getBuzzyNotification();
852 NotificationRecord other = getQuietOtherNotification();
853
854 // set up internal state
855 mService.buzzBeepBlinkLocked(r);
856 Mockito.reset(mVibrator);
857
858 // should not stop noise, since it does not own it
859 mService.buzzBeepBlinkLocked(other);
860 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500861 assertFalse(other.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400862 }
863
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400864 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500865 public void testQuietUpdateCancelsVibrate() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400866 NotificationRecord r = getBuzzyNotification();
867 NotificationRecord s = getQuietNotification();
868 s.isUpdate = true;
869
870 // set up internal state
871 mService.buzzBeepBlinkLocked(r);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500872 verifyVibrate();
Chris Wren93bb8b82016-03-29 14:35:05 -0400873
874 // quiet update should stop making noise
875 mService.buzzBeepBlinkLocked(s);
876 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500877 assertTrue(r.isInterruptive());
878 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400879 }
880
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400881 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500882 public void testQuietOnceUpdateCancelVibrate() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400883 NotificationRecord r = getBuzzyNotification();
884 NotificationRecord s = getQuietOnceNotification();
885 s.isUpdate = true;
886
887 // set up internal state
888 mService.buzzBeepBlinkLocked(r);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500889 verifyVibrate();
Chris Wren93bb8b82016-03-29 14:35:05 -0400890
891 // stop making noise - this is a weird corner case, but quiet should override once
892 mService.buzzBeepBlinkLocked(s);
893 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500894 assertTrue(r.isInterruptive());
895 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400896 }
897
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400898 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400899 public void testQuietUpdateCancelsDemotedVibrate() throws Exception {
900 NotificationRecord r = getBeepyNotification();
901 NotificationRecord s = getQuietNotification();
902
903 // the phone is quiet
904 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
905 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
906
907 mService.buzzBeepBlinkLocked(r);
908
909 // quiet update should stop making noise
910 mService.buzzBeepBlinkLocked(s);
911 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500912 assertTrue(r.isInterruptive());
913 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400914 }
Michael Wright71216972017-01-31 18:33:54 +0000915
Julia Reynoldsca80d162017-04-23 12:39:32 -0400916 @Test
Seungho Lee0e97ae62018-10-31 21:49:09 +0900917 public void testCanceledNoisyNeverVibrate() throws Exception {
918 NotificationRecord r = getBuzzyBeepyNotification();
919
920 final int waitMs = mAudioManager.getFocusRampTimeMs(
921 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
922 r.getAudioAttributes());
923
924 mService.buzzBeepBlinkLocked(r);
925 mService.clearNotifications();
926
927 verifyNeverVibrate();
928 Thread.sleep(waitMs);
929 verifyNeverVibrate();
930 }
931
932 @Test
Julia Reynoldsca80d162017-04-23 12:39:32 -0400933 public void testEmptyUriSoundTreatedAsNoSound() throws Exception {
934 NotificationChannel channel = new NotificationChannel("test", "test", IMPORTANCE_HIGH);
935 channel.setSound(Uri.EMPTY, null);
936 final Notification n = new Builder(getContext(), "test")
937 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
938
939 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
940 mPid, n, mUser, null, System.currentTimeMillis());
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000941 NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
Julia Reynoldsca80d162017-04-23 12:39:32 -0400942 mService.addNotification(r);
943
944 mService.buzzBeepBlinkLocked(r);
Julia Reynoldsca80d162017-04-23 12:39:32 -0400945 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500946 assertFalse(r.isInterruptive());
Julia Reynoldsca80d162017-04-23 12:39:32 -0400947 }
948
Julia Reynolds76c096d2017-06-19 08:16:04 -0400949 @Test
950 public void testRepeatedSoundOverLimitMuted() throws Exception {
951 when(mUsageStats.isAlertRateLimited(any())).thenReturn(true);
952
953 NotificationRecord r = getBeepyNotification();
954
955 mService.buzzBeepBlinkLocked(r);
956 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500957 assertFalse(r.isInterruptive());
Julia Reynolds76c096d2017-06-19 08:16:04 -0400958 }
959
960 @Test
961 public void testPostingSilentNotificationDoesNotAffectRateLimiting() throws Exception {
962 NotificationRecord r = getQuietNotification();
963 mService.buzzBeepBlinkLocked(r);
964
965 verify(mUsageStats, never()).isAlertRateLimited(any());
966 }
967
968 @Test
Julia Reynolds65b85cf2017-07-20 09:19:20 -0400969 public void testPostingGroupSuppressedDoesNotAffectRateLimiting() throws Exception {
970 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
971 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
972
973 mService.buzzBeepBlinkLocked(summary);
Julia Reynolds65b85cf2017-07-20 09:19:20 -0400974 verify(mUsageStats, never()).isAlertRateLimited(any());
975 }
976
977 @Test
Julia Reynolds79dfdd62018-04-17 15:36:33 -0400978 public void testGroupSuppressionFailureDoesNotAffectRateLimiting() {
979 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
980 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
981
982 mService.buzzBeepBlinkLocked(summary);
983 verify(mUsageStats, times(1)).isAlertRateLimited(any());
984 }
985
986 @Test
Julia Reynolds76c096d2017-06-19 08:16:04 -0400987 public void testCrossUserSoundMuted() throws Exception {
988 final Notification n = new Builder(getContext(), "test")
989 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
990
991 int userId = mUser.getIdentifier() + 1;
992 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
993 mPid, n, UserHandle.of(userId), null, System.currentTimeMillis());
994 NotificationRecord r = new NotificationRecord(getContext(), sbn,
995 new NotificationChannel("test", "test", IMPORTANCE_HIGH));
996
997 mService.buzzBeepBlinkLocked(r);
998 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500999 assertFalse(r.isInterruptive());
Julia Reynolds76c096d2017-06-19 08:16:04 -04001000 }
1001
Julia Reynolds94187562017-10-10 13:58:49 -04001002 @Test
1003 public void testA11yMinInitialPost() throws Exception {
1004 NotificationRecord r = getQuietNotification();
1005 r.setImportance(IMPORTANCE_MIN, "");
1006 mService.buzzBeepBlinkLocked(r);
1007 verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt());
1008 }
1009
1010 @Test
1011 public void testA11yQuietInitialPost() throws Exception {
1012 NotificationRecord r = getQuietNotification();
1013 mService.buzzBeepBlinkLocked(r);
1014 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
1015 }
1016
1017 @Test
1018 public void testA11yQuietUpdate() throws Exception {
1019 NotificationRecord r = getQuietNotification();
1020 mService.buzzBeepBlinkLocked(r);
1021 r.isUpdate = true;
1022 mService.buzzBeepBlinkLocked(r);
1023 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
1024 }
1025
Julia Reynolds54369232018-07-03 10:43:35 -04001026 @Test
1027 public void testLightsScreenOn() {
1028 mService.mScreenOn = true;
1029 NotificationRecord r = getLightsNotification();
1030 mService.buzzBeepBlinkLocked(r);
1031 verifyNeverLights();
1032 assertFalse(r.isInterruptive());
1033 }
1034
1035 @Test
1036 public void testLightsInCall() {
1037 mService.mInCall = true;
1038 NotificationRecord r = getLightsNotification();
1039 mService.buzzBeepBlinkLocked(r);
1040 verifyNeverLights();
1041 assertFalse(r.isInterruptive());
1042 }
1043
1044 @Test
1045 public void testLightsSilentUpdate() {
1046 NotificationRecord r = getLightsOnceNotification();
1047 mService.buzzBeepBlinkLocked(r);
1048 verifyLights();
1049 assertTrue(r.isInterruptive());
1050
1051 r = getLightsOnceNotification();
1052 r.isUpdate = true;
1053 mService.buzzBeepBlinkLocked(r);
1054 // checks that lights happened once, i.e. this new call didn't trigger them again
1055 verifyLights();
1056 assertFalse(r.isInterruptive());
1057 }
1058
1059 @Test
1060 public void testLightsUnimportant() {
1061 NotificationRecord r = getLightsNotification();
1062 r.setImportance(IMPORTANCE_LOW, "testing");
1063 mService.buzzBeepBlinkLocked(r);
1064 verifyNeverLights();
1065 assertFalse(r.isInterruptive());
1066 }
1067
1068 @Test
1069 public void testLightsNoLights() {
1070 NotificationRecord r = getQuietNotification();
1071 mService.buzzBeepBlinkLocked(r);
1072 verifyNeverLights();
1073 assertFalse(r.isInterruptive());
1074 }
1075
1076 @Test
1077 public void testLightsNoLightOnDevice() {
1078 mService.mHasLight = false;
1079 NotificationRecord r = getLightsNotification();
1080 mService.buzzBeepBlinkLocked(r);
1081 verifyNeverLights();
1082 assertFalse(r.isInterruptive());
1083 }
1084
1085 @Test
1086 public void testLightsLightsOffGlobally() {
1087 mService.mNotificationPulseEnabled = false;
1088 NotificationRecord r = getLightsNotification();
1089 mService.buzzBeepBlinkLocked(r);
1090 verifyNeverLights();
1091 assertFalse(r.isInterruptive());
1092 }
1093
1094 @Test
1095 public void testLightsDndIntercepted() {
1096 NotificationRecord r = getLightsNotification();
1097 r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS);
1098 mService.buzzBeepBlinkLocked(r);
1099 verifyNeverLights();
1100 assertFalse(r.isInterruptive());
1101 }
1102
1103 @Test
1104 public void testGroupAlertSummaryNoLightsChild() {
1105 NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
1106
1107 mService.buzzBeepBlinkLocked(child);
1108
1109 verifyNeverLights();
1110 assertFalse(child.isInterruptive());
1111 }
1112
1113 @Test
1114 public void testGroupAlertSummaryLightsSummary() {
1115 NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
1116 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
1117
1118 mService.buzzBeepBlinkLocked(summary);
1119
1120 verifyLights();
1121 // summaries should never count for interruptiveness counts
1122 assertFalse(summary.isInterruptive());
1123 }
1124
1125 @Test
1126 public void testGroupAlertSummaryLightsNonGroupChild() {
1127 NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_SUMMARY);
1128
1129 mService.buzzBeepBlinkLocked(nonGroup);
1130
1131 verifyLights();
1132 assertTrue(nonGroup.isInterruptive());
1133 }
1134
1135 @Test
1136 public void testGroupAlertChildNoLightsSummary() {
1137 NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
1138 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
1139
1140 mService.buzzBeepBlinkLocked(summary);
1141
1142 verifyNeverLights();
1143 assertFalse(summary.isInterruptive());
1144 }
1145
1146 @Test
1147 public void testGroupAlertChildLightsChild() {
1148 NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
1149
1150 mService.buzzBeepBlinkLocked(child);
1151
1152 verifyLights();
1153 assertTrue(child.isInterruptive());
1154 }
1155
1156 @Test
1157 public void testGroupAlertChildLightsNonGroupSummary() {
1158 NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_CHILDREN);
1159
1160 mService.buzzBeepBlinkLocked(nonGroup);
1161
1162 verifyLights();
1163 assertTrue(nonGroup.isInterruptive());
1164 }
1165
1166 @Test
1167 public void testGroupAlertAllLightsGroup() {
1168 NotificationRecord group = getLightsNotificationRecord("a", GROUP_ALERT_ALL);
1169
1170 mService.buzzBeepBlinkLocked(group);
1171
1172 verifyLights();
1173 assertTrue(group.isInterruptive());
1174 }
1175
Michael Wright71216972017-01-31 18:33:54 +00001176 static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
1177 private final int mRepeatIndex;
1178
1179 VibrateRepeatMatcher(int repeatIndex) {
1180 mRepeatIndex = repeatIndex;
1181 }
1182
1183 @Override
1184 public boolean matches(VibrationEffect actual) {
1185 if (actual instanceof VibrationEffect.Waveform &&
1186 ((VibrationEffect.Waveform) actual).getRepeatIndex() == mRepeatIndex) {
1187 return true;
1188 }
1189 // All non-waveform effects are essentially one shots.
1190 return mRepeatIndex == -1;
1191 }
1192
1193 @Override
1194 public String toString() {
1195 return "repeatIndex=" + mRepeatIndex;
1196 }
1197 }
Chris Wren93bb8b82016-03-29 14:35:05 -04001198}