Merge "assume a generous prior in the rate estimator" into nyc-dev

This commit is contained in:
Chris Wren
2016-06-18 19:28:16 +00:00
committed by Android (Google) Code Review
4 changed files with 43 additions and 9 deletions

View File

@@ -2521,6 +2521,8 @@ public class NotificationManagerService extends SystemService {
return; return;
} }
mUsageStats.registerEnqueuedByApp(pkg);
// Limit the number of notifications that any given package except the android // 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. // package or a registered listener can enqueue. Prevents DOS attacks and deals with leaks.
if (!isSystemNotification && !isNotificationFromListener) { if (!isSystemNotification && !isNotificationFromListener) {

View File

@@ -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. * Called when a notification has been posted.
*/ */
@@ -344,6 +355,7 @@ public class NotificationUsageStats {
private AggregatedStats mPrevious; private AggregatedStats mPrevious;
// ---- Updated as the respective events occur. // ---- Updated as the respective events occur.
public int numEnqueuedByApp;
public int numPostedByApp; public int numPostedByApp;
public int numUpdatedByApp; public int numUpdatedByApp;
public int numRemovedByApp; public int numRemovedByApp;
@@ -470,6 +482,7 @@ public class NotificationUsageStats {
public void emit() { public void emit() {
AggregatedStats previous = getPrevious(); AggregatedStats previous = getPrevious();
maybeCount("note_enqueued", (numEnqueuedByApp - previous.numEnqueuedByApp));
maybeCount("note_post", (numPostedByApp - previous.numPostedByApp)); maybeCount("note_post", (numPostedByApp - previous.numPostedByApp));
maybeCount("note_update", (numUpdatedByApp - previous.numUpdatedByApp)); maybeCount("note_update", (numUpdatedByApp - previous.numUpdatedByApp));
maybeCount("note_remove", (numRemovedByApp - previous.numRemovedByApp)); maybeCount("note_remove", (numRemovedByApp - previous.numRemovedByApp));
@@ -501,6 +514,7 @@ public class NotificationUsageStats {
quietImportance.maybeCount(previous.quietImportance); quietImportance.maybeCount(previous.quietImportance);
finalImportance.maybeCount(previous.finalImportance); finalImportance.maybeCount(previous.finalImportance);
previous.numEnqueuedByApp = numEnqueuedByApp;
previous.numPostedByApp = numPostedByApp; previous.numPostedByApp = numPostedByApp;
previous.numUpdatedByApp = numUpdatedByApp; previous.numUpdatedByApp = numUpdatedByApp;
previous.numRemovedByApp = numRemovedByApp; previous.numRemovedByApp = numRemovedByApp;
@@ -568,6 +582,8 @@ public class NotificationUsageStats {
output.append(indentPlusTwo); output.append(indentPlusTwo);
output.append("key='").append(key).append("',\n"); output.append("key='").append(key).append("',\n");
output.append(indentPlusTwo); output.append(indentPlusTwo);
output.append("numEnqueuedByApp=").append(numEnqueuedByApp).append(",\n");
output.append(indentPlusTwo);
output.append("numPostedByApp=").append(numPostedByApp).append(",\n"); output.append("numPostedByApp=").append(numPostedByApp).append(",\n");
output.append(indentPlusTwo); output.append(indentPlusTwo);
output.append("numUpdatedByApp=").append(numUpdatedByApp).append(",\n"); output.append("numUpdatedByApp=").append(numUpdatedByApp).append(",\n");
@@ -631,6 +647,7 @@ public class NotificationUsageStats {
JSONObject dump = new JSONObject(); JSONObject dump = new JSONObject();
dump.put("key", key); dump.put("key", key);
dump.put("duration", SystemClock.elapsedRealtime() - mCreated); dump.put("duration", SystemClock.elapsedRealtime() - mCreated);
maybePut(dump, "numEnqueuedByApp", numEnqueuedByApp);
maybePut(dump, "numPostedByApp", numPostedByApp); maybePut(dump, "numPostedByApp", numPostedByApp);
maybePut(dump, "numUpdatedByApp", numUpdatedByApp); maybePut(dump, "numUpdatedByApp", numUpdatedByApp);
maybePut(dump, "numRemovedByApp", numRemovedByApp); maybePut(dump, "numRemovedByApp", numRemovedByApp);

View File

@@ -26,9 +26,12 @@ public class RateEstimator {
private static final double RATE_ALPHA = 0.8; private static final double RATE_ALPHA = 0.8;
private static final double MINIMUM_DT = 0.0005; private static final double MINIMUM_DT = 0.0005;
private Long mLastEventTime; 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. */ /** Update the estimate to account for an event that just happened. */
public float update(long now) { public float update(long now) {
@@ -38,7 +41,7 @@ public class RateEstimator {
rate = 0f; rate = 0f;
} else { } else {
// Calculate the new inter-arrival time based on last event time. // Calculate the new inter-arrival time based on last event time.
mInterarrivalTime = (float) getInterarrivalEstimate(now); mInterarrivalTime = getInterarrivalEstimate(now);
rate = (float) (1.0 / mInterarrivalTime); rate = (float) (1.0 / mInterarrivalTime);
} }
mLastEventTime = now; mLastEventTime = now;
@@ -57,10 +60,6 @@ public class RateEstimator {
private double getInterarrivalEstimate(long now) { private double getInterarrivalEstimate(long now) {
double dt = ((double) (now - mLastEventTime)) / 1000.0; double dt = ((double) (now - mLastEventTime)) / 1000.0;
dt = Math.max(dt, MINIMUM_DT); 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) // a*iat_old + (1-a)*(t_now-t_last)
return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt); return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt);
} }

View File

@@ -58,6 +58,15 @@ public class RateEstimatorTest extends AndroidTestCase {
assertFalse(Float.isNaN(rate)); 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 @SmallTest
public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception { public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception {
assertUpdateTime(mTestStartTime); assertUpdateTime(mTestStartTime);
@@ -110,12 +119,19 @@ public class RateEstimatorTest extends AndroidTestCase {
assertLessThan("Rate", rate, 0.1f); 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) { 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) { 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. */ /** @returns the next event time. */