Fix parsing of kernel wakelocks
We handled stale wakelocks (wakelocks that disappear from /d/wakeup_sources)
differently in previous version of Android. They would be set stale, but still be
updated with their previous counts (they would never disappear).
The method setStale has been replaced with endSample(), which is semantically different.
Once a SamplingTimer has endSample() called, it expects any future calls to update() to
be a new sample, meaning the entire amount passed to update() is included in the kernel
wakelock's total. Since stale wakelocks were never removed from the list, this would
increase by large amounts when nothing had actually changed.
This was exacerbated by the fact that there was a bug where the last wakelock in
/d/wakeup_sources was never parsed, so if the order ever changed, this "stale" wakelock
would suddenly re-appear and the entire amount reported would be charged to the wakelock,
instead of just the difference since the last update.
All this was exposed when we added support to handle wakelocks that would disappear and
reappear with smaller values, meaning the kernel had pruned them from its accounting and
reset them.
Bug:28601080
Change-Id: Ic96027f7d580dac5e20aa73d67e5cedac4ccabeb
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 937fc75..93dc625 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -8873,8 +8873,6 @@
return;
}
- // Record whether we've seen a non-zero time (for debugging b/22716723).
- boolean seenNonZeroTime = false;
for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
String name = ent.getKey();
KernelWakelockStats.Entry kws = ent.getValue();
@@ -8884,27 +8882,24 @@
kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
mKernelWakelockStats.put(name, kwlt);
}
+
kwlt.update(kws.mTotalTime, kws.mCount);
kwlt.setUpdateVersion(kws.mVersion);
-
- if (kws.mVersion != wakelockStats.kernelWakelockVersion) {
- seenNonZeroTime |= kws.mTotalTime > 0;
- }
}
int numWakelocksSetStale = 0;
- if (wakelockStats.size() != mKernelWakelockStats.size()) {
- // Set timers to stale if they didn't appear in /proc/wakelocks this time.
- for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
- SamplingTimer st = ent.getValue();
- if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
- st.endSample();
- numWakelocksSetStale++;
- }
+ // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
+ // this time.
+ for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
+ SamplingTimer st = ent.getValue();
+ if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
+ st.endSample();
+ numWakelocksSetStale++;
}
}
- if (!seenNonZeroTime) {
+ // Record whether we've seen a non-zero time (for debugging b/22716723).
+ if (wakelockStats.isEmpty()) {
Slog.wtf(TAG, "All kernel wakelocks had time of zero");
}