Loading services/core/java/com/android/server/notification/NotificationManagerService.java +2 −0 Original line number Diff line number Diff line Loading @@ -2521,6 +2521,8 @@ public class NotificationManagerService extends SystemService { return; } mUsageStats.registerEnqueuedByApp(pkg); // Limit the number of notifications that any given package except the android // package or a registered listener can enqueue. Prevents DOS attacks and deals with leaks. if (!isSystemNotification && !isNotificationFromListener) { Loading services/core/java/com/android/server/notification/NotificationUsageStats.java +17 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,17 @@ public class NotificationUsageStats { } } /** * Called when a notification is tentatively enqueued by an app, before rate checking. */ public synchronized void registerEnqueuedByApp(String packageName) { AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(packageName); for (AggregatedStats stats : aggregatedStatsArray) { stats.numEnqueuedByApp++; } releaseAggregatedStatsLocked(aggregatedStatsArray); } /** * Called when a notification has been posted. */ Loading Loading @@ -344,6 +355,7 @@ public class NotificationUsageStats { private AggregatedStats mPrevious; // ---- Updated as the respective events occur. public int numEnqueuedByApp; public int numPostedByApp; public int numUpdatedByApp; public int numRemovedByApp; Loading Loading @@ -470,6 +482,7 @@ public class NotificationUsageStats { public void emit() { AggregatedStats previous = getPrevious(); maybeCount("note_enqueued", (numEnqueuedByApp - previous.numEnqueuedByApp)); maybeCount("note_post", (numPostedByApp - previous.numPostedByApp)); maybeCount("note_update", (numUpdatedByApp - previous.numUpdatedByApp)); maybeCount("note_remove", (numRemovedByApp - previous.numRemovedByApp)); Loading Loading @@ -501,6 +514,7 @@ public class NotificationUsageStats { quietImportance.maybeCount(previous.quietImportance); finalImportance.maybeCount(previous.finalImportance); previous.numEnqueuedByApp = numEnqueuedByApp; previous.numPostedByApp = numPostedByApp; previous.numUpdatedByApp = numUpdatedByApp; previous.numRemovedByApp = numRemovedByApp; Loading Loading @@ -568,6 +582,8 @@ public class NotificationUsageStats { output.append(indentPlusTwo); output.append("key='").append(key).append("',\n"); output.append(indentPlusTwo); output.append("numEnqueuedByApp=").append(numEnqueuedByApp).append(",\n"); output.append(indentPlusTwo); output.append("numPostedByApp=").append(numPostedByApp).append(",\n"); output.append(indentPlusTwo); output.append("numUpdatedByApp=").append(numUpdatedByApp).append(",\n"); Loading Loading @@ -631,6 +647,7 @@ public class NotificationUsageStats { JSONObject dump = new JSONObject(); dump.put("key", key); dump.put("duration", SystemClock.elapsedRealtime() - mCreated); maybePut(dump, "numEnqueuedByApp", numEnqueuedByApp); maybePut(dump, "numPostedByApp", numPostedByApp); maybePut(dump, "numUpdatedByApp", numUpdatedByApp); maybePut(dump, "numRemovedByApp", numRemovedByApp); Loading services/core/java/com/android/server/notification/RateEstimator.java +6 −7 Original line number Diff line number Diff line Loading @@ -26,9 +26,12 @@ public class RateEstimator { private static final double RATE_ALPHA = 0.8; private static final double MINIMUM_DT = 0.0005; private Long mLastEventTime; private Float mInterarrivalTime; private double mInterarrivalTime; public RateEstimator() {} public RateEstimator() { // assume something generous if we have no information mInterarrivalTime = 1000.0; } /** Update the estimate to account for an event that just happened. */ public float update(long now) { Loading @@ -38,7 +41,7 @@ public class RateEstimator { rate = 0f; } else { // Calculate the new inter-arrival time based on last event time. mInterarrivalTime = (float) getInterarrivalEstimate(now); mInterarrivalTime = getInterarrivalEstimate(now); rate = (float) (1.0 / mInterarrivalTime); } mLastEventTime = now; Loading @@ -57,10 +60,6 @@ public class RateEstimator { private double getInterarrivalEstimate(long now) { double dt = ((double) (now - mLastEventTime)) / 1000.0; dt = Math.max(dt, MINIMUM_DT); if (mInterarrivalTime == null) { // No last inter-arrival time, return the new value directly. return dt; } // a*iat_old + (1-a)*(t_now-t_last) return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt); } Loading services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java +18 −2 Original line number Diff line number Diff line Loading @@ -58,6 +58,15 @@ public class RateEstimatorTest extends AndroidTestCase { assertFalse(Float.isNaN(rate)); } @SmallTest public void testInstantaneousBurstIsEstimatedUnderTwoPercent() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 0, 5); // five events at \inf final float rate = mEstimator.getRate(nextEventTime); assertLessThan("Rate", rate, 20f); } @SmallTest public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception { assertUpdateTime(mTestStartTime); Loading Loading @@ -110,12 +119,19 @@ public class RateEstimatorTest extends AndroidTestCase { assertLessThan("Rate", rate, 0.1f); } @SmallTest public void testGetRateWithOneUpdate() throws Exception { assertUpdateTime(mTestStartTime); final float rate = mEstimator.getRate(mTestStartTime+1); assertLessThan("Rate", rate, 1f); } private void assertLessThan(String label, float a, float b) { assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a < b); assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a <= b); } private void assertGreaterThan(String label, float a, float b) { assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a > b); assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a >= b); } /** @returns the next event time. */ Loading Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +2 −0 Original line number Diff line number Diff line Loading @@ -2521,6 +2521,8 @@ public class NotificationManagerService extends SystemService { return; } mUsageStats.registerEnqueuedByApp(pkg); // Limit the number of notifications that any given package except the android // package or a registered listener can enqueue. Prevents DOS attacks and deals with leaks. if (!isSystemNotification && !isNotificationFromListener) { Loading
services/core/java/com/android/server/notification/NotificationUsageStats.java +17 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,17 @@ public class NotificationUsageStats { } } /** * Called when a notification is tentatively enqueued by an app, before rate checking. */ public synchronized void registerEnqueuedByApp(String packageName) { AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(packageName); for (AggregatedStats stats : aggregatedStatsArray) { stats.numEnqueuedByApp++; } releaseAggregatedStatsLocked(aggregatedStatsArray); } /** * Called when a notification has been posted. */ Loading Loading @@ -344,6 +355,7 @@ public class NotificationUsageStats { private AggregatedStats mPrevious; // ---- Updated as the respective events occur. public int numEnqueuedByApp; public int numPostedByApp; public int numUpdatedByApp; public int numRemovedByApp; Loading Loading @@ -470,6 +482,7 @@ public class NotificationUsageStats { public void emit() { AggregatedStats previous = getPrevious(); maybeCount("note_enqueued", (numEnqueuedByApp - previous.numEnqueuedByApp)); maybeCount("note_post", (numPostedByApp - previous.numPostedByApp)); maybeCount("note_update", (numUpdatedByApp - previous.numUpdatedByApp)); maybeCount("note_remove", (numRemovedByApp - previous.numRemovedByApp)); Loading Loading @@ -501,6 +514,7 @@ public class NotificationUsageStats { quietImportance.maybeCount(previous.quietImportance); finalImportance.maybeCount(previous.finalImportance); previous.numEnqueuedByApp = numEnqueuedByApp; previous.numPostedByApp = numPostedByApp; previous.numUpdatedByApp = numUpdatedByApp; previous.numRemovedByApp = numRemovedByApp; Loading Loading @@ -568,6 +582,8 @@ public class NotificationUsageStats { output.append(indentPlusTwo); output.append("key='").append(key).append("',\n"); output.append(indentPlusTwo); output.append("numEnqueuedByApp=").append(numEnqueuedByApp).append(",\n"); output.append(indentPlusTwo); output.append("numPostedByApp=").append(numPostedByApp).append(",\n"); output.append(indentPlusTwo); output.append("numUpdatedByApp=").append(numUpdatedByApp).append(",\n"); Loading Loading @@ -631,6 +647,7 @@ public class NotificationUsageStats { JSONObject dump = new JSONObject(); dump.put("key", key); dump.put("duration", SystemClock.elapsedRealtime() - mCreated); maybePut(dump, "numEnqueuedByApp", numEnqueuedByApp); maybePut(dump, "numPostedByApp", numPostedByApp); maybePut(dump, "numUpdatedByApp", numUpdatedByApp); maybePut(dump, "numRemovedByApp", numRemovedByApp); Loading
services/core/java/com/android/server/notification/RateEstimator.java +6 −7 Original line number Diff line number Diff line Loading @@ -26,9 +26,12 @@ public class RateEstimator { private static final double RATE_ALPHA = 0.8; private static final double MINIMUM_DT = 0.0005; private Long mLastEventTime; private Float mInterarrivalTime; private double mInterarrivalTime; public RateEstimator() {} public RateEstimator() { // assume something generous if we have no information mInterarrivalTime = 1000.0; } /** Update the estimate to account for an event that just happened. */ public float update(long now) { Loading @@ -38,7 +41,7 @@ public class RateEstimator { rate = 0f; } else { // Calculate the new inter-arrival time based on last event time. mInterarrivalTime = (float) getInterarrivalEstimate(now); mInterarrivalTime = getInterarrivalEstimate(now); rate = (float) (1.0 / mInterarrivalTime); } mLastEventTime = now; Loading @@ -57,10 +60,6 @@ public class RateEstimator { private double getInterarrivalEstimate(long now) { double dt = ((double) (now - mLastEventTime)) / 1000.0; dt = Math.max(dt, MINIMUM_DT); if (mInterarrivalTime == null) { // No last inter-arrival time, return the new value directly. return dt; } // a*iat_old + (1-a)*(t_now-t_last) return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt); } Loading
services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java +18 −2 Original line number Diff line number Diff line Loading @@ -58,6 +58,15 @@ public class RateEstimatorTest extends AndroidTestCase { assertFalse(Float.isNaN(rate)); } @SmallTest public void testInstantaneousBurstIsEstimatedUnderTwoPercent() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 0, 5); // five events at \inf final float rate = mEstimator.getRate(nextEventTime); assertLessThan("Rate", rate, 20f); } @SmallTest public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception { assertUpdateTime(mTestStartTime); Loading Loading @@ -110,12 +119,19 @@ public class RateEstimatorTest extends AndroidTestCase { assertLessThan("Rate", rate, 0.1f); } @SmallTest public void testGetRateWithOneUpdate() throws Exception { assertUpdateTime(mTestStartTime); final float rate = mEstimator.getRate(mTestStartTime+1); assertLessThan("Rate", rate, 1f); } private void assertLessThan(String label, float a, float b) { assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a < b); assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a <= b); } private void assertGreaterThan(String label, float a, float b) { assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a > b); assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a >= b); } /** @returns the next event time. */ Loading