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);
82 // Convenience functions for creating notification records
85 private NotificationRecord getNoisyOtherNotification() {
86 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
87 true /* noisy */, true /* buzzy*/);
90 private NotificationRecord getBeepyNotification() {
91 return getNotificationRecord(mId, false /* insistent */, false /* once */,
92 true /* noisy */, false /* buzzy*/);
95 private NotificationRecord getBeepyOnceNotification() {
96 return getNotificationRecord(mId, false /* insistent */, true /* once */,
97 true /* noisy */, false /* buzzy*/);
100 private NotificationRecord getQuietNotification() {
101 return getNotificationRecord(mId, false /* insistent */, false /* once */,
102 false /* noisy */, false /* buzzy*/);
105 private NotificationRecord getQuietOtherNotification() {
106 return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
107 false /* noisy */, false /* buzzy*/);
110 private NotificationRecord getQuietOnceNotification() {
111 return getNotificationRecord(mId, false /* insistent */, true /* once */,
112 false /* noisy */, false /* buzzy*/);
115 private NotificationRecord getInsistentBeepyNotification() {
116 return getNotificationRecord(mId, true /* insistent */, false /* once */,
117 true /* noisy */, false /* buzzy*/);
120 private NotificationRecord getBuzzyNotification() {
121 return getNotificationRecord(mId, false /* insistent */, false /* once */,
122 false /* noisy */, true /* buzzy*/);
125 private NotificationRecord getBuzzyOnceNotification() {
126 return getNotificationRecord(mId, false /* insistent */, true /* once */,
127 false /* noisy */, true /* buzzy*/);
130 private NotificationRecord getInsistentBuzzyNotification() {
131 return getNotificationRecord(mId, true /* insistent */, false /* once */,
132 false /* noisy */, true /* buzzy*/);
135 private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
136 boolean noisy, boolean buzzy) {
137 final Builder builder = new Builder(getContext())
138 .setContentTitle("foo")
139 .setSmallIcon(android.R.drawable.sym_def_app_icon)
140 .setPriority(Notification.PRIORITY_HIGH)
141 .setOnlyAlertOnce(once);
145 defaults |= Notification.DEFAULT_SOUND;
148 defaults |= Notification.DEFAULT_VIBRATE;
150 builder.setDefaults(defaults);
152 Notification n = builder.build();
154 n.flags |= Notification.FLAG_INSISTENT;
156 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid, mPid,
157 mScore, n, mUser, System.currentTimeMillis());
158 return new NotificationRecord(getContext(), sbn);
162 // Convenience functions for interacting with mocks
165 private void verifyNeverBeep() throws RemoteException {
166 verify(mRingtonePlayer, never()).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
167 anyBoolean(), (AudioAttributes) anyObject());
170 private void verifyBeep() throws RemoteException {
171 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
172 eq(true), (AudioAttributes) anyObject());
175 private void verifyBeepLooped() throws RemoteException {
176 verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
177 eq(false), (AudioAttributes) anyObject());
180 private void verifyNeverStopAudio() throws RemoteException {
181 verify(mRingtonePlayer, never()).stopAsync();
184 private void verifyStopAudio() throws RemoteException {
185 verify(mRingtonePlayer, times(1)).stopAsync();
188 private void verifyNeverVibrate() {
189 verify(mVibrator, never()).vibrate(anyInt(), anyString(), (long[]) anyObject(),
190 anyInt(), (AudioAttributes) anyObject());
193 private void verifyVibrate() {
194 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), (long[]) anyObject(),
195 eq(-1), (AudioAttributes) anyObject());
198 private void verifyVibrateLooped() {
199 verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), (long[]) anyObject(),
200 eq(0), (AudioAttributes) anyObject());
203 private void verifyStopVibrate() {
204 verify(mVibrator, times(1)).cancel();
207 private void verifyNeverStopVibrate() throws RemoteException {
208 verify(mVibrator, never()).cancel();
212 public void testBeep() throws Exception {
213 NotificationRecord r = getBeepyNotification();
215 mService.buzzBeepBlinkLocked(r);
218 verifyNeverVibrate();
226 public void testBeepInsistently() throws Exception {
227 NotificationRecord r = getInsistentBeepyNotification();
229 mService.buzzBeepBlinkLocked(r);
235 public void testNoInterruptionForMin() throws Exception {
236 NotificationRecord r = getBeepyNotification();
237 r.setImportance(Ranking.IMPORTANCE_MIN, "foo");
239 mService.buzzBeepBlinkLocked(r);
242 verifyNeverVibrate();
246 public void testNoInterruptionForIntercepted() throws Exception {
247 NotificationRecord r = getBeepyNotification();
248 r.setIntercepted(true);
250 mService.buzzBeepBlinkLocked(r);
253 verifyNeverVibrate();
257 public void testBeepTwice() throws Exception {
258 NotificationRecord r = getBeepyNotification();
260 // set up internal state
261 mService.buzzBeepBlinkLocked(r);
262 Mockito.reset(mRingtonePlayer);
264 // update should beep
266 mService.buzzBeepBlinkLocked(r);
271 public void testHonorAlertOnlyOnceForBeep() throws Exception {
272 NotificationRecord r = getBeepyNotification();
273 NotificationRecord s = getBeepyOnceNotification();
276 // set up internal state
277 mService.buzzBeepBlinkLocked(r);
278 Mockito.reset(mRingtonePlayer);
280 // update should not beep
281 mService.buzzBeepBlinkLocked(s);
286 public void testNoisyUpdateDoesNotCancelAudio() throws Exception {
287 NotificationRecord r = getBeepyNotification();
289 mService.buzzBeepBlinkLocked(r);
291 mService.buzzBeepBlinkLocked(r);
293 verifyNeverStopAudio();
297 public void testNoisyOnceUpdateDoesNotCancelAudio() throws Exception {
298 NotificationRecord r = getBeepyNotification();
299 NotificationRecord s = getBeepyOnceNotification();
302 mService.buzzBeepBlinkLocked(r);
303 mService.buzzBeepBlinkLocked(s);
305 verifyNeverStopAudio();
309 public void testQuietUpdateDoesNotCancelAudioFromOther() throws Exception {
310 NotificationRecord r = getBeepyNotification();
311 NotificationRecord s = getQuietNotification();
313 NotificationRecord other = getNoisyOtherNotification();
315 // set up internal state
316 mService.buzzBeepBlinkLocked(r);
317 mService.buzzBeepBlinkLocked(other); // this takes the audio stream
318 Mockito.reset(mRingtonePlayer);
320 // should not stop noise, since we no longer own it
321 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
322 verifyNeverStopAudio();
326 public void testQuietInterloperDoesNotCancelAudio() throws Exception {
327 NotificationRecord r = getBeepyNotification();
328 NotificationRecord other = getQuietOtherNotification();
330 // set up internal state
331 mService.buzzBeepBlinkLocked(r);
332 Mockito.reset(mRingtonePlayer);
334 // should not stop noise, since it does not own it
335 mService.buzzBeepBlinkLocked(other);
336 verifyNeverStopAudio();
340 public void testQuietUpdateCancelsAudio() throws Exception {
341 NotificationRecord r = getBeepyNotification();
342 NotificationRecord s = getQuietNotification();
345 // set up internal state
346 mService.buzzBeepBlinkLocked(r);
347 Mockito.reset(mRingtonePlayer);
349 // quiet update should stop making noise
350 mService.buzzBeepBlinkLocked(s);
355 public void testQuietOnceUpdateCancelsAudio() throws Exception {
356 NotificationRecord r = getBeepyNotification();
357 NotificationRecord s = getQuietOnceNotification();
360 // set up internal state
361 mService.buzzBeepBlinkLocked(r);
362 Mockito.reset(mRingtonePlayer);
364 // stop making noise - this is a weird corner case, but quiet should override once
365 mService.buzzBeepBlinkLocked(s);
370 public void testDemoteSoundToVibrate() throws Exception {
371 NotificationRecord r = getBeepyNotification();
373 // the phone is quiet
374 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
375 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
377 mService.buzzBeepBlinkLocked(r);
384 public void testDemotInsistenteSoundToVibrate() throws Exception {
385 NotificationRecord r = getInsistentBeepyNotification();
387 // the phone is quiet
388 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
389 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
391 mService.buzzBeepBlinkLocked(r);
393 verifyVibrateLooped();
397 public void testVibrate() throws Exception {
398 NotificationRecord r = getBuzzyNotification();
400 mService.buzzBeepBlinkLocked(r);
407 public void testInsistenteVibrate() throws Exception {
408 NotificationRecord r = getInsistentBuzzyNotification();
410 mService.buzzBeepBlinkLocked(r);
411 verifyVibrateLooped();
415 public void testVibratTwice() throws Exception {
416 NotificationRecord r = getBuzzyNotification();
418 // set up internal state
419 mService.buzzBeepBlinkLocked(r);
420 Mockito.reset(mVibrator);
422 // update should vibrate
424 mService.buzzBeepBlinkLocked(r);
429 public void testHonorAlertOnlyOnceForBuzz() throws Exception {
430 NotificationRecord r = getBuzzyNotification();
431 NotificationRecord s = getBuzzyOnceNotification();
434 // set up internal state
435 mService.buzzBeepBlinkLocked(r);
436 Mockito.reset(mVibrator);
438 // update should not beep
439 mService.buzzBeepBlinkLocked(s);
440 verifyNeverVibrate();
444 public void testNoisyUpdateDoesNotCancelVibrate() throws Exception {
445 NotificationRecord r = getBuzzyNotification();
447 mService.buzzBeepBlinkLocked(r);
449 mService.buzzBeepBlinkLocked(r);
451 verifyNeverStopVibrate();
455 public void testNoisyOnceUpdateDoesNotCancelVibrate() throws Exception {
456 NotificationRecord r = getBuzzyNotification();
457 NotificationRecord s = getBuzzyOnceNotification();
460 mService.buzzBeepBlinkLocked(r);
461 mService.buzzBeepBlinkLocked(s);
463 verifyNeverStopVibrate();
467 public void testQuietUpdateDoesNotCancelVibrateFromOther() throws Exception {
468 NotificationRecord r = getBuzzyNotification();
469 NotificationRecord s = getQuietNotification();
471 NotificationRecord other = getNoisyOtherNotification();
473 // set up internal state
474 mService.buzzBeepBlinkLocked(r);
475 mService.buzzBeepBlinkLocked(other); // this takes the vibrate stream
476 Mockito.reset(mVibrator);
478 // should not stop vibrate, since we no longer own it
479 mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
480 verifyNeverStopVibrate();
484 public void testQuietInterloperDoesNotCancelVibrate() throws Exception {
485 NotificationRecord r = getBuzzyNotification();
486 NotificationRecord other = getQuietOtherNotification();
488 // set up internal state
489 mService.buzzBeepBlinkLocked(r);
490 Mockito.reset(mVibrator);
492 // should not stop noise, since it does not own it
493 mService.buzzBeepBlinkLocked(other);
494 verifyNeverStopVibrate();
498 public void testQuietUpdateCancelsVibrate() throws Exception {
499 NotificationRecord r = getBuzzyNotification();
500 NotificationRecord s = getQuietNotification();
503 // set up internal state
504 mService.buzzBeepBlinkLocked(r);
506 // quiet update should stop making noise
507 mService.buzzBeepBlinkLocked(s);
512 public void testQuietOnceUpdateCancelsvibrate() throws Exception {
513 NotificationRecord r = getBuzzyNotification();
514 NotificationRecord s = getQuietOnceNotification();
517 // set up internal state
518 mService.buzzBeepBlinkLocked(r);
519 Mockito.reset(mVibrator);
521 // stop making noise - this is a weird corner case, but quiet should override once
522 mService.buzzBeepBlinkLocked(s);
527 public void testQuietUpdateCancelsDemotedVibrate() throws Exception {
528 NotificationRecord r = getBeepyNotification();
529 NotificationRecord s = getQuietNotification();
531 // the phone is quiet
532 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
533 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
535 mService.buzzBeepBlinkLocked(r);
537 // quiet update should stop making noise
538 mService.buzzBeepBlinkLocked(s);