blob: 7b2684f7333ed1cbb6605dcaa4c07804d782d955 [file] [log] [blame]
Chris Wren93bb8b82016-03-29 14:35:05 -04001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.server.notification;
17
Julia Reynoldsa79c3712017-04-21 10:29:57 -040018import static android.app.Notification.GROUP_ALERT_ALL;
19import static android.app.Notification.GROUP_ALERT_CHILDREN;
20import static android.app.Notification.GROUP_ALERT_SUMMARY;
Julia Reynoldsca80d162017-04-23 12:39:32 -040021import static android.app.NotificationManager.IMPORTANCE_HIGH;
Julia Reynolds54369232018-07-03 10:43:35 -040022import static android.app.NotificationManager.IMPORTANCE_LOW;
Julia Reynolds94187562017-10-10 13:58:49 -040023import static android.app.NotificationManager.IMPORTANCE_MIN;
Julia Reynolds54369232018-07-03 10:43:35 -040024import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
Julia Reynoldsca80d162017-04-23 12:39:32 -040025
Julia Reynolds1fac86e2018-03-07 08:30:37 -050026import static junit.framework.Assert.assertFalse;
Julia Reynolds0c299d42016-11-15 14:37:04 -050027import static junit.framework.Assert.assertNull;
28import static junit.framework.Assert.assertTrue;
29
Julia Reynolds76c096d2017-06-19 08:16:04 -040030import static org.mockito.Matchers.any;
Chris Wren93bb8b82016-03-29 14:35:05 -040031import static org.mockito.Matchers.anyBoolean;
32import static org.mockito.Matchers.anyInt;
33import static org.mockito.Matchers.anyObject;
34import static org.mockito.Matchers.anyString;
Michael Wright71216972017-01-31 18:33:54 +000035import static org.mockito.Matchers.argThat;
Chris Wren93bb8b82016-03-29 14:35:05 -040036import static org.mockito.Matchers.eq;
37import static org.mockito.Mockito.never;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070038import static org.mockito.Mockito.spy;
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -070039import static org.mockito.Mockito.timeout;
Chris Wren93bb8b82016-03-29 14:35:05 -040040import static org.mockito.Mockito.times;
41import static org.mockito.Mockito.verify;
42import static org.mockito.Mockito.when;
43
Tony Mantlerab55f0f2017-06-16 10:50:00 -070044import android.app.ActivityManager;
45import android.app.Notification;
46import android.app.Notification.Builder;
47import android.app.NotificationChannel;
48import android.app.NotificationManager;
49import android.content.Context;
50import android.content.pm.PackageManager;
51import android.graphics.Color;
52import android.media.AudioAttributes;
53import android.media.AudioManager;
54import android.net.Uri;
55import android.os.Handler;
56import android.os.RemoteException;
57import android.os.UserHandle;
58import android.os.VibrationEffect;
59import android.os.Vibrator;
60import android.provider.Settings;
61import android.service.notification.StatusBarNotification;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070062import android.test.suitebuilder.annotation.SmallTest;
Julia Reynolds94187562017-10-10 13:58:49 -040063import android.view.accessibility.AccessibilityEvent;
64import android.view.accessibility.AccessibilityManager;
65import android.view.accessibility.IAccessibilityManager;
66import android.view.accessibility.IAccessibilityManagerClient;
Tony Mantlerab55f0f2017-06-16 10:50:00 -070067
Brett Chabot8091d9e2019-02-26 14:52:33 -080068import androidx.test.runner.AndroidJUnit4;
69
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)
116 .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
117 .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 Reynoldsb5e44b72016-08-16 15:00:25 -0400234 private NotificationRecord getCustomLightsNotification() {
235 return getNotificationRecord(mId, false /* insistent */, true /* once */,
236 false /* noisy */, true /* buzzy*/, true /* lights */,
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400237 true /* defaultVibration */, true /* defaultSound */, false /* defaultLights */,
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700238 null, 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
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400348 private void verifyCustomBeep() throws RemoteException {
349 verify(mRingtonePlayer, times(1)).playAsync(eq(CUSTOM_SOUND), (UserHandle) anyObject(),
350 eq(false), (AudioAttributes) anyObject());
351 }
352
Chris Wren93bb8b82016-03-29 14:35:05 -0400353 private void verifyNeverStopAudio() throws RemoteException {
354 verify(mRingtonePlayer, never()).stopAsync();
355 }
356
357 private void verifyStopAudio() throws RemoteException {
358 verify(mRingtonePlayer, times(1)).stopAsync();
359 }
360
361 private void verifyNeverVibrate() {
Michael Wright71216972017-01-31 18:33:54 +0000362 verify(mVibrator, never()).vibrate(anyInt(), anyString(), (VibrationEffect) anyObject(),
363 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400364 }
365
366 private void verifyVibrate() {
Michael Wright71216972017-01-31 18:33:54 +0000367 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateOnceMatcher),
368 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400369 }
370
371 private void verifyVibrateLooped() {
Michael Wright71216972017-01-31 18:33:54 +0000372 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateLoopMatcher),
373 (AudioAttributes) anyObject());
Chris Wren93bb8b82016-03-29 14:35:05 -0400374 }
375
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700376 private void verifyDelayedVibrateLooped() {
377 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
378 argThat(mVibrateLoopMatcher), (AudioAttributes) anyObject());
379 }
380
Chris Wren93bb8b82016-03-29 14:35:05 -0400381 private void verifyStopVibrate() {
382 verify(mVibrator, times(1)).cancel();
383 }
384
385 private void verifyNeverStopVibrate() throws RemoteException {
386 verify(mVibrator, never()).cancel();
387 }
388
Julia Reynolds54369232018-07-03 10:43:35 -0400389 private void verifyNeverLights() {
390 verify(mLight, never()).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
391 }
392
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400393 private void verifyLights() {
Julia Reynolds033a4122017-01-31 16:50:38 -0500394 verify(mLight, times(1)).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400395 }
396
397 private void verifyCustomLights() {
Julia Reynolds033a4122017-01-31 16:50:38 -0500398 verify(mLight, times(1)).setFlashing(
399 eq(CUSTOM_LIGHT_COLOR), anyInt(), eq(CUSTOM_LIGHT_ON), eq(CUSTOM_LIGHT_OFF));
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400400 }
401
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400402 //
403 // Tests
404 //
405
406 @Test
407 public void testLights() throws Exception {
408 NotificationRecord r = getLightsNotification();
409 r.setImportance(NotificationManager.IMPORTANCE_DEFAULT, "for testing");
410
411 mService.buzzBeepBlinkLocked(r);
412
413 verifyLights();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500414 assertTrue(r.isInterruptive());
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400415 }
416
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400417 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400418 public void testBeep() throws Exception {
419 NotificationRecord r = getBeepyNotification();
420
421 mService.buzzBeepBlinkLocked(r);
422
423 verifyBeepLooped();
424 verifyNeverVibrate();
Julia Reynolds94187562017-10-10 13:58:49 -0400425 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500426 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400427 }
428
Julia Reynoldsb5e44b72016-08-16 15:00:25 -0400429 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400430 public void testBeepInsistently() throws Exception {
431 NotificationRecord r = getInsistentBeepyNotification();
432
433 mService.buzzBeepBlinkLocked(r);
434
435 verifyBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500436 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400437 }
438
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400439 @Test
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700440 public void testNoLeanbackBeep() throws Exception {
441 NotificationRecord r = getInsistentBeepyLeanbackNotification();
442
443 mService.buzzBeepBlinkLocked(r);
444
445 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500446 assertFalse(r.isInterruptive());
Tony Mantlerab55f0f2017-06-16 10:50:00 -0700447 }
448
449 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400450 public void testNoInterruptionForMin() throws Exception {
451 NotificationRecord r = getBeepyNotification();
Julia Reynolds85769912016-10-25 09:08:57 -0400452 r.setImportance(NotificationManager.IMPORTANCE_MIN, "foo");
Chris Wren93bb8b82016-03-29 14:35:05 -0400453
454 mService.buzzBeepBlinkLocked(r);
455
456 verifyNeverBeep();
457 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500458 assertFalse(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400459 }
460
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400461 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400462 public void testNoInterruptionForIntercepted() throws Exception {
463 NotificationRecord r = getBeepyNotification();
464 r.setIntercepted(true);
465
466 mService.buzzBeepBlinkLocked(r);
467
468 verifyNeverBeep();
469 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500470 assertFalse(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400471 }
472
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400473 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400474 public void testBeepTwice() throws Exception {
475 NotificationRecord r = getBeepyNotification();
476
477 // set up internal state
478 mService.buzzBeepBlinkLocked(r);
479 Mockito.reset(mRingtonePlayer);
480
481 // update should beep
482 r.isUpdate = true;
483 mService.buzzBeepBlinkLocked(r);
484 verifyBeepLooped();
Julia Reynolds94187562017-10-10 13:58:49 -0400485 verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500486 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400487 }
488
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400489 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400490 public void testHonorAlertOnlyOnceForBeep() throws Exception {
491 NotificationRecord r = getBeepyNotification();
492 NotificationRecord s = getBeepyOnceNotification();
493 s.isUpdate = true;
494
495 // set up internal state
496 mService.buzzBeepBlinkLocked(r);
497 Mockito.reset(mRingtonePlayer);
498
499 // update should not beep
500 mService.buzzBeepBlinkLocked(s);
501 verifyNeverBeep();
Julia Reynolds94187562017-10-10 13:58:49 -0400502 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
Chris Wren93bb8b82016-03-29 14:35:05 -0400503 }
504
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400505 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400506 public void testNoisyUpdateDoesNotCancelAudio() throws Exception {
507 NotificationRecord r = getBeepyNotification();
508
509 mService.buzzBeepBlinkLocked(r);
510 r.isUpdate = true;
511 mService.buzzBeepBlinkLocked(r);
512
513 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500514 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400515 }
516
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400517 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400518 public void testNoisyOnceUpdateDoesNotCancelAudio() throws Exception {
519 NotificationRecord r = getBeepyNotification();
520 NotificationRecord s = getBeepyOnceNotification();
521 s.isUpdate = true;
522
523 mService.buzzBeepBlinkLocked(r);
524 mService.buzzBeepBlinkLocked(s);
525
526 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500527 assertTrue(r.isInterruptive());
528 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400529 }
530
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400531 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400532 public void testQuietUpdateDoesNotCancelAudioFromOther() throws Exception {
533 NotificationRecord r = getBeepyNotification();
534 NotificationRecord s = getQuietNotification();
535 s.isUpdate = true;
536 NotificationRecord other = getNoisyOtherNotification();
537
538 // set up internal state
539 mService.buzzBeepBlinkLocked(r);
540 mService.buzzBeepBlinkLocked(other); // this takes the audio stream
541 Mockito.reset(mRingtonePlayer);
542
543 // should not stop noise, since we no longer own it
544 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
545 verifyNeverStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500546 assertTrue(other.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400547 }
548
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400549 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400550 public void testQuietInterloperDoesNotCancelAudio() throws Exception {
551 NotificationRecord r = getBeepyNotification();
552 NotificationRecord other = getQuietOtherNotification();
553
554 // set up internal state
555 mService.buzzBeepBlinkLocked(r);
556 Mockito.reset(mRingtonePlayer);
557
558 // should not stop noise, since it does not own it
559 mService.buzzBeepBlinkLocked(other);
560 verifyNeverStopAudio();
561 }
562
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400563 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400564 public void testQuietUpdateCancelsAudio() throws Exception {
565 NotificationRecord r = getBeepyNotification();
566 NotificationRecord s = getQuietNotification();
567 s.isUpdate = true;
568
569 // set up internal state
570 mService.buzzBeepBlinkLocked(r);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500571 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400572 Mockito.reset(mRingtonePlayer);
573
574 // quiet update should stop making noise
575 mService.buzzBeepBlinkLocked(s);
576 verifyStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500577 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400578 }
579
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400580 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400581 public void testQuietOnceUpdateCancelsAudio() throws Exception {
582 NotificationRecord r = getBeepyNotification();
583 NotificationRecord s = getQuietOnceNotification();
584 s.isUpdate = true;
585
586 // set up internal state
587 mService.buzzBeepBlinkLocked(r);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500588 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400589 Mockito.reset(mRingtonePlayer);
590
591 // stop making noise - this is a weird corner case, but quiet should override once
592 mService.buzzBeepBlinkLocked(s);
593 verifyStopAudio();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500594 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400595 }
596
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400597 @Test
Beverly5d463b62017-07-26 14:13:40 -0400598 public void testInCallNotification() throws Exception {
599 NotificationRecord r = getBeepyNotification();
600
601 // set up internal state
602 mService.buzzBeepBlinkLocked(r);
603 Mockito.reset(mRingtonePlayer);
604
605 mService.mInCall = true;
606 mService.buzzBeepBlinkLocked(r);
607
Julia Reynolds94187562017-10-10 13:58:49 -0400608 verify(mService, times(1)).playInCallNotification();
Beverly5d463b62017-07-26 14:13:40 -0400609 verifyNeverBeep(); // doesn't play normal beep
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500610 assertTrue(r.isInterruptive());
Beverly5d463b62017-07-26 14:13:40 -0400611 }
612
613 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500614 public void testNoDemoteSoundToVibrateIfVibrateGiven() throws Exception {
615 NotificationRecord r = getBuzzyBeepyNotification();
616 assertTrue(r.getSound() != null);
Chris Wren93bb8b82016-03-29 14:35:05 -0400617
618 // the phone is quiet
Chris Wren93bb8b82016-03-29 14:35:05 -0400619 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
Julia Reynolds85896572017-09-20 12:54:52 -0400620 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
Chris Wren93bb8b82016-03-29 14:35:05 -0400621
622 mService.buzzBeepBlinkLocked(r);
623
Michael Wright71216972017-01-31 18:33:54 +0000624 VibrationEffect effect = VibrationEffect.createWaveform(r.getVibration(), -1);
625
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700626 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
627 eq(effect), (AudioAttributes) anyObject());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500628 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400629 }
630
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400631 @Test
Julia Reynolds85896572017-09-20 12:54:52 -0400632 public void testNoDemoteSoundToVibrateIfNonNotificationStream() throws Exception {
633 NotificationRecord r = getBeepyNotification();
634 assertTrue(r.getSound() != null);
635 assertNull(r.getVibration());
636
637 // the phone is quiet
638 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
639 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(1);
640
641 mService.buzzBeepBlinkLocked(r);
642
643 verifyNeverVibrate();
644 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500645 assertTrue(r.isInterruptive());
Julia Reynolds85896572017-09-20 12:54:52 -0400646 }
647
648 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500649 public void testDemoteSoundToVibrate() throws Exception {
650 NotificationRecord r = getBeepyNotification();
651 assertTrue(r.getSound() != null);
652 assertNull(r.getVibration());
653
654 // the phone is quiet
655 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
Julia Reynolds85896572017-09-20 12:54:52 -0400656 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500657
658 mService.buzzBeepBlinkLocked(r);
659
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700660 verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
661 eq(FALLBACK_VIBRATION), (AudioAttributes) anyObject());
Julia Reynolds619a69f2017-01-27 15:11:38 -0500662 verify(mRingtonePlayer, never()).playAsync
663 (anyObject(), anyObject(), anyBoolean(), anyObject());
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500664 assertTrue(r.isInterruptive());
Julia Reynolds0c299d42016-11-15 14:37:04 -0500665 }
666
667 @Test
668 public void testDemoteInsistentSoundToVibrate() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400669 NotificationRecord r = getInsistentBeepyNotification();
Julia Reynolds0c299d42016-11-15 14:37:04 -0500670 assertTrue(r.getSound() != null);
671 assertNull(r.getVibration());
Chris Wren93bb8b82016-03-29 14:35:05 -0400672
673 // the phone is quiet
674 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
675 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
676
677 mService.buzzBeepBlinkLocked(r);
678
Jean-Michel Triviea0eb5f2017-05-25 18:32:40 -0700679 verifyDelayedVibrateLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500680 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400681 }
682
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400683 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400684 public void testVibrate() throws Exception {
685 NotificationRecord r = getBuzzyNotification();
686
687 mService.buzzBeepBlinkLocked(r);
688
689 verifyNeverBeep();
690 verifyVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500691 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400692 }
693
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400694 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500695 public void testInsistentVibrate() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400696 NotificationRecord r = getInsistentBuzzyNotification();
697
698 mService.buzzBeepBlinkLocked(r);
699 verifyVibrateLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500700 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400701 }
702
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400703 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500704 public void testVibrateTwice() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400705 NotificationRecord r = getBuzzyNotification();
706
707 // set up internal state
708 mService.buzzBeepBlinkLocked(r);
709 Mockito.reset(mVibrator);
710
711 // update should vibrate
712 r.isUpdate = true;
713 mService.buzzBeepBlinkLocked(r);
714 verifyVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500715 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400716 }
717
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400718 @Test
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400719 public void testGroupAlertSummarySilenceChild() throws Exception {
720 NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
721
722 mService.buzzBeepBlinkLocked(child);
723
724 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500725 assertFalse(child.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400726 }
727
728 @Test
729 public void testGroupAlertSummaryNoSilenceSummary() throws Exception {
730 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
731 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
732
733 mService.buzzBeepBlinkLocked(summary);
734
735 verifyBeepLooped();
Julia Reynolds54369232018-07-03 10:43:35 -0400736 // summaries are never interruptive for notification counts
737 assertFalse(summary.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400738 }
739
740 @Test
741 public void testGroupAlertSummaryNoSilenceNonGroupChild() throws Exception {
742 NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_SUMMARY);
743
744 mService.buzzBeepBlinkLocked(nonGroup);
745
746 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500747 assertTrue(nonGroup.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400748 }
749
750 @Test
751 public void testGroupAlertChildSilenceSummary() throws Exception {
752 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
753 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
754
755 mService.buzzBeepBlinkLocked(summary);
756
757 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500758 assertFalse(summary.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400759 }
760
761 @Test
762 public void testGroupAlertChildNoSilenceChild() throws Exception {
763 NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
764
765 mService.buzzBeepBlinkLocked(child);
766
767 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500768 assertTrue(child.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400769 }
770
771 @Test
772 public void testGroupAlertChildNoSilenceNonGroupSummary() throws Exception {
773 NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_CHILDREN);
774
775 mService.buzzBeepBlinkLocked(nonGroup);
776
777 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500778 assertTrue(nonGroup.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400779 }
780
781 @Test
782 public void testGroupAlertAllNoSilenceGroup() throws Exception {
783 NotificationRecord group = getBeepyNotificationRecord("a", GROUP_ALERT_ALL);
784
785 mService.buzzBeepBlinkLocked(group);
786
787 verifyBeepLooped();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500788 assertTrue(group.isInterruptive());
Julia Reynoldsa79c3712017-04-21 10:29:57 -0400789 }
790
791 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400792 public void testHonorAlertOnlyOnceForBuzz() throws Exception {
793 NotificationRecord r = getBuzzyNotification();
794 NotificationRecord s = getBuzzyOnceNotification();
795 s.isUpdate = true;
796
797 // set up internal state
798 mService.buzzBeepBlinkLocked(r);
799 Mockito.reset(mVibrator);
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500800 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400801
802 // update should not beep
803 mService.buzzBeepBlinkLocked(s);
804 verifyNeverVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500805 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400806 }
807
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400808 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400809 public void testNoisyUpdateDoesNotCancelVibrate() throws Exception {
810 NotificationRecord r = getBuzzyNotification();
811
812 mService.buzzBeepBlinkLocked(r);
813 r.isUpdate = true;
814 mService.buzzBeepBlinkLocked(r);
815
816 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500817 assertTrue(r.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400818 }
819
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400820 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400821 public void testNoisyOnceUpdateDoesNotCancelVibrate() throws Exception {
822 NotificationRecord r = getBuzzyNotification();
823 NotificationRecord s = getBuzzyOnceNotification();
824 s.isUpdate = true;
825
826 mService.buzzBeepBlinkLocked(r);
827 mService.buzzBeepBlinkLocked(s);
828
829 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500830 assertTrue(r.isInterruptive());
831 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400832 }
833
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400834 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400835 public void testQuietUpdateDoesNotCancelVibrateFromOther() throws Exception {
836 NotificationRecord r = getBuzzyNotification();
837 NotificationRecord s = getQuietNotification();
838 s.isUpdate = true;
839 NotificationRecord other = getNoisyOtherNotification();
840
841 // set up internal state
842 mService.buzzBeepBlinkLocked(r);
843 mService.buzzBeepBlinkLocked(other); // this takes the vibrate stream
844 Mockito.reset(mVibrator);
845
846 // should not stop vibrate, since we no longer own it
847 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
848 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500849 assertTrue(r.isInterruptive());
850 assertTrue(other.isInterruptive());
851 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400852 }
853
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400854 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400855 public void testQuietInterloperDoesNotCancelVibrate() throws Exception {
856 NotificationRecord r = getBuzzyNotification();
857 NotificationRecord other = getQuietOtherNotification();
858
859 // set up internal state
860 mService.buzzBeepBlinkLocked(r);
861 Mockito.reset(mVibrator);
862
863 // should not stop noise, since it does not own it
864 mService.buzzBeepBlinkLocked(other);
865 verifyNeverStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500866 assertFalse(other.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400867 }
868
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400869 @Test
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500870 public void testQuietUpdateCancelsVibrate() {
Chris Wren93bb8b82016-03-29 14:35:05 -0400871 NotificationRecord r = getBuzzyNotification();
872 NotificationRecord s = getQuietNotification();
873 s.isUpdate = true;
874
875 // set up internal state
876 mService.buzzBeepBlinkLocked(r);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500877 verifyVibrate();
Chris Wren93bb8b82016-03-29 14:35:05 -0400878
879 // quiet update should stop making noise
880 mService.buzzBeepBlinkLocked(s);
881 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500882 assertTrue(r.isInterruptive());
883 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400884 }
885
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400886 @Test
Julia Reynolds0c299d42016-11-15 14:37:04 -0500887 public void testQuietOnceUpdateCancelVibrate() throws Exception {
Chris Wren93bb8b82016-03-29 14:35:05 -0400888 NotificationRecord r = getBuzzyNotification();
889 NotificationRecord s = getQuietOnceNotification();
890 s.isUpdate = true;
891
892 // set up internal state
893 mService.buzzBeepBlinkLocked(r);
Julia Reynolds0c299d42016-11-15 14:37:04 -0500894 verifyVibrate();
Chris Wren93bb8b82016-03-29 14:35:05 -0400895
896 // stop making noise - this is a weird corner case, but quiet should override once
897 mService.buzzBeepBlinkLocked(s);
898 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500899 assertTrue(r.isInterruptive());
900 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400901 }
902
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400903 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400904 public void testQuietUpdateCancelsDemotedVibrate() throws Exception {
905 NotificationRecord r = getBeepyNotification();
906 NotificationRecord s = getQuietNotification();
907
908 // the phone is quiet
909 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
910 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
911
912 mService.buzzBeepBlinkLocked(r);
913
914 // quiet update should stop making noise
915 mService.buzzBeepBlinkLocked(s);
916 verifyStopVibrate();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500917 assertTrue(r.isInterruptive());
918 assertFalse(s.isInterruptive());
Chris Wren93bb8b82016-03-29 14:35:05 -0400919 }
Michael Wright71216972017-01-31 18:33:54 +0000920
Julia Reynoldsca80d162017-04-23 12:39:32 -0400921 @Test
Seungho Lee0e97ae62018-10-31 21:49:09 +0900922 public void testCanceledNoisyNeverVibrate() throws Exception {
923 NotificationRecord r = getBuzzyBeepyNotification();
924
925 final int waitMs = mAudioManager.getFocusRampTimeMs(
926 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
927 r.getAudioAttributes());
928
929 mService.buzzBeepBlinkLocked(r);
930 mService.clearNotifications();
931
932 verifyNeverVibrate();
933 Thread.sleep(waitMs);
934 verifyNeverVibrate();
935 }
936
937 @Test
Julia Reynoldsca80d162017-04-23 12:39:32 -0400938 public void testEmptyUriSoundTreatedAsNoSound() throws Exception {
939 NotificationChannel channel = new NotificationChannel("test", "test", IMPORTANCE_HIGH);
940 channel.setSound(Uri.EMPTY, null);
941 final Notification n = new Builder(getContext(), "test")
942 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
943
944 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
945 mPid, n, mUser, null, System.currentTimeMillis());
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000946 NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
Julia Reynoldsca80d162017-04-23 12:39:32 -0400947 mService.addNotification(r);
948
949 mService.buzzBeepBlinkLocked(r);
Julia Reynoldsca80d162017-04-23 12:39:32 -0400950 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500951 assertFalse(r.isInterruptive());
Julia Reynoldsca80d162017-04-23 12:39:32 -0400952 }
953
Julia Reynolds76c096d2017-06-19 08:16:04 -0400954 @Test
955 public void testRepeatedSoundOverLimitMuted() throws Exception {
956 when(mUsageStats.isAlertRateLimited(any())).thenReturn(true);
957
958 NotificationRecord r = getBeepyNotification();
959
960 mService.buzzBeepBlinkLocked(r);
961 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -0500962 assertFalse(r.isInterruptive());
Julia Reynolds76c096d2017-06-19 08:16:04 -0400963 }
964
965 @Test
966 public void testPostingSilentNotificationDoesNotAffectRateLimiting() throws Exception {
967 NotificationRecord r = getQuietNotification();
968 mService.buzzBeepBlinkLocked(r);
969
970 verify(mUsageStats, never()).isAlertRateLimited(any());
971 }
972
973 @Test
Julia Reynolds65b85cf2017-07-20 09:19:20 -0400974 public void testPostingGroupSuppressedDoesNotAffectRateLimiting() throws Exception {
975 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
976 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
977
978 mService.buzzBeepBlinkLocked(summary);
Julia Reynolds65b85cf2017-07-20 09:19:20 -0400979 verify(mUsageStats, never()).isAlertRateLimited(any());
980 }
981
982 @Test
Julia Reynolds79dfdd62018-04-17 15:36:33 -0400983 public void testGroupSuppressionFailureDoesNotAffectRateLimiting() {
984 NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
985 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
986
987 mService.buzzBeepBlinkLocked(summary);
988 verify(mUsageStats, times(1)).isAlertRateLimited(any());
989 }
990
991 @Test
Julia Reynolds76c096d2017-06-19 08:16:04 -0400992 public void testCrossUserSoundMuted() throws Exception {
993 final Notification n = new Builder(getContext(), "test")
994 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
995
996 int userId = mUser.getIdentifier() + 1;
997 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
998 mPid, n, UserHandle.of(userId), null, System.currentTimeMillis());
999 NotificationRecord r = new NotificationRecord(getContext(), sbn,
1000 new NotificationChannel("test", "test", IMPORTANCE_HIGH));
1001
1002 mService.buzzBeepBlinkLocked(r);
1003 verifyNeverBeep();
Julia Reynolds1fac86e2018-03-07 08:30:37 -05001004 assertFalse(r.isInterruptive());
Julia Reynolds76c096d2017-06-19 08:16:04 -04001005 }
1006
Julia Reynolds94187562017-10-10 13:58:49 -04001007 @Test
1008 public void testA11yMinInitialPost() throws Exception {
1009 NotificationRecord r = getQuietNotification();
1010 r.setImportance(IMPORTANCE_MIN, "");
1011 mService.buzzBeepBlinkLocked(r);
1012 verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt());
1013 }
1014
1015 @Test
1016 public void testA11yQuietInitialPost() throws Exception {
1017 NotificationRecord r = getQuietNotification();
1018 mService.buzzBeepBlinkLocked(r);
1019 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
1020 }
1021
1022 @Test
1023 public void testA11yQuietUpdate() throws Exception {
1024 NotificationRecord r = getQuietNotification();
1025 mService.buzzBeepBlinkLocked(r);
1026 r.isUpdate = true;
1027 mService.buzzBeepBlinkLocked(r);
1028 verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
1029 }
1030
Julia Reynolds54369232018-07-03 10:43:35 -04001031 @Test
1032 public void testLightsScreenOn() {
1033 mService.mScreenOn = true;
1034 NotificationRecord r = getLightsNotification();
1035 mService.buzzBeepBlinkLocked(r);
1036 verifyNeverLights();
1037 assertFalse(r.isInterruptive());
1038 }
1039
1040 @Test
1041 public void testLightsInCall() {
1042 mService.mInCall = true;
1043 NotificationRecord r = getLightsNotification();
1044 mService.buzzBeepBlinkLocked(r);
1045 verifyNeverLights();
1046 assertFalse(r.isInterruptive());
1047 }
1048
1049 @Test
1050 public void testLightsSilentUpdate() {
1051 NotificationRecord r = getLightsOnceNotification();
1052 mService.buzzBeepBlinkLocked(r);
1053 verifyLights();
1054 assertTrue(r.isInterruptive());
1055
1056 r = getLightsOnceNotification();
1057 r.isUpdate = true;
1058 mService.buzzBeepBlinkLocked(r);
1059 // checks that lights happened once, i.e. this new call didn't trigger them again
1060 verifyLights();
1061 assertFalse(r.isInterruptive());
1062 }
1063
1064 @Test
1065 public void testLightsUnimportant() {
1066 NotificationRecord r = getLightsNotification();
1067 r.setImportance(IMPORTANCE_LOW, "testing");
1068 mService.buzzBeepBlinkLocked(r);
1069 verifyNeverLights();
1070 assertFalse(r.isInterruptive());
1071 }
1072
1073 @Test
1074 public void testLightsNoLights() {
1075 NotificationRecord r = getQuietNotification();
1076 mService.buzzBeepBlinkLocked(r);
1077 verifyNeverLights();
1078 assertFalse(r.isInterruptive());
1079 }
1080
1081 @Test
1082 public void testLightsNoLightOnDevice() {
1083 mService.mHasLight = false;
1084 NotificationRecord r = getLightsNotification();
1085 mService.buzzBeepBlinkLocked(r);
1086 verifyNeverLights();
1087 assertFalse(r.isInterruptive());
1088 }
1089
1090 @Test
1091 public void testLightsLightsOffGlobally() {
1092 mService.mNotificationPulseEnabled = false;
1093 NotificationRecord r = getLightsNotification();
1094 mService.buzzBeepBlinkLocked(r);
1095 verifyNeverLights();
1096 assertFalse(r.isInterruptive());
1097 }
1098
1099 @Test
1100 public void testLightsDndIntercepted() {
1101 NotificationRecord r = getLightsNotification();
1102 r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS);
1103 mService.buzzBeepBlinkLocked(r);
1104 verifyNeverLights();
1105 assertFalse(r.isInterruptive());
1106 }
1107
1108 @Test
1109 public void testGroupAlertSummaryNoLightsChild() {
1110 NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
1111
1112 mService.buzzBeepBlinkLocked(child);
1113
1114 verifyNeverLights();
1115 assertFalse(child.isInterruptive());
1116 }
1117
1118 @Test
1119 public void testGroupAlertSummaryLightsSummary() {
1120 NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
1121 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
1122
1123 mService.buzzBeepBlinkLocked(summary);
1124
1125 verifyLights();
1126 // summaries should never count for interruptiveness counts
1127 assertFalse(summary.isInterruptive());
1128 }
1129
1130 @Test
1131 public void testGroupAlertSummaryLightsNonGroupChild() {
1132 NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_SUMMARY);
1133
1134 mService.buzzBeepBlinkLocked(nonGroup);
1135
1136 verifyLights();
1137 assertTrue(nonGroup.isInterruptive());
1138 }
1139
1140 @Test
1141 public void testGroupAlertChildNoLightsSummary() {
1142 NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
1143 summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
1144
1145 mService.buzzBeepBlinkLocked(summary);
1146
1147 verifyNeverLights();
1148 assertFalse(summary.isInterruptive());
1149 }
1150
1151 @Test
1152 public void testGroupAlertChildLightsChild() {
1153 NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
1154
1155 mService.buzzBeepBlinkLocked(child);
1156
1157 verifyLights();
1158 assertTrue(child.isInterruptive());
1159 }
1160
1161 @Test
1162 public void testGroupAlertChildLightsNonGroupSummary() {
1163 NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_CHILDREN);
1164
1165 mService.buzzBeepBlinkLocked(nonGroup);
1166
1167 verifyLights();
1168 assertTrue(nonGroup.isInterruptive());
1169 }
1170
1171 @Test
1172 public void testGroupAlertAllLightsGroup() {
1173 NotificationRecord group = getLightsNotificationRecord("a", GROUP_ALERT_ALL);
1174
1175 mService.buzzBeepBlinkLocked(group);
1176
1177 verifyLights();
1178 assertTrue(group.isInterruptive());
1179 }
1180
Michael Wright71216972017-01-31 18:33:54 +00001181 static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
1182 private final int mRepeatIndex;
1183
1184 VibrateRepeatMatcher(int repeatIndex) {
1185 mRepeatIndex = repeatIndex;
1186 }
1187
1188 @Override
1189 public boolean matches(VibrationEffect actual) {
1190 if (actual instanceof VibrationEffect.Waveform &&
1191 ((VibrationEffect.Waveform) actual).getRepeatIndex() == mRepeatIndex) {
1192 return true;
1193 }
1194 // All non-waveform effects are essentially one shots.
1195 return mRepeatIndex == -1;
1196 }
1197
1198 @Override
1199 public String toString() {
1200 return "repeatIndex=" + mRepeatIndex;
1201 }
1202 }
Chris Wren93bb8b82016-03-29 14:35:05 -04001203}