2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.android.server.notification;
19 import android.app.ActivityManager;
20 import android.app.Notification;
21 import android.app.Notification.Builder;
22 import android.media.AudioAttributes;
23 import android.media.AudioManager;
24 import android.net.Uri;
25 import android.os.Handler;
26 import android.os.RemoteException;
27 import android.os.UserHandle;
28 import android.os.Vibrator;
29 import android.service.notification.NotificationListenerService.Ranking;
30 import android.service.notification.StatusBarNotification;
31 import android.test.AndroidTestCase;
32 import android.test.suitebuilder.annotation.SmallTest;
34 import org.mockito.Mock;
35 import org.mockito.Mockito;
36 import org.mockito.MockitoAnnotations;
38 import static org.mockito.Matchers.anyBoolean;
39 import static org.mockito.Matchers.anyInt;
40 import static org.mockito.Matchers.anyObject;
41 import static org.mockito.Matchers.anyString;
42 import static org.mockito.Matchers.eq;
43 import static org.mockito.Mockito.never;
44 import static org.mockito.Mockito.times;
45 import static org.mockito.Mockito.verify;
46 import static org.mockito.Mockito.when;
48 public class BuzzBeepBlinkTest extends AndroidTestCase {
50 @Mock AudioManager mAudioManager;
51 @Mock Vibrator mVibrator;
52 @Mock android.media.IRingtonePlayer mRingtonePlayer;
53 @Mock Handler mHandler;
55 private NotificationManagerService mService;
56 private String mPkg = "com.android.server.notification";
57 private int mId = 1001;
58 private int mOtherId = 1002;
59 private String mTag = null;
60 private int mUid = 1000;
61 private int mPid = 2000;
62 private int mScore = 10;
63 private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
67 MockitoAnnotations.initMocks(this);
69 when(mAudioManager.isAudioFocusExclusive()).thenReturn(false);
70 when(mAudioManager.getRingtonePlayer()).thenReturn(mRingtonePlayer);
71 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
72 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
74 mService = new NotificationManagerService(getContext());
75 mService.setAudioManager(mAudioManager);
76 mService.setVibrator(mVibrator);
77 mService.setSystemReady(true);
78 mService.setHandler(mHandler);
79 mService.setSystemNotificationSound("beep!");
83 // Convenience functions for creating notification records
86 private NotificationRecord getNoisyOtherNotification() {
87 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
88 true /* noisy */, true /* buzzy*/);
91 private NotificationRecord getBeepyNotification() {
92 return getNotificationRecord(mId, false /* insistent */, false /* once */,
93 true /* noisy */, false /* buzzy*/);
96 private NotificationRecord getBeepyOnceNotification() {
97 return getNotificationRecord(mId, false /* insistent */, true /* once */,
98 true /* noisy */, false /* buzzy*/);
101 private NotificationRecord getQuietNotification() {
102 return getNotificationRecord(mId, false /* insistent */, false /* once */,
103 false /* noisy */, false /* buzzy*/);
106 private NotificationRecord getQuietOtherNotification() {
107 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
108 false /* noisy */, false /* buzzy*/);
111 private NotificationRecord getQuietOnceNotification() {
112 return getNotificationRecord(mId, false /* insistent */, true /* once */,
113 false /* noisy */, false /* buzzy*/);
116 private NotificationRecord getInsistentBeepyNotification() {
117 return getNotificationRecord(mId, true /* insistent */, false /* once */,
118 true /* noisy */, false /* buzzy*/);
121 private NotificationRecord getBuzzyNotification() {
122 return getNotificationRecord(mId, false /* insistent */, false /* once */,
123 false /* noisy */, true /* buzzy*/);
126 private NotificationRecord getBuzzyOnceNotification() {
127 return getNotificationRecord(mId, false /* insistent */, true /* once */,
128 false /* noisy */, true /* buzzy*/);
131 private NotificationRecord getInsistentBuzzyNotification() {
132 return getNotificationRecord(mId, true /* insistent */, false /* once */,
133 false /* noisy */, true /* buzzy*/);
136 private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
137 boolean noisy, boolean buzzy) {
138 final Builder builder = new Builder(getContext())
139 .setContentTitle("foo")
140 .setSmallIcon(android.R.drawable.sym_def_app_icon)
141 .setPriority(Notification.PRIORITY_HIGH)
142 .setOnlyAlertOnce(once);
146 defaults |= Notification.DEFAULT_SOUND;
149 defaults |= Notification.DEFAULT_VIBRATE;
151 builder.setDefaults(defaults);
153 Notification n = builder.build();
155 n.flags |= Notification.FLAG_INSISTENT;
157 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid, mPid,
158 mScore, n, mUser, System.currentTimeMillis());
159 return new NotificationRecord(getContext(), sbn);
163 // Convenience functions for interacting with mocks
166 private void verifyNeverBeep() throws RemoteException {
167 verify(mRingtonePlayer, never()).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
168 anyBoolean(), (AudioAttributes) anyObject());
171 private void verifyBeep() throws RemoteException {
172 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
173 eq(true), (AudioAttributes) anyObject());
176 private void verifyBeepLooped() throws RemoteException {
177 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
178 eq(false), (AudioAttributes) anyObject());
181 private void verifyNeverStopAudio() throws RemoteException {
182 verify(mRingtonePlayer, never()).stopAsync();
185 private void verifyStopAudio() throws RemoteException {
186 verify(mRingtonePlayer, times(1)).stopAsync();
189 private void verifyNeverVibrate() {
190 verify(mVibrator, never()).vibrate(anyInt(), anyString(), (long[]) anyObject(),
191 anyInt(), (AudioAttributes) anyObject());
194 private void verifyVibrate() {
195 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), (long[]) anyObject(),
196 eq(-1), (AudioAttributes) anyObject());
199 private void verifyVibrateLooped() {
200 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), (long[]) anyObject(),
201 eq(0), (AudioAttributes) anyObject());
204 private void verifyStopVibrate() {
205 verify(mVibrator, times(1)).cancel();
208 private void verifyNeverStopVibrate() throws RemoteException {
209 verify(mVibrator, never()).cancel();
213 public void testBeep() throws Exception {
214 NotificationRecord r = getBeepyNotification();
216 mService.buzzBeepBlinkLocked(r);
219 verifyNeverVibrate();
227 public void testBeepInsistently() throws Exception {
228 NotificationRecord r = getInsistentBeepyNotification();
230 mService.buzzBeepBlinkLocked(r);
236 public void testNoInterruptionForMin() throws Exception {
237 NotificationRecord r = getBeepyNotification();
238 r.setImportance(Ranking.IMPORTANCE_MIN, "foo");
240 mService.buzzBeepBlinkLocked(r);
243 verifyNeverVibrate();
247 public void testNoInterruptionForIntercepted() throws Exception {
248 NotificationRecord r = getBeepyNotification();
249 r.setIntercepted(true);
251 mService.buzzBeepBlinkLocked(r);
254 verifyNeverVibrate();
258 public void testBeepTwice() throws Exception {
259 NotificationRecord r = getBeepyNotification();
261 // set up internal state
262 mService.buzzBeepBlinkLocked(r);
263 Mockito.reset(mRingtonePlayer);
265 // update should beep
267 mService.buzzBeepBlinkLocked(r);
272 public void testHonorAlertOnlyOnceForBeep() throws Exception {
273 NotificationRecord r = getBeepyNotification();
274 NotificationRecord s = getBeepyOnceNotification();
277 // set up internal state
278 mService.buzzBeepBlinkLocked(r);
279 Mockito.reset(mRingtonePlayer);
281 // update should not beep
282 mService.buzzBeepBlinkLocked(s);
287 public void testNoisyUpdateDoesNotCancelAudio() throws Exception {
288 NotificationRecord r = getBeepyNotification();
290 mService.buzzBeepBlinkLocked(r);
292 mService.buzzBeepBlinkLocked(r);
294 verifyNeverStopAudio();
298 public void testNoisyOnceUpdateDoesNotCancelAudio() throws Exception {
299 NotificationRecord r = getBeepyNotification();
300 NotificationRecord s = getBeepyOnceNotification();
303 mService.buzzBeepBlinkLocked(r);
304 mService.buzzBeepBlinkLocked(s);
306 verifyNeverStopAudio();
310 public void testQuietUpdateDoesNotCancelAudioFromOther() throws Exception {
311 NotificationRecord r = getBeepyNotification();
312 NotificationRecord s = getQuietNotification();
314 NotificationRecord other = getNoisyOtherNotification();
316 // set up internal state
317 mService.buzzBeepBlinkLocked(r);
318 mService.buzzBeepBlinkLocked(other); // this takes the audio stream
319 Mockito.reset(mRingtonePlayer);
321 // should not stop noise, since we no longer own it
322 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
323 verifyNeverStopAudio();
327 public void testQuietInterloperDoesNotCancelAudio() throws Exception {
328 NotificationRecord r = getBeepyNotification();
329 NotificationRecord other = getQuietOtherNotification();
331 // set up internal state
332 mService.buzzBeepBlinkLocked(r);
333 Mockito.reset(mRingtonePlayer);
335 // should not stop noise, since it does not own it
336 mService.buzzBeepBlinkLocked(other);
337 verifyNeverStopAudio();
341 public void testQuietUpdateCancelsAudio() throws Exception {
342 NotificationRecord r = getBeepyNotification();
343 NotificationRecord s = getQuietNotification();
346 // set up internal state
347 mService.buzzBeepBlinkLocked(r);
348 Mockito.reset(mRingtonePlayer);
350 // quiet update should stop making noise
351 mService.buzzBeepBlinkLocked(s);
356 public void testQuietOnceUpdateCancelsAudio() throws Exception {
357 NotificationRecord r = getBeepyNotification();
358 NotificationRecord s = getQuietOnceNotification();
361 // set up internal state
362 mService.buzzBeepBlinkLocked(r);
363 Mockito.reset(mRingtonePlayer);
365 // stop making noise - this is a weird corner case, but quiet should override once
366 mService.buzzBeepBlinkLocked(s);
371 public void testDemoteSoundToVibrate() throws Exception {
372 NotificationRecord r = getBeepyNotification();
374 // the phone is quiet
375 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
376 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
378 mService.buzzBeepBlinkLocked(r);
385 public void testDemotInsistenteSoundToVibrate() throws Exception {
386 NotificationRecord r = getInsistentBeepyNotification();
388 // the phone is quiet
389 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
390 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
392 mService.buzzBeepBlinkLocked(r);
394 verifyVibrateLooped();
398 public void testVibrate() throws Exception {
399 NotificationRecord r = getBuzzyNotification();
401 mService.buzzBeepBlinkLocked(r);
408 public void testInsistenteVibrate() throws Exception {
409 NotificationRecord r = getInsistentBuzzyNotification();
411 mService.buzzBeepBlinkLocked(r);
412 verifyVibrateLooped();
416 public void testVibratTwice() throws Exception {
417 NotificationRecord r = getBuzzyNotification();
419 // set up internal state
420 mService.buzzBeepBlinkLocked(r);
421 Mockito.reset(mVibrator);
423 // update should vibrate
425 mService.buzzBeepBlinkLocked(r);
430 public void testHonorAlertOnlyOnceForBuzz() throws Exception {
431 NotificationRecord r = getBuzzyNotification();
432 NotificationRecord s = getBuzzyOnceNotification();
435 // set up internal state
436 mService.buzzBeepBlinkLocked(r);
437 Mockito.reset(mVibrator);
439 // update should not beep
440 mService.buzzBeepBlinkLocked(s);
441 verifyNeverVibrate();
445 public void testNoisyUpdateDoesNotCancelVibrate() throws Exception {
446 NotificationRecord r = getBuzzyNotification();
448 mService.buzzBeepBlinkLocked(r);
450 mService.buzzBeepBlinkLocked(r);
452 verifyNeverStopVibrate();
456 public void testNoisyOnceUpdateDoesNotCancelVibrate() throws Exception {
457 NotificationRecord r = getBuzzyNotification();
458 NotificationRecord s = getBuzzyOnceNotification();
461 mService.buzzBeepBlinkLocked(r);
462 mService.buzzBeepBlinkLocked(s);
464 verifyNeverStopVibrate();
468 public void testQuietUpdateDoesNotCancelVibrateFromOther() throws Exception {
469 NotificationRecord r = getBuzzyNotification();
470 NotificationRecord s = getQuietNotification();
472 NotificationRecord other = getNoisyOtherNotification();
474 // set up internal state
475 mService.buzzBeepBlinkLocked(r);
476 mService.buzzBeepBlinkLocked(other); // this takes the vibrate stream
477 Mockito.reset(mVibrator);
479 // should not stop vibrate, since we no longer own it
480 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
481 verifyNeverStopVibrate();
485 public void testQuietInterloperDoesNotCancelVibrate() throws Exception {
486 NotificationRecord r = getBuzzyNotification();
487 NotificationRecord other = getQuietOtherNotification();
489 // set up internal state
490 mService.buzzBeepBlinkLocked(r);
491 Mockito.reset(mVibrator);
493 // should not stop noise, since it does not own it
494 mService.buzzBeepBlinkLocked(other);
495 verifyNeverStopVibrate();
499 public void testQuietUpdateCancelsVibrate() throws Exception {
500 NotificationRecord r = getBuzzyNotification();
501 NotificationRecord s = getQuietNotification();
504 // set up internal state
505 mService.buzzBeepBlinkLocked(r);
507 // quiet update should stop making noise
508 mService.buzzBeepBlinkLocked(s);
513 public void testQuietOnceUpdateCancelsvibrate() throws Exception {
514 NotificationRecord r = getBuzzyNotification();
515 NotificationRecord s = getQuietOnceNotification();
518 // set up internal state
519 mService.buzzBeepBlinkLocked(r);
520 Mockito.reset(mVibrator);
522 // stop making noise - this is a weird corner case, but quiet should override once
523 mService.buzzBeepBlinkLocked(s);
528 public void testQuietUpdateCancelsDemotedVibrate() throws Exception {
529 NotificationRecord r = getBeepyNotification();
530 NotificationRecord s = getQuietNotification();
532 // the phone is quiet
533 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
534 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
536 mService.buzzBeepBlinkLocked(r);
538 // quiet update should stop making noise
539 mService.buzzBeepBlinkLocked(s);