Loading services/core/java/com/android/server/notification/NotificationUsageStats.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -384,7 +384,7 @@ public class NotificationUsageStats { noisyImportance = new ImportanceHistogram(context, "note_imp_noisy_"); noisyImportance = new ImportanceHistogram(context, "note_imp_noisy_"); 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(mCreated); enqueueRate = new RateEstimator(); } } public AggregatedStats getPrevious() { public AggregatedStats getPrevious() { Loading services/core/java/com/android/server/notification/RateEstimator.java +22 −9 Original line number Original line Diff line number Diff line Loading @@ -25,30 +25,43 @@ package com.android.server.notification; public class RateEstimator { 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 Float mInterarrivalTime; public RateEstimator(long now) { public RateEstimator() {} mLastEventTime = now; } /** Update the estimate to account for an event that jsut happened. */ /** Update the estimate to account for an event that just happened. */ public float update(long now) { public float update(long now) { float rate; if (mLastEventTime == null) { // No last event time, rate is zero. rate = 0f; } else { // Calculate the new inter-arrival time based on last event time. mInterarrivalTime = (float) getInterarrivalEstimate(now); mInterarrivalTime = (float) getInterarrivalEstimate(now); rate = (float) (1.0 / mInterarrivalTime); } mLastEventTime = now; mLastEventTime = now; return (float) (1.0 / mInterarrivalTime); return rate; } } /** @return the estimated rate if there were a new event right now. */ /** @return the estimated rate if there were a new event right now. */ public float getRate(long now) { public float getRate(long now) { if (mLastEventTime == null) { return 0f; } return (float) (1.0 / getInterarrivalEstimate(now)); return (float) (1.0 / getInterarrivalEstimate(now)); } } /** @return the average inter-arrival time if there were a new event right now. */ /** @return the average inter-arrival time if there were a new event right now. */ private double getInterarrivalEstimate(long now) { private double getInterarrivalEstimate(long now) { // a*iat_old + (1-a)*(t_now-t_last) 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) return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt); return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt); } } } } services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java +25 −7 Original line number Original line Diff line number Diff line Loading @@ -26,18 +26,18 @@ public class RateEstimatorTest extends AndroidTestCase { @Override @Override public void setUp() { public void setUp() { mTestStartTime = 1225731600000L; mTestStartTime = 1225731600000L; mEstimator = new RateEstimator(mTestStartTime); mEstimator = new RateEstimator(); } } @SmallTest @SmallTest public void testRunningTimeBackwardDoesntExplodeUpdate() throws Exception { public void testRunningTimeBackwardDoesntExplodeUpdate() throws Exception { final float rate = mEstimator.update(mTestStartTime - 1000L); assertUpdateTime(mTestStartTime); assertFalse(Float.isInfinite(rate)); assertUpdateTime(mTestStartTime - 1000L); assertFalse(Float.isNaN(rate)); } } @SmallTest @SmallTest public void testRunningTimeBackwardDoesntExplodeGet() throws Exception { public void testRunningTimeBackwardDoesntExplodeGet() throws Exception { assertUpdateTime(mTestStartTime); final float rate = mEstimator.getRate(mTestStartTime - 1000L); final float rate = mEstimator.getRate(mTestStartTime - 1000L); assertFalse(Float.isInfinite(rate)); assertFalse(Float.isInfinite(rate)); assertFalse(Float.isNaN(rate)); assertFalse(Float.isNaN(rate)); Loading @@ -45,13 +45,14 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testInstantaneousEventsDontExplodeUpdate() throws Exception { public void testInstantaneousEventsDontExplodeUpdate() throws Exception { final float rate = mEstimator.update(mTestStartTime); assertUpdateTime(mTestStartTime); assertFalse(Float.isInfinite(rate)); assertUpdateTime(mTestStartTime); assertFalse(Float.isNaN(rate)); } } @SmallTest @SmallTest public void testInstantaneousEventsDontExplodeGet() throws Exception { public void testInstantaneousEventsDontExplodeGet() throws Exception { assertUpdateTime(mTestStartTime); assertUpdateTime(mTestStartTime); final float rate = mEstimator.getRate(mTestStartTime); final float rate = mEstimator.getRate(mTestStartTime); assertFalse(Float.isInfinite(rate)); assertFalse(Float.isInfinite(rate)); assertFalse(Float.isNaN(rate)); assertFalse(Float.isNaN(rate)); Loading @@ -59,6 +60,7 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception { public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 1, 5); // five events at 1000Hz long nextEventTime = postEvents(eventStart, 1, 5); // five events at 1000Hz final float rate = mEstimator.getRate(nextEventTime); final float rate = mEstimator.getRate(nextEventTime); Loading @@ -67,6 +69,7 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testSustained1000HzBurstIsEstimatedOverNinetyPercent() throws Exception { public void testSustained1000HzBurstIsEstimatedOverNinetyPercent() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 1, 100); // one hundred events at 1000Hz long nextEventTime = postEvents(eventStart, 1, 100); // one hundred events at 1000Hz final float rate = mEstimator.getRate(nextEventTime); final float rate = mEstimator.getRate(nextEventTime); Loading @@ -75,6 +78,7 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testSustained100HzBurstIsEstimatedOverNinetyPercent() throws Exception { public void testSustained100HzBurstIsEstimatedOverNinetyPercent() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 10, 100); // one hundred events at 100Hz long nextEventTime = postEvents(eventStart, 10, 100); // one hundred events at 100Hz final float rate = mEstimator.getRate(nextEventTime); final float rate = mEstimator.getRate(nextEventTime); Loading @@ -84,6 +88,7 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testRecoverQuicklyAfterSustainedBurst() throws Exception { public void testRecoverQuicklyAfterSustainedBurst() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 10, 1000); // one hundred events at 100Hz long nextEventTime = postEvents(eventStart, 10, 1000); // one hundred events at 100Hz final float rate = mEstimator.getRate(nextEventTime + 5000L); // two seconds later final float rate = mEstimator.getRate(nextEventTime + 5000L); // two seconds later Loading @@ -92,12 +97,19 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testEstimateShouldNotOvershoot() throws Exception { public void testEstimateShouldNotOvershoot() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 1, 1000); // one thousand events at 1000Hz long nextEventTime = postEvents(eventStart, 1, 1000); // one thousand events at 1000Hz final float rate = mEstimator.getRate(nextEventTime); final float rate = mEstimator.getRate(nextEventTime); assertLessThan("Rate", rate, 1000f); assertLessThan("Rate", rate, 1000f); } } @SmallTest public void testGetRateWithoutUpdate() throws Exception { final float rate = mEstimator.getRate(mTestStartTime); assertLessThan("Rate", rate, 0.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); } } Loading @@ -115,4 +127,10 @@ public class RateEstimatorTest extends AndroidTestCase { } } return time; return time; } } private void assertUpdateTime(long time) { final float rate = mEstimator.update(time); assertFalse(Float.isInfinite(rate)); assertFalse(Float.isNaN(rate)); } } } Loading
services/core/java/com/android/server/notification/NotificationUsageStats.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -384,7 +384,7 @@ public class NotificationUsageStats { noisyImportance = new ImportanceHistogram(context, "note_imp_noisy_"); noisyImportance = new ImportanceHistogram(context, "note_imp_noisy_"); 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(mCreated); enqueueRate = new RateEstimator(); } } public AggregatedStats getPrevious() { public AggregatedStats getPrevious() { Loading
services/core/java/com/android/server/notification/RateEstimator.java +22 −9 Original line number Original line Diff line number Diff line Loading @@ -25,30 +25,43 @@ package com.android.server.notification; public class RateEstimator { 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 Float mInterarrivalTime; public RateEstimator(long now) { public RateEstimator() {} mLastEventTime = now; } /** Update the estimate to account for an event that jsut happened. */ /** Update the estimate to account for an event that just happened. */ public float update(long now) { public float update(long now) { float rate; if (mLastEventTime == null) { // No last event time, rate is zero. rate = 0f; } else { // Calculate the new inter-arrival time based on last event time. mInterarrivalTime = (float) getInterarrivalEstimate(now); mInterarrivalTime = (float) getInterarrivalEstimate(now); rate = (float) (1.0 / mInterarrivalTime); } mLastEventTime = now; mLastEventTime = now; return (float) (1.0 / mInterarrivalTime); return rate; } } /** @return the estimated rate if there were a new event right now. */ /** @return the estimated rate if there were a new event right now. */ public float getRate(long now) { public float getRate(long now) { if (mLastEventTime == null) { return 0f; } return (float) (1.0 / getInterarrivalEstimate(now)); return (float) (1.0 / getInterarrivalEstimate(now)); } } /** @return the average inter-arrival time if there were a new event right now. */ /** @return the average inter-arrival time if there were a new event right now. */ private double getInterarrivalEstimate(long now) { private double getInterarrivalEstimate(long now) { // a*iat_old + (1-a)*(t_now-t_last) 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) return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt); return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt); } } } }
services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java +25 −7 Original line number Original line Diff line number Diff line Loading @@ -26,18 +26,18 @@ public class RateEstimatorTest extends AndroidTestCase { @Override @Override public void setUp() { public void setUp() { mTestStartTime = 1225731600000L; mTestStartTime = 1225731600000L; mEstimator = new RateEstimator(mTestStartTime); mEstimator = new RateEstimator(); } } @SmallTest @SmallTest public void testRunningTimeBackwardDoesntExplodeUpdate() throws Exception { public void testRunningTimeBackwardDoesntExplodeUpdate() throws Exception { final float rate = mEstimator.update(mTestStartTime - 1000L); assertUpdateTime(mTestStartTime); assertFalse(Float.isInfinite(rate)); assertUpdateTime(mTestStartTime - 1000L); assertFalse(Float.isNaN(rate)); } } @SmallTest @SmallTest public void testRunningTimeBackwardDoesntExplodeGet() throws Exception { public void testRunningTimeBackwardDoesntExplodeGet() throws Exception { assertUpdateTime(mTestStartTime); final float rate = mEstimator.getRate(mTestStartTime - 1000L); final float rate = mEstimator.getRate(mTestStartTime - 1000L); assertFalse(Float.isInfinite(rate)); assertFalse(Float.isInfinite(rate)); assertFalse(Float.isNaN(rate)); assertFalse(Float.isNaN(rate)); Loading @@ -45,13 +45,14 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testInstantaneousEventsDontExplodeUpdate() throws Exception { public void testInstantaneousEventsDontExplodeUpdate() throws Exception { final float rate = mEstimator.update(mTestStartTime); assertUpdateTime(mTestStartTime); assertFalse(Float.isInfinite(rate)); assertUpdateTime(mTestStartTime); assertFalse(Float.isNaN(rate)); } } @SmallTest @SmallTest public void testInstantaneousEventsDontExplodeGet() throws Exception { public void testInstantaneousEventsDontExplodeGet() throws Exception { assertUpdateTime(mTestStartTime); assertUpdateTime(mTestStartTime); final float rate = mEstimator.getRate(mTestStartTime); final float rate = mEstimator.getRate(mTestStartTime); assertFalse(Float.isInfinite(rate)); assertFalse(Float.isInfinite(rate)); assertFalse(Float.isNaN(rate)); assertFalse(Float.isNaN(rate)); Loading @@ -59,6 +60,7 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception { public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 1, 5); // five events at 1000Hz long nextEventTime = postEvents(eventStart, 1, 5); // five events at 1000Hz final float rate = mEstimator.getRate(nextEventTime); final float rate = mEstimator.getRate(nextEventTime); Loading @@ -67,6 +69,7 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testSustained1000HzBurstIsEstimatedOverNinetyPercent() throws Exception { public void testSustained1000HzBurstIsEstimatedOverNinetyPercent() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 1, 100); // one hundred events at 1000Hz long nextEventTime = postEvents(eventStart, 1, 100); // one hundred events at 1000Hz final float rate = mEstimator.getRate(nextEventTime); final float rate = mEstimator.getRate(nextEventTime); Loading @@ -75,6 +78,7 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testSustained100HzBurstIsEstimatedOverNinetyPercent() throws Exception { public void testSustained100HzBurstIsEstimatedOverNinetyPercent() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 10, 100); // one hundred events at 100Hz long nextEventTime = postEvents(eventStart, 10, 100); // one hundred events at 100Hz final float rate = mEstimator.getRate(nextEventTime); final float rate = mEstimator.getRate(nextEventTime); Loading @@ -84,6 +88,7 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testRecoverQuicklyAfterSustainedBurst() throws Exception { public void testRecoverQuicklyAfterSustainedBurst() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 10, 1000); // one hundred events at 100Hz long nextEventTime = postEvents(eventStart, 10, 1000); // one hundred events at 100Hz final float rate = mEstimator.getRate(nextEventTime + 5000L); // two seconds later final float rate = mEstimator.getRate(nextEventTime + 5000L); // two seconds later Loading @@ -92,12 +97,19 @@ public class RateEstimatorTest extends AndroidTestCase { @SmallTest @SmallTest public void testEstimateShouldNotOvershoot() throws Exception { public void testEstimateShouldNotOvershoot() throws Exception { assertUpdateTime(mTestStartTime); long eventStart = mTestStartTime + 1000; // start event a long time after initialization long eventStart = mTestStartTime + 1000; // start event a long time after initialization long nextEventTime = postEvents(eventStart, 1, 1000); // one thousand events at 1000Hz long nextEventTime = postEvents(eventStart, 1, 1000); // one thousand events at 1000Hz final float rate = mEstimator.getRate(nextEventTime); final float rate = mEstimator.getRate(nextEventTime); assertLessThan("Rate", rate, 1000f); assertLessThan("Rate", rate, 1000f); } } @SmallTest public void testGetRateWithoutUpdate() throws Exception { final float rate = mEstimator.getRate(mTestStartTime); assertLessThan("Rate", rate, 0.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); } } Loading @@ -115,4 +127,10 @@ public class RateEstimatorTest extends AndroidTestCase { } } return time; return time; } } private void assertUpdateTime(long time) { final float rate = mEstimator.update(time); assertFalse(Float.isInfinite(rate)); assertFalse(Float.isNaN(rate)); } } }