Work on issue #5465917: Wakelock *overflow* held for very long times
- Fix ordering problem in sync manager that would cause its wake
locks to slightly appear in the system process when they should
be fully accounted against the app.
- Allow the system process to have more wake lock names in its
battery stats.
- In the bug report output, print totals of the wake locks for each
process, to make it easier to parse what is being printed for things
like the system process with a huge number of individual wake locks.
Change-Id: I3cf39330f22f3c51c11e65e4124150d73a7da2dd
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 4225393..7d683a5 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -990,8 +990,8 @@
mBound = false;
mContext.unbindService(this);
}
- mSyncWakeLock.setWorkSource(null);
mSyncWakeLock.release();
+ mSyncWakeLock.setWorkSource(null);
}
@Override
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index e344197..438c536 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1095,6 +1095,16 @@
}
}
+ private static long computeWakeLock(Timer timer, long batteryRealtime, int which) {
+ if (timer != null) {
+ // Convert from microseconds to milliseconds with rounding
+ long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
+ long totalTimeMillis = (totalTimeMicros + 500) / 1000;
+ return totalTimeMillis;
+ }
+ return 0;
+ }
+
/**
*
* @param sb a StringBuilder object.
@@ -1109,9 +1119,7 @@
long batteryRealtime, String name, int which, String linePrefix) {
if (timer != null) {
- // Convert from microseconds to milliseconds with rounding
- long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
- long totalTimeMillis = (totalTimeMicros + 500) / 1000;
+ long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
int count = timer.getCountLocked(which);
if (totalTimeMillis != 0) {
@@ -1735,6 +1743,8 @@
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
+ long totalFull = 0, totalPartial = 0, totalWindow = 0;
+ int count = 0;
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
: wakelocks.entrySet()) {
Uid.Wakelock wl = ent.getValue();
@@ -1754,6 +1764,44 @@
// Only print out wake locks that were held
pw.println(sb.toString());
uidActivity = true;
+ count++;
+ }
+ totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
+ batteryRealtime, which);
+ totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
+ batteryRealtime, which);
+ totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
+ batteryRealtime, which);
+ }
+ if (count > 1) {
+ if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" TOTAL wake: ");
+ boolean needComma = false;
+ if (totalFull != 0) {
+ needComma = true;
+ formatTimeMs(sb, totalFull);
+ sb.append("full");
+ }
+ if (totalPartial != 0) {
+ if (needComma) {
+ sb.append(", ");
+ }
+ needComma = true;
+ formatTimeMs(sb, totalPartial);
+ sb.append("partial");
+ }
+ if (totalWindow != 0) {
+ if (needComma) {
+ sb.append(", ");
+ }
+ needComma = true;
+ formatTimeMs(sb, totalWindow);
+ sb.append("window");
+ }
+ sb.append(" realtime");
+ pw.println(sb.toString());
}
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index e2a2566..3e96c81 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -98,6 +98,10 @@
// in to one common name.
private static final int MAX_WAKELOCKS_PER_UID = 30;
+ // The system process gets more. It is special. Oh so special.
+ // With, you know, special needs. Like this.
+ private static final int MAX_WAKELOCKS_PER_UID_IN_SYSTEM = 50;
+
private static final String BATCHED_WAKELOCK_NAME = "*overflow*";
private static int sNumSpeedSteps;
@@ -2895,12 +2899,10 @@
String wakelockName = in.readString();
Uid.Wakelock wakelock = new Wakelock();
wakelock.readFromParcelLocked(unpluggables, in);
- if (mWakelockStats.size() < MAX_WAKELOCKS_PER_UID) {
- // We will just drop some random set of wakelocks if
- // the previous run of the system was an older version
- // that didn't impose a limit.
- mWakelockStats.put(wakelockName, wakelock);
- }
+ // We will just drop some random set of wakelocks if
+ // the previous run of the system was an older version
+ // that didn't impose a limit.
+ mWakelockStats.put(wakelockName, wakelock);
}
int numSensors = in.readInt();
@@ -3904,7 +3906,9 @@
public StopwatchTimer getWakeTimerLocked(String name, int type) {
Wakelock wl = mWakelockStats.get(name);
if (wl == null) {
- if (mWakelockStats.size() > MAX_WAKELOCKS_PER_UID) {
+ final int N = mWakelockStats.size();
+ if (N > MAX_WAKELOCKS_PER_UID && (mUid != Process.SYSTEM_UID
+ || N > MAX_WAKELOCKS_PER_UID_IN_SYSTEM)) {
name = BATCHED_WAKELOCK_NAME;
wl = mWakelockStats.get(name);
}