Loading core/java/android/provider/Settings.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -10681,7 +10681,7 @@ public final class Settings { /** /** * The maximum allowed notification enqueue rate in Hertz. * The maximum allowed notification enqueue rate in Hertz. * * * Should be a float, and includes both posts and updates. * Should be a float, and includes updates only. * @hide * @hide */ */ public static final String MAX_NOTIFICATION_ENQUEUE_RATE = "max_notification_enqueue_rate"; public static final String MAX_NOTIFICATION_ENQUEUE_RATE = "max_notification_enqueue_rate"; Loading services/core/java/com/android/server/notification/AlertRateLimiter.java 0 → 100644 +35 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2017 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; /** * {@hide} */ public class AlertRateLimiter { static final long ALLOWED_ALERT_INTERVAL = 1000; private long mLastNotificationMillis = 0; boolean isRateLimited(long now) { final long millisSinceLast = now - mLastNotificationMillis; if (millisSinceLast < 0 || millisSinceLast < ALLOWED_ALERT_INTERVAL) { return true; } mLastNotificationMillis = now; return false; } } services/core/java/com/android/server/notification/NotificationManagerService.java +35 −20 Original line number Original line Diff line number Diff line Loading @@ -1120,6 +1120,11 @@ public class NotificationManagerService extends SystemService { mIsTelevision = isTelevision; mIsTelevision = isTelevision; } } @VisibleForTesting void setUsageStats(NotificationUsageStats us) { mUsageStats = us; } // TODO: Tests should call onStart instead once the methods above are removed. // TODO: Tests should call onStart instead once the methods above are removed. @VisibleForTesting @VisibleForTesting void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient, void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient, Loading Loading @@ -3838,18 +3843,6 @@ public class NotificationManagerService extends SystemService { // Should this notification make noise, vibe, or use the LED? // Should this notification make noise, vibe, or use the LED? final boolean aboveThreshold = final boolean aboveThreshold = record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT; record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT; final boolean canInterrupt = aboveThreshold && !record.isIntercepted(); if (DBG) Slog.v(TAG, "pkg=" + record.sbn.getPackageName() + " canInterrupt=" + canInterrupt + " intercept=" + record.isIntercepted() ); // If we're not supposed to beep, vibrate, etc. then don't. final String disableEffects = disableNotificationEffects(record); if (disableEffects != null) { ZenLog.traceDisableEffects(record, disableEffects); } // Remember if this notification already owns the notification channels. // Remember if this notification already owns the notification channels. boolean wasBeep = key != null && key.equals(mSoundNotificationKey); boolean wasBeep = key != null && key.equals(mSoundNotificationKey); Loading @@ -3858,20 +3851,16 @@ public class NotificationManagerService extends SystemService { boolean hasValidVibrate = false; boolean hasValidVibrate = false; boolean hasValidSound = false; boolean hasValidSound = false; if (isNotificationForCurrentUser(record)) { if (aboveThreshold && isNotificationForCurrentUser(record)) { // If the notification will appear in the status bar, it should send an accessibility // If the notification will appear in the status bar, it should send an accessibility // event // event if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN) { if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN) { sendAccessibilityEvent(notification, record.sbn.getPackageName()); sendAccessibilityEvent(notification, record.sbn.getPackageName()); } } if (mSystemReady && mAudioManager != null) { if (disableEffects == null && canInterrupt && mSystemReady && mAudioManager != null) { if (DBG) Slog.v(TAG, "Interrupting!"); Uri soundUri = record.getSound(); Uri soundUri = record.getSound(); hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri); hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri); long[] vibration = record.getVibration(); long[] vibration = record.getVibration(); // Demote sound to vibration if vibration missing & phone in vibration mode. // Demote sound to vibration if vibration missing & phone in vibration mode. if (vibration == null if (vibration == null Loading @@ -3882,7 +3871,10 @@ public class NotificationManagerService extends SystemService { } } hasValidVibrate = vibration != null; hasValidVibrate = vibration != null; if (!shouldMuteNotificationLocked(record)) { boolean hasAudibleAlert = hasValidSound || hasValidVibrate; if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) { if (DBG) Slog.v(TAG, "Interrupting!"); if (hasValidSound) { if (hasValidSound) { mSoundNotificationKey = key; mSoundNotificationKey = key; if (mInCall) { if (mInCall) { Loading Loading @@ -3939,14 +3931,37 @@ public class NotificationManagerService extends SystemService { @GuardedBy("mNotificationLock") @GuardedBy("mNotificationLock") boolean shouldMuteNotificationLocked(final NotificationRecord record) { boolean shouldMuteNotificationLocked(final NotificationRecord record) { // Suppressed because it's a silent update final Notification notification = record.getNotification(); final Notification notification = record.getNotification(); if(record.isUpdate if(record.isUpdate && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) { && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) { return true; return true; } } // Suppressed for being too recently noisy final String pkg = record.sbn.getPackageName(); if (mUsageStats.isAlertRateLimited(pkg)) { Slog.e(TAG, "Muting recently noisy " + record.getKey()); return true; } // muted by listener final String disableEffects = disableNotificationEffects(record); if (disableEffects != null) { ZenLog.traceDisableEffects(record, disableEffects); return true; } // suppressed due to DND if (record.isIntercepted()) { return true; } // Suppressed because another notification in its group handles alerting if (record.sbn.isGroup()) { if (record.sbn.isGroup()) { return notification.suppressAlertingDueToGrouping(); return notification.suppressAlertingDueToGrouping(); } } return false; return false; } } Loading services/core/java/com/android/server/notification/NotificationUsageStats.java +30 −0 Original line number Original line Diff line number Diff line Loading @@ -113,6 +113,18 @@ public class NotificationUsageStats { } } } } /** * Called when a notification wants to alert. */ public synchronized boolean isAlertRateLimited(String packageName) { AggregatedStats stats = getOrCreateAggregatedStatsLocked(packageName); if (stats != null) { return stats.isAlertRateLimited(); } else { return false; } } /** /** * Called when a notification is tentatively enqueued by an app, before rate checking. * Called when a notification is tentatively enqueued by an app, before rate checking. */ */ Loading Loading @@ -386,7 +398,9 @@ public class NotificationUsageStats { public ImportanceHistogram quietImportance; public ImportanceHistogram quietImportance; public ImportanceHistogram finalImportance; public ImportanceHistogram finalImportance; public RateEstimator enqueueRate; public RateEstimator enqueueRate; public AlertRateLimiter alertRate; public int numRateViolations; public int numRateViolations; public int numAlertViolations; public int numQuotaViolations; public int numQuotaViolations; public long mLastAccessTime; public long mLastAccessTime; Loading @@ -398,6 +412,7 @@ public class NotificationUsageStats { quietImportance = new ImportanceHistogram(context, "note_imp_quiet_"); quietImportance = new ImportanceHistogram(context, "note_imp_quiet_"); finalImportance = new ImportanceHistogram(context, "note_importance_"); finalImportance = new ImportanceHistogram(context, "note_importance_"); enqueueRate = new RateEstimator(); enqueueRate = new RateEstimator(); alertRate = new AlertRateLimiter(); } } public AggregatedStats getPrevious() { public AggregatedStats getPrevious() { Loading Loading @@ -510,6 +525,7 @@ public class NotificationUsageStats { maybeCount("note_sub_text", (numWithSubText - previous.numWithSubText)); maybeCount("note_sub_text", (numWithSubText - previous.numWithSubText)); maybeCount("note_info_text", (numWithInfoText - previous.numWithInfoText)); maybeCount("note_info_text", (numWithInfoText - previous.numWithInfoText)); maybeCount("note_over_rate", (numRateViolations - previous.numRateViolations)); maybeCount("note_over_rate", (numRateViolations - previous.numRateViolations)); maybeCount("note_over_alert_rate", (numAlertViolations - previous.numAlertViolations)); maybeCount("note_over_quota", (numQuotaViolations - previous.numQuotaViolations)); maybeCount("note_over_quota", (numQuotaViolations - previous.numQuotaViolations)); noisyImportance.maybeCount(previous.noisyImportance); noisyImportance.maybeCount(previous.noisyImportance); quietImportance.maybeCount(previous.quietImportance); quietImportance.maybeCount(previous.quietImportance); Loading Loading @@ -542,6 +558,7 @@ public class NotificationUsageStats { previous.numWithSubText = numWithSubText; previous.numWithSubText = numWithSubText; previous.numWithInfoText = numWithInfoText; previous.numWithInfoText = numWithInfoText; previous.numRateViolations = numRateViolations; previous.numRateViolations = numRateViolations; previous.numAlertViolations = numAlertViolations; previous.numQuotaViolations = numQuotaViolations; previous.numQuotaViolations = numQuotaViolations; noisyImportance.update(previous.noisyImportance); noisyImportance.update(previous.noisyImportance); quietImportance.update(previous.quietImportance); quietImportance.update(previous.quietImportance); Loading Loading @@ -576,6 +593,14 @@ public class NotificationUsageStats { enqueueRate.update(now); enqueueRate.update(now); } } public boolean isAlertRateLimited() { boolean limited = alertRate.isRateLimited(SystemClock.elapsedRealtime()); if (limited) { numAlertViolations++; } return limited; } private String toStringWithIndent(String indent) { private String toStringWithIndent(String indent) { StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder(); output.append(indent).append("AggregatedStats{\n"); output.append(indent).append("AggregatedStats{\n"); Loading Loading @@ -634,7 +659,11 @@ public class NotificationUsageStats { output.append("numWithSubText=").append(numWithSubText).append("\n"); output.append("numWithSubText=").append(numWithSubText).append("\n"); output.append(indentPlusTwo); output.append(indentPlusTwo); output.append("numWithInfoText=").append(numWithInfoText).append("\n"); output.append("numWithInfoText=").append(numWithInfoText).append("\n"); output.append(indentPlusTwo); output.append("numRateViolations=").append(numRateViolations).append("\n"); output.append("numRateViolations=").append(numRateViolations).append("\n"); output.append(indentPlusTwo); output.append("numAlertViolations=").append(numAlertViolations).append("\n"); output.append(indentPlusTwo); output.append("numQuotaViolations=").append(numQuotaViolations).append("\n"); output.append("numQuotaViolations=").append(numQuotaViolations).append("\n"); output.append(indentPlusTwo).append(noisyImportance.toString()).append("\n"); output.append(indentPlusTwo).append(noisyImportance.toString()).append("\n"); output.append(indentPlusTwo).append(quietImportance.toString()).append("\n"); output.append(indentPlusTwo).append(quietImportance.toString()).append("\n"); Loading Loading @@ -677,6 +706,7 @@ public class NotificationUsageStats { maybePut(dump, "numRateViolations", numRateViolations); maybePut(dump, "numRateViolations", numRateViolations); maybePut(dump, "numQuotaLViolations", numQuotaViolations); maybePut(dump, "numQuotaLViolations", numQuotaViolations); maybePut(dump, "notificationEnqueueRate", getEnqueueRate()); maybePut(dump, "notificationEnqueueRate", getEnqueueRate()); maybePut(dump, "numAlertViolations", numAlertViolations); noisyImportance.maybePut(dump, previous.noisyImportance); noisyImportance.maybePut(dump, previous.noisyImportance); quietImportance.maybePut(dump, previous.quietImportance); quietImportance.maybePut(dump, previous.quietImportance); finalImportance.maybePut(dump, previous.finalImportance); finalImportance.maybePut(dump, previous.finalImportance); Loading services/tests/notification/src/com/android/server/notification/AlertRateLimiterTest.java 0 → 100644 +72 −0 Original line number Original line Diff line number Diff line /* * 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)); } } Loading
core/java/android/provider/Settings.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -10681,7 +10681,7 @@ public final class Settings { /** /** * The maximum allowed notification enqueue rate in Hertz. * The maximum allowed notification enqueue rate in Hertz. * * * Should be a float, and includes both posts and updates. * Should be a float, and includes updates only. * @hide * @hide */ */ public static final String MAX_NOTIFICATION_ENQUEUE_RATE = "max_notification_enqueue_rate"; public static final String MAX_NOTIFICATION_ENQUEUE_RATE = "max_notification_enqueue_rate"; Loading
services/core/java/com/android/server/notification/AlertRateLimiter.java 0 → 100644 +35 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2017 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; /** * {@hide} */ public class AlertRateLimiter { static final long ALLOWED_ALERT_INTERVAL = 1000; private long mLastNotificationMillis = 0; boolean isRateLimited(long now) { final long millisSinceLast = now - mLastNotificationMillis; if (millisSinceLast < 0 || millisSinceLast < ALLOWED_ALERT_INTERVAL) { return true; } mLastNotificationMillis = now; return false; } }
services/core/java/com/android/server/notification/NotificationManagerService.java +35 −20 Original line number Original line Diff line number Diff line Loading @@ -1120,6 +1120,11 @@ public class NotificationManagerService extends SystemService { mIsTelevision = isTelevision; mIsTelevision = isTelevision; } } @VisibleForTesting void setUsageStats(NotificationUsageStats us) { mUsageStats = us; } // TODO: Tests should call onStart instead once the methods above are removed. // TODO: Tests should call onStart instead once the methods above are removed. @VisibleForTesting @VisibleForTesting void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient, void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient, Loading Loading @@ -3838,18 +3843,6 @@ public class NotificationManagerService extends SystemService { // Should this notification make noise, vibe, or use the LED? // Should this notification make noise, vibe, or use the LED? final boolean aboveThreshold = final boolean aboveThreshold = record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT; record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT; final boolean canInterrupt = aboveThreshold && !record.isIntercepted(); if (DBG) Slog.v(TAG, "pkg=" + record.sbn.getPackageName() + " canInterrupt=" + canInterrupt + " intercept=" + record.isIntercepted() ); // If we're not supposed to beep, vibrate, etc. then don't. final String disableEffects = disableNotificationEffects(record); if (disableEffects != null) { ZenLog.traceDisableEffects(record, disableEffects); } // Remember if this notification already owns the notification channels. // Remember if this notification already owns the notification channels. boolean wasBeep = key != null && key.equals(mSoundNotificationKey); boolean wasBeep = key != null && key.equals(mSoundNotificationKey); Loading @@ -3858,20 +3851,16 @@ public class NotificationManagerService extends SystemService { boolean hasValidVibrate = false; boolean hasValidVibrate = false; boolean hasValidSound = false; boolean hasValidSound = false; if (isNotificationForCurrentUser(record)) { if (aboveThreshold && isNotificationForCurrentUser(record)) { // If the notification will appear in the status bar, it should send an accessibility // If the notification will appear in the status bar, it should send an accessibility // event // event if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN) { if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN) { sendAccessibilityEvent(notification, record.sbn.getPackageName()); sendAccessibilityEvent(notification, record.sbn.getPackageName()); } } if (mSystemReady && mAudioManager != null) { if (disableEffects == null && canInterrupt && mSystemReady && mAudioManager != null) { if (DBG) Slog.v(TAG, "Interrupting!"); Uri soundUri = record.getSound(); Uri soundUri = record.getSound(); hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri); hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri); long[] vibration = record.getVibration(); long[] vibration = record.getVibration(); // Demote sound to vibration if vibration missing & phone in vibration mode. // Demote sound to vibration if vibration missing & phone in vibration mode. if (vibration == null if (vibration == null Loading @@ -3882,7 +3871,10 @@ public class NotificationManagerService extends SystemService { } } hasValidVibrate = vibration != null; hasValidVibrate = vibration != null; if (!shouldMuteNotificationLocked(record)) { boolean hasAudibleAlert = hasValidSound || hasValidVibrate; if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) { if (DBG) Slog.v(TAG, "Interrupting!"); if (hasValidSound) { if (hasValidSound) { mSoundNotificationKey = key; mSoundNotificationKey = key; if (mInCall) { if (mInCall) { Loading Loading @@ -3939,14 +3931,37 @@ public class NotificationManagerService extends SystemService { @GuardedBy("mNotificationLock") @GuardedBy("mNotificationLock") boolean shouldMuteNotificationLocked(final NotificationRecord record) { boolean shouldMuteNotificationLocked(final NotificationRecord record) { // Suppressed because it's a silent update final Notification notification = record.getNotification(); final Notification notification = record.getNotification(); if(record.isUpdate if(record.isUpdate && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) { && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) { return true; return true; } } // Suppressed for being too recently noisy final String pkg = record.sbn.getPackageName(); if (mUsageStats.isAlertRateLimited(pkg)) { Slog.e(TAG, "Muting recently noisy " + record.getKey()); return true; } // muted by listener final String disableEffects = disableNotificationEffects(record); if (disableEffects != null) { ZenLog.traceDisableEffects(record, disableEffects); return true; } // suppressed due to DND if (record.isIntercepted()) { return true; } // Suppressed because another notification in its group handles alerting if (record.sbn.isGroup()) { if (record.sbn.isGroup()) { return notification.suppressAlertingDueToGrouping(); return notification.suppressAlertingDueToGrouping(); } } return false; return false; } } Loading
services/core/java/com/android/server/notification/NotificationUsageStats.java +30 −0 Original line number Original line Diff line number Diff line Loading @@ -113,6 +113,18 @@ public class NotificationUsageStats { } } } } /** * Called when a notification wants to alert. */ public synchronized boolean isAlertRateLimited(String packageName) { AggregatedStats stats = getOrCreateAggregatedStatsLocked(packageName); if (stats != null) { return stats.isAlertRateLimited(); } else { return false; } } /** /** * Called when a notification is tentatively enqueued by an app, before rate checking. * Called when a notification is tentatively enqueued by an app, before rate checking. */ */ Loading Loading @@ -386,7 +398,9 @@ public class NotificationUsageStats { public ImportanceHistogram quietImportance; public ImportanceHistogram quietImportance; public ImportanceHistogram finalImportance; public ImportanceHistogram finalImportance; public RateEstimator enqueueRate; public RateEstimator enqueueRate; public AlertRateLimiter alertRate; public int numRateViolations; public int numRateViolations; public int numAlertViolations; public int numQuotaViolations; public int numQuotaViolations; public long mLastAccessTime; public long mLastAccessTime; Loading @@ -398,6 +412,7 @@ public class NotificationUsageStats { quietImportance = new ImportanceHistogram(context, "note_imp_quiet_"); quietImportance = new ImportanceHistogram(context, "note_imp_quiet_"); finalImportance = new ImportanceHistogram(context, "note_importance_"); finalImportance = new ImportanceHistogram(context, "note_importance_"); enqueueRate = new RateEstimator(); enqueueRate = new RateEstimator(); alertRate = new AlertRateLimiter(); } } public AggregatedStats getPrevious() { public AggregatedStats getPrevious() { Loading Loading @@ -510,6 +525,7 @@ public class NotificationUsageStats { maybeCount("note_sub_text", (numWithSubText - previous.numWithSubText)); maybeCount("note_sub_text", (numWithSubText - previous.numWithSubText)); maybeCount("note_info_text", (numWithInfoText - previous.numWithInfoText)); maybeCount("note_info_text", (numWithInfoText - previous.numWithInfoText)); maybeCount("note_over_rate", (numRateViolations - previous.numRateViolations)); maybeCount("note_over_rate", (numRateViolations - previous.numRateViolations)); maybeCount("note_over_alert_rate", (numAlertViolations - previous.numAlertViolations)); maybeCount("note_over_quota", (numQuotaViolations - previous.numQuotaViolations)); maybeCount("note_over_quota", (numQuotaViolations - previous.numQuotaViolations)); noisyImportance.maybeCount(previous.noisyImportance); noisyImportance.maybeCount(previous.noisyImportance); quietImportance.maybeCount(previous.quietImportance); quietImportance.maybeCount(previous.quietImportance); Loading Loading @@ -542,6 +558,7 @@ public class NotificationUsageStats { previous.numWithSubText = numWithSubText; previous.numWithSubText = numWithSubText; previous.numWithInfoText = numWithInfoText; previous.numWithInfoText = numWithInfoText; previous.numRateViolations = numRateViolations; previous.numRateViolations = numRateViolations; previous.numAlertViolations = numAlertViolations; previous.numQuotaViolations = numQuotaViolations; previous.numQuotaViolations = numQuotaViolations; noisyImportance.update(previous.noisyImportance); noisyImportance.update(previous.noisyImportance); quietImportance.update(previous.quietImportance); quietImportance.update(previous.quietImportance); Loading Loading @@ -576,6 +593,14 @@ public class NotificationUsageStats { enqueueRate.update(now); enqueueRate.update(now); } } public boolean isAlertRateLimited() { boolean limited = alertRate.isRateLimited(SystemClock.elapsedRealtime()); if (limited) { numAlertViolations++; } return limited; } private String toStringWithIndent(String indent) { private String toStringWithIndent(String indent) { StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder(); output.append(indent).append("AggregatedStats{\n"); output.append(indent).append("AggregatedStats{\n"); Loading Loading @@ -634,7 +659,11 @@ public class NotificationUsageStats { output.append("numWithSubText=").append(numWithSubText).append("\n"); output.append("numWithSubText=").append(numWithSubText).append("\n"); output.append(indentPlusTwo); output.append(indentPlusTwo); output.append("numWithInfoText=").append(numWithInfoText).append("\n"); output.append("numWithInfoText=").append(numWithInfoText).append("\n"); output.append(indentPlusTwo); output.append("numRateViolations=").append(numRateViolations).append("\n"); output.append("numRateViolations=").append(numRateViolations).append("\n"); output.append(indentPlusTwo); output.append("numAlertViolations=").append(numAlertViolations).append("\n"); output.append(indentPlusTwo); output.append("numQuotaViolations=").append(numQuotaViolations).append("\n"); output.append("numQuotaViolations=").append(numQuotaViolations).append("\n"); output.append(indentPlusTwo).append(noisyImportance.toString()).append("\n"); output.append(indentPlusTwo).append(noisyImportance.toString()).append("\n"); output.append(indentPlusTwo).append(quietImportance.toString()).append("\n"); output.append(indentPlusTwo).append(quietImportance.toString()).append("\n"); Loading Loading @@ -677,6 +706,7 @@ public class NotificationUsageStats { maybePut(dump, "numRateViolations", numRateViolations); maybePut(dump, "numRateViolations", numRateViolations); maybePut(dump, "numQuotaLViolations", numQuotaViolations); maybePut(dump, "numQuotaLViolations", numQuotaViolations); maybePut(dump, "notificationEnqueueRate", getEnqueueRate()); maybePut(dump, "notificationEnqueueRate", getEnqueueRate()); maybePut(dump, "numAlertViolations", numAlertViolations); noisyImportance.maybePut(dump, previous.noisyImportance); noisyImportance.maybePut(dump, previous.noisyImportance); quietImportance.maybePut(dump, previous.quietImportance); quietImportance.maybePut(dump, previous.quietImportance); finalImportance.maybePut(dump, previous.finalImportance); finalImportance.maybePut(dump, previous.finalImportance); Loading
services/tests/notification/src/com/android/server/notification/AlertRateLimiterTest.java 0 → 100644 +72 −0 Original line number Original line Diff line number Diff line /* * 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)); } }