[go: nahoru, domu]

Rate limit notification sounds/vibrations

1 alert per second.

Bug: 36662487
Test: runtest systemui-notification
Change-Id: I2046ae17b9e89ac0a83e182b91422fd242bc7557
diff --git a/services/tests/notification/src/com/android/server/notification/AlertRateLimiterTest.java b/services/tests/notification/src/com/android/server/notification/AlertRateLimiterTest.java
new file mode 100644
index 0000000..5ed8210
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/AlertRateLimiterTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.notification;
+
+import static com.android.server.notification.AlertRateLimiter.ALLOWED_ALERT_INTERVAL;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AlertRateLimiterTest extends NotificationTestCase {
+
+    private long mTestStartTime;
+    private
+    AlertRateLimiter mLimiter;
+
+    @Before
+    public void setUp() {
+        mTestStartTime = 1225731600000L;
+        mLimiter = new AlertRateLimiter();
+    }
+
+    @Test
+    public void testFirstAlertAllowed() throws Exception {
+        assertFalse(mLimiter.isRateLimited(mTestStartTime));
+    }
+
+    @Test
+    public void testAllowedAfterSecond() throws Exception {
+        assertFalse(mLimiter.isRateLimited(mTestStartTime));
+        assertFalse(mLimiter.isRateLimited(mTestStartTime + ALLOWED_ALERT_INTERVAL));
+    }
+
+    @Test
+    public void testAllowedAfterSecondEvenWithBlockedEntries() throws Exception {
+        assertFalse(mLimiter.isRateLimited(mTestStartTime));
+        assertTrue(mLimiter.isRateLimited(mTestStartTime + ALLOWED_ALERT_INTERVAL - 1));
+        assertFalse(mLimiter.isRateLimited(mTestStartTime + ALLOWED_ALERT_INTERVAL));
+    }
+
+    @Test
+    public void testAllowedDisallowedBeforeSecond() throws Exception {
+        assertFalse(mLimiter.isRateLimited(mTestStartTime));
+        assertTrue(mLimiter.isRateLimited(mTestStartTime + ALLOWED_ALERT_INTERVAL - 1));
+    }
+
+    @Test
+    public void testDisallowedTimePast() throws Exception {
+        assertFalse(mLimiter.isRateLimited(mTestStartTime));
+        assertTrue(mLimiter.isRateLimited(mTestStartTime - ALLOWED_ALERT_INTERVAL));
+    }
+}
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index ae98274..807703b 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -23,6 +23,7 @@
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
 
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyObject;
@@ -76,6 +77,8 @@
     @Mock android.media.IRingtonePlayer mRingtonePlayer;
     @Mock Light mLight;
     @Mock Handler mHandler;
+    @Mock
+    NotificationUsageStats mUsageStats;
 
     private NotificationManagerService mService;
     private String mPkg = "com.android.server.notification";
@@ -115,6 +118,8 @@
         when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
 
+        when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
+
         mService = new NotificationManagerService(getContext());
         mService.setAudioManager(mAudioManager);
         mService.setVibrator(mVibrator);
@@ -123,6 +128,7 @@
         mService.setLights(mLight);
         mService.setScreenOn(false);
         mService.setFallbackVibrationPattern(FALLBACK_VIBRATION_PATTERN);
+        mService.setUsageStats(mUsageStats);
     }
 
     //
@@ -806,6 +812,39 @@
         verifyNeverBeep();
     }
 
+    @Test
+    public void testRepeatedSoundOverLimitMuted() throws Exception {
+        when(mUsageStats.isAlertRateLimited(any())).thenReturn(true);
+
+        NotificationRecord r = getBeepyNotification();
+
+        mService.buzzBeepBlinkLocked(r);
+        verifyNeverBeep();
+    }
+
+    @Test
+    public void testPostingSilentNotificationDoesNotAffectRateLimiting() throws Exception {
+        NotificationRecord r = getQuietNotification();
+        mService.buzzBeepBlinkLocked(r);
+
+        verify(mUsageStats, never()).isAlertRateLimited(any());
+    }
+
+    @Test
+    public void testCrossUserSoundMuted() throws Exception {
+        final Notification n = new Builder(getContext(), "test")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
+
+        int userId = mUser.getIdentifier() + 1;
+        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
+                mPid, n, UserHandle.of(userId), null, System.currentTimeMillis());
+        NotificationRecord r = new NotificationRecord(getContext(), sbn,
+                new NotificationChannel("test", "test", IMPORTANCE_HIGH));
+
+        mService.buzzBeepBlinkLocked(r);
+        verifyNeverBeep();
+    }
+
     static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
         private final int mRepeatIndex;
 
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index a356ae0..b603a02 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -50,6 +50,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.graphics.Color;
+import android.media.AudioManager;
 import android.os.Binder;
 import android.os.Process;
 import android.os.UserHandle;
@@ -103,6 +104,8 @@
     File mFile;
     @Mock
     private NotificationUsageStats mUsageStats;
+    @Mock
+    private AudioManager mAudioManager;
     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
             TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
     @Mock
@@ -153,6 +156,7 @@
                 .thenReturn(applicationInfo);
         final LightsManager mockLightsManager = mock(LightsManager.class);
         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
+        when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
         // Use this testable looper.
         mTestableLooper = TestableLooper.get(this);
 
@@ -174,6 +178,7 @@
                 throw e;
             }
         }
+        mNotificationManagerService.setAudioManager(mAudioManager);
 
         // Tests call directly into the Binder.
         mBinderService = mNotificationManagerService.getBinderService();