[go: nahoru, domu]

blob: f1f708c486d9137e34b46c077510eb0cdfc9a2cf [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
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -040018import org.junit.Before;
19import org.junit.Test;
20import org.junit.runner.RunWith;
Chris Wren93bb8b82016-03-29 14:35:05 -040021
22import android.app.ActivityManager;
23import android.app.Notification;
24import android.app.Notification.Builder;
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -040025import android.content.Context;
Chris Wren93bb8b82016-03-29 14:35:05 -040026import android.media.AudioAttributes;
27import android.media.AudioManager;
28import android.net.Uri;
29import android.os.Handler;
30import android.os.RemoteException;
31import android.os.UserHandle;
32import android.os.Vibrator;
33import android.service.notification.NotificationListenerService.Ranking;
34import android.service.notification.StatusBarNotification;
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -040035import android.support.test.InstrumentationRegistry;
36import android.support.test.runner.AndroidJUnit4;
Chris Wren93bb8b82016-03-29 14:35:05 -040037import android.test.suitebuilder.annotation.SmallTest;
38
39import org.mockito.Mock;
40import org.mockito.Mockito;
41import org.mockito.MockitoAnnotations;
42
43import static org.mockito.Matchers.anyBoolean;
44import static org.mockito.Matchers.anyInt;
45import static org.mockito.Matchers.anyObject;
46import static org.mockito.Matchers.anyString;
47import static org.mockito.Matchers.eq;
48import static org.mockito.Mockito.never;
49import static org.mockito.Mockito.times;
50import static org.mockito.Mockito.verify;
51import static org.mockito.Mockito.when;
52
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -040053@SmallTest
54@RunWith(AndroidJUnit4.class)
55public class BuzzBeepBlinkTest {
Chris Wren93bb8b82016-03-29 14:35:05 -040056
57 @Mock AudioManager mAudioManager;
58 @Mock Vibrator mVibrator;
59 @Mock android.media.IRingtonePlayer mRingtonePlayer;
60 @Mock Handler mHandler;
61
62 private NotificationManagerService mService;
63 private String mPkg = "com.android.server.notification";
64 private int mId = 1001;
65 private int mOtherId = 1002;
66 private String mTag = null;
67 private int mUid = 1000;
68 private int mPid = 2000;
69 private int mScore = 10;
70 private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
71
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -040072 @Before
Chris Wren93bb8b82016-03-29 14:35:05 -040073 public void setUp() {
74 MockitoAnnotations.initMocks(this);
75
76 when(mAudioManager.isAudioFocusExclusive()).thenReturn(false);
77 when(mAudioManager.getRingtonePlayer()).thenReturn(mRingtonePlayer);
78 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
79 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
80
81 mService = new NotificationManagerService(getContext());
82 mService.setAudioManager(mAudioManager);
83 mService.setVibrator(mVibrator);
84 mService.setSystemReady(true);
85 mService.setHandler(mHandler);
Chris Wrend4054312016-06-24 17:07:40 -040086 mService.setSystemNotificationSound("beep!");
Chris Wren93bb8b82016-03-29 14:35:05 -040087 }
88
89 //
90 // Convenience functions for creating notification records
91 //
92
93 private NotificationRecord getNoisyOtherNotification() {
94 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
95 true /* noisy */, true /* buzzy*/);
96 }
97
98 private NotificationRecord getBeepyNotification() {
99 return getNotificationRecord(mId, false /* insistent */, false /* once */,
100 true /* noisy */, false /* buzzy*/);
101 }
102
103 private NotificationRecord getBeepyOnceNotification() {
104 return getNotificationRecord(mId, false /* insistent */, true /* once */,
105 true /* noisy */, false /* buzzy*/);
106 }
107
108 private NotificationRecord getQuietNotification() {
109 return getNotificationRecord(mId, false /* insistent */, false /* once */,
110 false /* noisy */, false /* buzzy*/);
111 }
112
113 private NotificationRecord getQuietOtherNotification() {
114 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
115 false /* noisy */, false /* buzzy*/);
116 }
117
118 private NotificationRecord getQuietOnceNotification() {
119 return getNotificationRecord(mId, false /* insistent */, true /* once */,
120 false /* noisy */, false /* buzzy*/);
121 }
122
123 private NotificationRecord getInsistentBeepyNotification() {
124 return getNotificationRecord(mId, true /* insistent */, false /* once */,
125 true /* noisy */, false /* buzzy*/);
126 }
127
128 private NotificationRecord getBuzzyNotification() {
129 return getNotificationRecord(mId, false /* insistent */, false /* once */,
130 false /* noisy */, true /* buzzy*/);
131 }
132
133 private NotificationRecord getBuzzyOnceNotification() {
134 return getNotificationRecord(mId, false /* insistent */, true /* once */,
135 false /* noisy */, true /* buzzy*/);
136 }
137
138 private NotificationRecord getInsistentBuzzyNotification() {
139 return getNotificationRecord(mId, true /* insistent */, false /* once */,
140 false /* noisy */, true /* buzzy*/);
141 }
142
143 private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
144 boolean noisy, boolean buzzy) {
145 final Builder builder = new Builder(getContext())
146 .setContentTitle("foo")
147 .setSmallIcon(android.R.drawable.sym_def_app_icon)
148 .setPriority(Notification.PRIORITY_HIGH)
149 .setOnlyAlertOnce(once);
150
151 int defaults = 0;
152 if (noisy) {
153 defaults |= Notification.DEFAULT_SOUND;
154 }
155 if (buzzy) {
156 defaults |= Notification.DEFAULT_VIBRATE;
157 }
158 builder.setDefaults(defaults);
159
160 Notification n = builder.build();
161 if (insistent) {
162 n.flags |= Notification.FLAG_INSISTENT;
163 }
164 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid, mPid,
165 mScore, n, mUser, System.currentTimeMillis());
166 return new NotificationRecord(getContext(), sbn);
167 }
168
169 //
170 // Convenience functions for interacting with mocks
171 //
172
173 private void verifyNeverBeep() throws RemoteException {
174 verify(mRingtonePlayer, never()).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
175 anyBoolean(), (AudioAttributes) anyObject());
176 }
177
178 private void verifyBeep() throws RemoteException {
179 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
180 eq(true), (AudioAttributes) anyObject());
181 }
182
183 private void verifyBeepLooped() throws RemoteException {
184 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
185 eq(false), (AudioAttributes) anyObject());
186 }
187
188 private void verifyNeverStopAudio() throws RemoteException {
189 verify(mRingtonePlayer, never()).stopAsync();
190 }
191
192 private void verifyStopAudio() throws RemoteException {
193 verify(mRingtonePlayer, times(1)).stopAsync();
194 }
195
196 private void verifyNeverVibrate() {
197 verify(mVibrator, never()).vibrate(anyInt(), anyString(), (long[]) anyObject(),
198 anyInt(), (AudioAttributes) anyObject());
199 }
200
201 private void verifyVibrate() {
202 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), (long[]) anyObject(),
203 eq(-1), (AudioAttributes) anyObject());
204 }
205
206 private void verifyVibrateLooped() {
207 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), (long[]) anyObject(),
208 eq(0), (AudioAttributes) anyObject());
209 }
210
211 private void verifyStopVibrate() {
212 verify(mVibrator, times(1)).cancel();
213 }
214
215 private void verifyNeverStopVibrate() throws RemoteException {
216 verify(mVibrator, never()).cancel();
217 }
218
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400219 private Context getContext() {
220 return InstrumentationRegistry.getTargetContext();
221 }
222
223 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400224 public void testBeep() throws Exception {
225 NotificationRecord r = getBeepyNotification();
226
227 mService.buzzBeepBlinkLocked(r);
228
229 verifyBeepLooped();
230 verifyNeverVibrate();
231 }
232
233 //
234 // Tests
235 //
236
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400237 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400238 public void testBeepInsistently() throws Exception {
239 NotificationRecord r = getInsistentBeepyNotification();
240
241 mService.buzzBeepBlinkLocked(r);
242
243 verifyBeep();
244 }
245
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400246 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400247 public void testNoInterruptionForMin() throws Exception {
248 NotificationRecord r = getBeepyNotification();
249 r.setImportance(Ranking.IMPORTANCE_MIN, "foo");
250
251 mService.buzzBeepBlinkLocked(r);
252
253 verifyNeverBeep();
254 verifyNeverVibrate();
255 }
256
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400257 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400258 public void testNoInterruptionForIntercepted() throws Exception {
259 NotificationRecord r = getBeepyNotification();
260 r.setIntercepted(true);
261
262 mService.buzzBeepBlinkLocked(r);
263
264 verifyNeverBeep();
265 verifyNeverVibrate();
266 }
267
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400268 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400269 public void testBeepTwice() throws Exception {
270 NotificationRecord r = getBeepyNotification();
271
272 // set up internal state
273 mService.buzzBeepBlinkLocked(r);
274 Mockito.reset(mRingtonePlayer);
275
276 // update should beep
277 r.isUpdate = true;
278 mService.buzzBeepBlinkLocked(r);
279 verifyBeepLooped();
280 }
281
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400282 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400283 public void testHonorAlertOnlyOnceForBeep() throws Exception {
284 NotificationRecord r = getBeepyNotification();
285 NotificationRecord s = getBeepyOnceNotification();
286 s.isUpdate = true;
287
288 // set up internal state
289 mService.buzzBeepBlinkLocked(r);
290 Mockito.reset(mRingtonePlayer);
291
292 // update should not beep
293 mService.buzzBeepBlinkLocked(s);
294 verifyNeverBeep();
295 }
296
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400297 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400298 public void testNoisyUpdateDoesNotCancelAudio() throws Exception {
299 NotificationRecord r = getBeepyNotification();
300
301 mService.buzzBeepBlinkLocked(r);
302 r.isUpdate = true;
303 mService.buzzBeepBlinkLocked(r);
304
305 verifyNeverStopAudio();
306 }
307
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400308 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400309 public void testNoisyOnceUpdateDoesNotCancelAudio() throws Exception {
310 NotificationRecord r = getBeepyNotification();
311 NotificationRecord s = getBeepyOnceNotification();
312 s.isUpdate = true;
313
314 mService.buzzBeepBlinkLocked(r);
315 mService.buzzBeepBlinkLocked(s);
316
317 verifyNeverStopAudio();
318 }
319
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400320 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400321 public void testQuietUpdateDoesNotCancelAudioFromOther() throws Exception {
322 NotificationRecord r = getBeepyNotification();
323 NotificationRecord s = getQuietNotification();
324 s.isUpdate = true;
325 NotificationRecord other = getNoisyOtherNotification();
326
327 // set up internal state
328 mService.buzzBeepBlinkLocked(r);
329 mService.buzzBeepBlinkLocked(other); // this takes the audio stream
330 Mockito.reset(mRingtonePlayer);
331
332 // should not stop noise, since we no longer own it
333 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
334 verifyNeverStopAudio();
335 }
336
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400337 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400338 public void testQuietInterloperDoesNotCancelAudio() throws Exception {
339 NotificationRecord r = getBeepyNotification();
340 NotificationRecord other = getQuietOtherNotification();
341
342 // set up internal state
343 mService.buzzBeepBlinkLocked(r);
344 Mockito.reset(mRingtonePlayer);
345
346 // should not stop noise, since it does not own it
347 mService.buzzBeepBlinkLocked(other);
348 verifyNeverStopAudio();
349 }
350
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400351 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400352 public void testQuietUpdateCancelsAudio() throws Exception {
353 NotificationRecord r = getBeepyNotification();
354 NotificationRecord s = getQuietNotification();
355 s.isUpdate = true;
356
357 // set up internal state
358 mService.buzzBeepBlinkLocked(r);
359 Mockito.reset(mRingtonePlayer);
360
361 // quiet update should stop making noise
362 mService.buzzBeepBlinkLocked(s);
363 verifyStopAudio();
364 }
365
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400366 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400367 public void testQuietOnceUpdateCancelsAudio() throws Exception {
368 NotificationRecord r = getBeepyNotification();
369 NotificationRecord s = getQuietOnceNotification();
370 s.isUpdate = true;
371
372 // set up internal state
373 mService.buzzBeepBlinkLocked(r);
374 Mockito.reset(mRingtonePlayer);
375
376 // stop making noise - this is a weird corner case, but quiet should override once
377 mService.buzzBeepBlinkLocked(s);
378 verifyStopAudio();
379 }
380
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400381 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400382 public void testDemoteSoundToVibrate() throws Exception {
383 NotificationRecord r = getBeepyNotification();
384
385 // the phone is quiet
386 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
387 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
388
389 mService.buzzBeepBlinkLocked(r);
390
391 verifyNeverBeep();
392 verifyVibrate();
393 }
394
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400395 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400396 public void testDemotInsistenteSoundToVibrate() throws Exception {
397 NotificationRecord r = getInsistentBeepyNotification();
398
399 // the phone is quiet
400 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
401 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
402
403 mService.buzzBeepBlinkLocked(r);
404
405 verifyVibrateLooped();
406 }
407
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400408 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400409 public void testVibrate() throws Exception {
410 NotificationRecord r = getBuzzyNotification();
411
412 mService.buzzBeepBlinkLocked(r);
413
414 verifyNeverBeep();
415 verifyVibrate();
416 }
417
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400418 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400419 public void testInsistenteVibrate() throws Exception {
420 NotificationRecord r = getInsistentBuzzyNotification();
421
422 mService.buzzBeepBlinkLocked(r);
423 verifyVibrateLooped();
424 }
425
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400426 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400427 public void testVibratTwice() throws Exception {
428 NotificationRecord r = getBuzzyNotification();
429
430 // set up internal state
431 mService.buzzBeepBlinkLocked(r);
432 Mockito.reset(mVibrator);
433
434 // update should vibrate
435 r.isUpdate = true;
436 mService.buzzBeepBlinkLocked(r);
437 verifyVibrate();
438 }
439
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400440 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400441 public void testHonorAlertOnlyOnceForBuzz() throws Exception {
442 NotificationRecord r = getBuzzyNotification();
443 NotificationRecord s = getBuzzyOnceNotification();
444 s.isUpdate = true;
445
446 // set up internal state
447 mService.buzzBeepBlinkLocked(r);
448 Mockito.reset(mVibrator);
449
450 // update should not beep
451 mService.buzzBeepBlinkLocked(s);
452 verifyNeverVibrate();
453 }
454
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400455 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400456 public void testNoisyUpdateDoesNotCancelVibrate() throws Exception {
457 NotificationRecord r = getBuzzyNotification();
458
459 mService.buzzBeepBlinkLocked(r);
460 r.isUpdate = true;
461 mService.buzzBeepBlinkLocked(r);
462
463 verifyNeverStopVibrate();
464 }
465
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400466 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400467 public void testNoisyOnceUpdateDoesNotCancelVibrate() throws Exception {
468 NotificationRecord r = getBuzzyNotification();
469 NotificationRecord s = getBuzzyOnceNotification();
470 s.isUpdate = true;
471
472 mService.buzzBeepBlinkLocked(r);
473 mService.buzzBeepBlinkLocked(s);
474
475 verifyNeverStopVibrate();
476 }
477
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400478 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400479 public void testQuietUpdateDoesNotCancelVibrateFromOther() throws Exception {
480 NotificationRecord r = getBuzzyNotification();
481 NotificationRecord s = getQuietNotification();
482 s.isUpdate = true;
483 NotificationRecord other = getNoisyOtherNotification();
484
485 // set up internal state
486 mService.buzzBeepBlinkLocked(r);
487 mService.buzzBeepBlinkLocked(other); // this takes the vibrate stream
488 Mockito.reset(mVibrator);
489
490 // should not stop vibrate, since we no longer own it
491 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
492 verifyNeverStopVibrate();
493 }
494
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400495 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400496 public void testQuietInterloperDoesNotCancelVibrate() throws Exception {
497 NotificationRecord r = getBuzzyNotification();
498 NotificationRecord other = getQuietOtherNotification();
499
500 // set up internal state
501 mService.buzzBeepBlinkLocked(r);
502 Mockito.reset(mVibrator);
503
504 // should not stop noise, since it does not own it
505 mService.buzzBeepBlinkLocked(other);
506 verifyNeverStopVibrate();
507 }
508
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400509 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400510 public void testQuietUpdateCancelsVibrate() throws Exception {
511 NotificationRecord r = getBuzzyNotification();
512 NotificationRecord s = getQuietNotification();
513 s.isUpdate = true;
514
515 // set up internal state
516 mService.buzzBeepBlinkLocked(r);
517
518 // quiet update should stop making noise
519 mService.buzzBeepBlinkLocked(s);
520 verifyStopVibrate();
521 }
522
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400523 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400524 public void testQuietOnceUpdateCancelsvibrate() throws Exception {
525 NotificationRecord r = getBuzzyNotification();
526 NotificationRecord s = getQuietOnceNotification();
527 s.isUpdate = true;
528
529 // set up internal state
530 mService.buzzBeepBlinkLocked(r);
531 Mockito.reset(mVibrator);
532
533 // stop making noise - this is a weird corner case, but quiet should override once
534 mService.buzzBeepBlinkLocked(s);
535 verifyStopVibrate();
536 }
537
Geoffrey Pitsch0ffe7552016-08-29 10:07:40 -0400538 @Test
Chris Wren93bb8b82016-03-29 14:35:05 -0400539 public void testQuietUpdateCancelsDemotedVibrate() throws Exception {
540 NotificationRecord r = getBeepyNotification();
541 NotificationRecord s = getQuietNotification();
542
543 // the phone is quiet
544 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
545 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
546
547 mService.buzzBeepBlinkLocked(r);
548
549 // quiet update should stop making noise
550 mService.buzzBeepBlinkLocked(s);
551 verifyStopVibrate();
552 }
553}