Loading core/java/com/android/internal/os/BatteryStatsImpl.java +70 −36 Original line number Diff line number Diff line Loading @@ -1210,6 +1210,16 @@ public class BatteryStatsImpl extends BatteryStats { } } /** * A counter meant to accept monotonically increasing values to its {@link #update(long, int)} * method. The state of the timer according to its {@link TimeBase} will determine how much * of the value is recorded. * * If the value being recorded resets, {@link #endSample()} can be called in order to * account for the change. If the value passed in to {@link #update(long, int)} decreased * between calls, the {@link #endSample()} is automatically called and the new value is * expected to increase monotonically from that point on. */ public static class SamplingTimer extends Timer { /** Loading Loading @@ -1262,16 +1272,21 @@ public class BatteryStatsImpl extends BatteryStats { } @VisibleForTesting public SamplingTimer(Clocks clocks, TimeBase timeBase, boolean trackReportedValues) { public SamplingTimer(Clocks clocks, TimeBase timeBase) { super(clocks, 0, timeBase); mTrackingReportedValues = trackReportedValues; mTrackingReportedValues = false; mTimeBaseRunning = timeBase.isRunning(); } public void setStale() { mTrackingReportedValues = false; mUnpluggedReportedTotalTime = 0; mUnpluggedReportedCount = 0; /** * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to * be less than the values used for a previous invocation. */ public void endSample() { mTotalTime = computeRunTimeLocked(0 /* unused by us */); mCount = computeCurrentCountLocked(); mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0; mUnpluggedReportedCount = mCurrentReportedCount = 0; } public void setUpdateVersion(int version) { Loading @@ -1282,34 +1297,46 @@ public class BatteryStatsImpl extends BatteryStats { return mUpdateVersion; } public void updateCurrentReportedCount(int count) { if (mTimeBaseRunning && mUnpluggedReportedCount == 0) { /** * Updates the current recorded values. These are meant to be monotonically increasing * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}. * * If the values being recorded have been reset, the monotonically increasing requirement * will be broken. In this case, {@link #endSample()} is automatically called and * the total value of totalTime and count are recorded, starting a new monotonically * increasing sample. * * @param totalTime total time of sample in microseconds. * @param count total number of times the event being sampled occurred. */ public void update(long totalTime, int count) { if (mTimeBaseRunning && !mTrackingReportedValues) { // Updating the reported value for the first time. mUnpluggedReportedTotalTime = totalTime; mUnpluggedReportedCount = count; // If we are receiving an update update mTrackingReportedValues; mTrackingReportedValues = true; } mCurrentReportedCount = count; } public void addCurrentReportedCount(int delta) { updateCurrentReportedCount(mCurrentReportedCount + delta); } public void updateCurrentReportedTotalTime(long totalTime) { if (mTimeBaseRunning && mUnpluggedReportedTotalTime == 0) { // Updating the reported value for the first time. mUnpluggedReportedTotalTime = totalTime; // If we are receiving an update update mTrackingReportedValues; mTrackingReportedValues = true; if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) { endSample(); } mCurrentReportedTotalTime = totalTime; mCurrentReportedCount = count; } public void addCurrentReportedTotalTime(long delta) { updateCurrentReportedTotalTime(mCurrentReportedTotalTime + delta); /** * Adds deltaTime and deltaCount to the current sample. * * @param deltaTime additional time recorded since the last sampled event, in microseconds. * @param deltaCount additional number of times the event being sampled occurred. */ public void add(long deltaTime, int deltaCount) { update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount); } @Override public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime); if (mTrackingReportedValues) { Loading @@ -1319,11 +1346,13 @@ public class BatteryStatsImpl extends BatteryStats { mTimeBaseRunning = true; } @Override public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime); mTimeBaseRunning = false; } @Override public void logState(Printer pw, String prefix) { super.logState(pw, prefix); pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount Loading @@ -1332,16 +1361,19 @@ public class BatteryStatsImpl extends BatteryStats { + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime); } @Override protected long computeRunTimeLocked(long curBatteryRealtime) { return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0); } @Override protected int computeCurrentCountLocked() { return mCount + (mTimeBaseRunning && mTrackingReportedValues ? mCurrentReportedCount - mUnpluggedReportedCount : 0); } @Override public void writeToParcel(Parcel out, long elapsedRealtimeUs) { super.writeToParcel(out, elapsedRealtimeUs); out.writeInt(mCurrentReportedCount); Loading @@ -1351,12 +1383,16 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(mTrackingReportedValues ? 1 : 0); } @Override public boolean reset(boolean detachIfReset) { super.reset(detachIfReset); setStale(); mTrackingReportedValues = false; mUnpluggedReportedTotalTime = 0; mUnpluggedReportedCount = 0; return true; } @Override public void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { super.writeSummaryFromParcelLocked(out, batteryRealtime); out.writeLong(mCurrentReportedTotalTime); Loading @@ -1364,6 +1400,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(mTrackingReportedValues ? 1 : 0); } @Override public void readSummaryFromParcelLocked(Parcel in) { super.readSummaryFromParcelLocked(in); mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong(); Loading Loading @@ -2002,7 +2039,7 @@ public class BatteryStatsImpl extends BatteryStats { public SamplingTimer getWakeupReasonTimerLocked(String name) { SamplingTimer timer = mWakeupReasonStats.get(name); if (timer == null) { timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, true); timer = new SamplingTimer(mClocks, mOnBatteryTimeBase); mWakeupReasonStats.put(name, timer); } return timer; Loading @@ -2015,8 +2052,7 @@ public class BatteryStatsImpl extends BatteryStats { public SamplingTimer getKernelWakelockTimerLocked(String name) { SamplingTimer kwlt = mKernelWakelockStats.get(name); if (kwlt == null) { kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, true /* track reported values */); kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase); mKernelWakelockStats.put(name, kwlt); } return kwlt; Loading Loading @@ -3125,8 +3161,7 @@ public class BatteryStatsImpl extends BatteryStats { if (mLastWakeupReason != null) { long deltaUptime = uptimeMs - mLastWakeupUptimeMs; SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason); timer.addCurrentReportedCount(1); timer.addCurrentReportedTotalTime(deltaUptime * 1000); // time is in microseconds timer.add(deltaUptime * 1000, 1); // time in in microseconds mLastWakeupReason = null; } } Loading Loading @@ -8727,17 +8762,16 @@ public class BatteryStatsImpl extends BatteryStats { SamplingTimer kwlt = mKernelWakelockStats.get(name); if (kwlt == null) { kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, true /* track reported val */); kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase); mKernelWakelockStats.put(name, kwlt); } kwlt.updateCurrentReportedCount(kws.mCount); kwlt.updateCurrentReportedTotalTime(kws.mTotalTime); kwlt.update(kws.mTotalTime, kws.mCount); kwlt.setUpdateVersion(kws.mVersion); if (kws.mVersion != wakelockStats.kernelWakelockVersion) if (kws.mVersion != wakelockStats.kernelWakelockVersion) { seenNonZeroTime |= kws.mTotalTime > 0; } } int numWakelocksSetStale = 0; if (wakelockStats.size() != mKernelWakelockStats.size()) { Loading @@ -8745,7 +8779,7 @@ public class BatteryStatsImpl extends BatteryStats { for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { SamplingTimer st = ent.getValue(); if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) { st.setStale(); st.endSample(); numWakelocksSetStale++; } } Loading core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java +116 −8 Original line number Diff line number Diff line Loading @@ -21,8 +21,119 @@ import android.support.test.filters.SmallTest; import junit.framework.TestCase; import org.mockito.Mockito; public class BatteryStatsSamplingTimerTest extends TestCase { @SmallTest public void testSettingStalePreservesData() throws Exception { final MockClocks clocks = new MockClocks(); final BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, Mockito.mock(BatteryStatsImpl.TimeBase.class)); timer.onTimeStarted(100, 100, 100); // First update is absorbed. timer.update(10, 1); timer.update(20, 2); assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(10, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); timer.endSample(); assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(10, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); timer.onTimeStopped(200, 200, 200); assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(10, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); } @SmallTest public void testEndSampleAndContinueWhenTimeOrCountDecreases() throws Exception { final MockClocks clocks = new MockClocks(); final BatteryStatsImpl.TimeBase timeBase = Mockito.mock(BatteryStatsImpl.TimeBase.class); final BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); // First once is absorbed. timer.update(10, 1); timer.add(10, 1); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); // This is less than we currently have, so we will end the sample. Time isn't running, so // nothing should happen. timer.update(0, 0); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); timer.onTimeStarted(100, 100, 100); // This should add. timer.add(100, 10); assertEquals(100, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(10, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); // This is less than we currently have, so we should end our sample and continue with the // entire amount updated here. timer.update(50, 5); assertEquals(150, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(15, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); timer.onTimeStopped(200, 200, 200); assertEquals(150, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(15, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); } @SmallTest public void testFirstUpdateIsAbsorbed() throws Exception { final MockClocks clocks = new MockClocks(); final BatteryStatsImpl.TimeBase timeBase = Mockito.mock(BatteryStatsImpl.TimeBase.class); BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); // This should be absorbed because it is our first update and we don't know what // was being counted before. timer.update(10, 1); assertEquals(0, timer.getTotalTimeLocked(10, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); timer.onTimeStarted(100, 100, 100); // This should be absorbed. timer.update(10, 1); assertEquals(0, timer.getTotalTimeLocked(100, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); // This should NOT be aborbed, since we've already done that. timer.add(10, 1); assertEquals(10, timer.getTotalTimeLocked(100, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); timer.onTimeStopped(200, 200, 200); timer.onTimeStarted(300, 300, 300); // This should NOT be absorbed. timer.add(10, 1); assertEquals(20, timer.getTotalTimeLocked(300, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(2, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); } @SmallTest public void testSampleTimerSummaryParceling() throws Exception { final MockClocks clocks = new MockClocks(); Loading @@ -32,18 +143,15 @@ public class BatteryStatsSamplingTimerTest extends TestCase { final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase(); timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime()); BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase, true); BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); // Start running on battery. timeBase.setRunning(true, clocks.uptimeMillis(), clocks.elapsedRealtime()); // The first update on battery consumes the values as a way of starting cleanly. timer.addCurrentReportedTotalTime(10); timer.addCurrentReportedCount(1); timer.add(10, 1); timer.addCurrentReportedTotalTime(10); timer.addCurrentReportedCount(1); timer.add(10, 1); clocks.realtime = 20; clocks.uptime = 20; Loading Loading @@ -72,14 +180,14 @@ public class BatteryStatsSamplingTimerTest extends TestCase { // Read the on battery summary from the parcel. BatteryStatsImpl.SamplingTimer unparceledTimer = new BatteryStatsImpl.SamplingTimer( clocks, timeBase, true); clocks, timeBase); unparceledTimer.readSummaryFromParcelLocked(onBatterySummaryParcel); assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); // Read the off battery summary from the parcel. unparceledTimer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase, true); unparceledTimer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); unparceledTimer.readSummaryFromParcelLocked(offBatterySummaryParcel); assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED)); Loading Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +70 −36 Original line number Diff line number Diff line Loading @@ -1210,6 +1210,16 @@ public class BatteryStatsImpl extends BatteryStats { } } /** * A counter meant to accept monotonically increasing values to its {@link #update(long, int)} * method. The state of the timer according to its {@link TimeBase} will determine how much * of the value is recorded. * * If the value being recorded resets, {@link #endSample()} can be called in order to * account for the change. If the value passed in to {@link #update(long, int)} decreased * between calls, the {@link #endSample()} is automatically called and the new value is * expected to increase monotonically from that point on. */ public static class SamplingTimer extends Timer { /** Loading Loading @@ -1262,16 +1272,21 @@ public class BatteryStatsImpl extends BatteryStats { } @VisibleForTesting public SamplingTimer(Clocks clocks, TimeBase timeBase, boolean trackReportedValues) { public SamplingTimer(Clocks clocks, TimeBase timeBase) { super(clocks, 0, timeBase); mTrackingReportedValues = trackReportedValues; mTrackingReportedValues = false; mTimeBaseRunning = timeBase.isRunning(); } public void setStale() { mTrackingReportedValues = false; mUnpluggedReportedTotalTime = 0; mUnpluggedReportedCount = 0; /** * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to * be less than the values used for a previous invocation. */ public void endSample() { mTotalTime = computeRunTimeLocked(0 /* unused by us */); mCount = computeCurrentCountLocked(); mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0; mUnpluggedReportedCount = mCurrentReportedCount = 0; } public void setUpdateVersion(int version) { Loading @@ -1282,34 +1297,46 @@ public class BatteryStatsImpl extends BatteryStats { return mUpdateVersion; } public void updateCurrentReportedCount(int count) { if (mTimeBaseRunning && mUnpluggedReportedCount == 0) { /** * Updates the current recorded values. These are meant to be monotonically increasing * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}. * * If the values being recorded have been reset, the monotonically increasing requirement * will be broken. In this case, {@link #endSample()} is automatically called and * the total value of totalTime and count are recorded, starting a new monotonically * increasing sample. * * @param totalTime total time of sample in microseconds. * @param count total number of times the event being sampled occurred. */ public void update(long totalTime, int count) { if (mTimeBaseRunning && !mTrackingReportedValues) { // Updating the reported value for the first time. mUnpluggedReportedTotalTime = totalTime; mUnpluggedReportedCount = count; // If we are receiving an update update mTrackingReportedValues; mTrackingReportedValues = true; } mCurrentReportedCount = count; } public void addCurrentReportedCount(int delta) { updateCurrentReportedCount(mCurrentReportedCount + delta); } public void updateCurrentReportedTotalTime(long totalTime) { if (mTimeBaseRunning && mUnpluggedReportedTotalTime == 0) { // Updating the reported value for the first time. mUnpluggedReportedTotalTime = totalTime; // If we are receiving an update update mTrackingReportedValues; mTrackingReportedValues = true; if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) { endSample(); } mCurrentReportedTotalTime = totalTime; mCurrentReportedCount = count; } public void addCurrentReportedTotalTime(long delta) { updateCurrentReportedTotalTime(mCurrentReportedTotalTime + delta); /** * Adds deltaTime and deltaCount to the current sample. * * @param deltaTime additional time recorded since the last sampled event, in microseconds. * @param deltaCount additional number of times the event being sampled occurred. */ public void add(long deltaTime, int deltaCount) { update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount); } @Override public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime); if (mTrackingReportedValues) { Loading @@ -1319,11 +1346,13 @@ public class BatteryStatsImpl extends BatteryStats { mTimeBaseRunning = true; } @Override public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime); mTimeBaseRunning = false; } @Override public void logState(Printer pw, String prefix) { super.logState(pw, prefix); pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount Loading @@ -1332,16 +1361,19 @@ public class BatteryStatsImpl extends BatteryStats { + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime); } @Override protected long computeRunTimeLocked(long curBatteryRealtime) { return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0); } @Override protected int computeCurrentCountLocked() { return mCount + (mTimeBaseRunning && mTrackingReportedValues ? mCurrentReportedCount - mUnpluggedReportedCount : 0); } @Override public void writeToParcel(Parcel out, long elapsedRealtimeUs) { super.writeToParcel(out, elapsedRealtimeUs); out.writeInt(mCurrentReportedCount); Loading @@ -1351,12 +1383,16 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(mTrackingReportedValues ? 1 : 0); } @Override public boolean reset(boolean detachIfReset) { super.reset(detachIfReset); setStale(); mTrackingReportedValues = false; mUnpluggedReportedTotalTime = 0; mUnpluggedReportedCount = 0; return true; } @Override public void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { super.writeSummaryFromParcelLocked(out, batteryRealtime); out.writeLong(mCurrentReportedTotalTime); Loading @@ -1364,6 +1400,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(mTrackingReportedValues ? 1 : 0); } @Override public void readSummaryFromParcelLocked(Parcel in) { super.readSummaryFromParcelLocked(in); mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong(); Loading Loading @@ -2002,7 +2039,7 @@ public class BatteryStatsImpl extends BatteryStats { public SamplingTimer getWakeupReasonTimerLocked(String name) { SamplingTimer timer = mWakeupReasonStats.get(name); if (timer == null) { timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, true); timer = new SamplingTimer(mClocks, mOnBatteryTimeBase); mWakeupReasonStats.put(name, timer); } return timer; Loading @@ -2015,8 +2052,7 @@ public class BatteryStatsImpl extends BatteryStats { public SamplingTimer getKernelWakelockTimerLocked(String name) { SamplingTimer kwlt = mKernelWakelockStats.get(name); if (kwlt == null) { kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, true /* track reported values */); kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase); mKernelWakelockStats.put(name, kwlt); } return kwlt; Loading Loading @@ -3125,8 +3161,7 @@ public class BatteryStatsImpl extends BatteryStats { if (mLastWakeupReason != null) { long deltaUptime = uptimeMs - mLastWakeupUptimeMs; SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason); timer.addCurrentReportedCount(1); timer.addCurrentReportedTotalTime(deltaUptime * 1000); // time is in microseconds timer.add(deltaUptime * 1000, 1); // time in in microseconds mLastWakeupReason = null; } } Loading Loading @@ -8727,17 +8762,16 @@ public class BatteryStatsImpl extends BatteryStats { SamplingTimer kwlt = mKernelWakelockStats.get(name); if (kwlt == null) { kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, true /* track reported val */); kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase); mKernelWakelockStats.put(name, kwlt); } kwlt.updateCurrentReportedCount(kws.mCount); kwlt.updateCurrentReportedTotalTime(kws.mTotalTime); kwlt.update(kws.mTotalTime, kws.mCount); kwlt.setUpdateVersion(kws.mVersion); if (kws.mVersion != wakelockStats.kernelWakelockVersion) if (kws.mVersion != wakelockStats.kernelWakelockVersion) { seenNonZeroTime |= kws.mTotalTime > 0; } } int numWakelocksSetStale = 0; if (wakelockStats.size() != mKernelWakelockStats.size()) { Loading @@ -8745,7 +8779,7 @@ public class BatteryStatsImpl extends BatteryStats { for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { SamplingTimer st = ent.getValue(); if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) { st.setStale(); st.endSample(); numWakelocksSetStale++; } } Loading
core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java +116 −8 Original line number Diff line number Diff line Loading @@ -21,8 +21,119 @@ import android.support.test.filters.SmallTest; import junit.framework.TestCase; import org.mockito.Mockito; public class BatteryStatsSamplingTimerTest extends TestCase { @SmallTest public void testSettingStalePreservesData() throws Exception { final MockClocks clocks = new MockClocks(); final BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, Mockito.mock(BatteryStatsImpl.TimeBase.class)); timer.onTimeStarted(100, 100, 100); // First update is absorbed. timer.update(10, 1); timer.update(20, 2); assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(10, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); timer.endSample(); assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(10, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); timer.onTimeStopped(200, 200, 200); assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(10, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); } @SmallTest public void testEndSampleAndContinueWhenTimeOrCountDecreases() throws Exception { final MockClocks clocks = new MockClocks(); final BatteryStatsImpl.TimeBase timeBase = Mockito.mock(BatteryStatsImpl.TimeBase.class); final BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); // First once is absorbed. timer.update(10, 1); timer.add(10, 1); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); // This is less than we currently have, so we will end the sample. Time isn't running, so // nothing should happen. timer.update(0, 0); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); timer.onTimeStarted(100, 100, 100); // This should add. timer.add(100, 10); assertEquals(100, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(10, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); // This is less than we currently have, so we should end our sample and continue with the // entire amount updated here. timer.update(50, 5); assertEquals(150, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(15, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); timer.onTimeStopped(200, 200, 200); assertEquals(150, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(15, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); } @SmallTest public void testFirstUpdateIsAbsorbed() throws Exception { final MockClocks clocks = new MockClocks(); final BatteryStatsImpl.TimeBase timeBase = Mockito.mock(BatteryStatsImpl.TimeBase.class); BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); // This should be absorbed because it is our first update and we don't know what // was being counted before. timer.update(10, 1); assertEquals(0, timer.getTotalTimeLocked(10, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); timer.onTimeStarted(100, 100, 100); // This should be absorbed. timer.update(10, 1); assertEquals(0, timer.getTotalTimeLocked(100, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); // This should NOT be aborbed, since we've already done that. timer.add(10, 1); assertEquals(10, timer.getTotalTimeLocked(100, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); timer.onTimeStopped(200, 200, 200); timer.onTimeStarted(300, 300, 300); // This should NOT be absorbed. timer.add(10, 1); assertEquals(20, timer.getTotalTimeLocked(300, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(2, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); } @SmallTest public void testSampleTimerSummaryParceling() throws Exception { final MockClocks clocks = new MockClocks(); Loading @@ -32,18 +143,15 @@ public class BatteryStatsSamplingTimerTest extends TestCase { final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase(); timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime()); BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase, true); BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); // Start running on battery. timeBase.setRunning(true, clocks.uptimeMillis(), clocks.elapsedRealtime()); // The first update on battery consumes the values as a way of starting cleanly. timer.addCurrentReportedTotalTime(10); timer.addCurrentReportedCount(1); timer.add(10, 1); timer.addCurrentReportedTotalTime(10); timer.addCurrentReportedCount(1); timer.add(10, 1); clocks.realtime = 20; clocks.uptime = 20; Loading Loading @@ -72,14 +180,14 @@ public class BatteryStatsSamplingTimerTest extends TestCase { // Read the on battery summary from the parcel. BatteryStatsImpl.SamplingTimer unparceledTimer = new BatteryStatsImpl.SamplingTimer( clocks, timeBase, true); clocks, timeBase); unparceledTimer.readSummaryFromParcelLocked(onBatterySummaryParcel); assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); // Read the off battery summary from the parcel. unparceledTimer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase, true); unparceledTimer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); unparceledTimer.readSummaryFromParcelLocked(offBatterySummaryParcel); assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED)); Loading