Battery stats tweaks.
- Generate currently active events when a partial
history is requested.
- Tag wake lock release with the wake lock name if it is
different than the one that was acquired.
- New RESET mark for the start of the history.
Change-Id: Ic105656649c46f52855946ed0ad7f98f1d24dedc
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8b7467f..4857533 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -21,6 +21,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Formatter;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -30,6 +31,8 @@
import android.text.format.DateFormat;
import android.util.Printer;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
import android.util.TimeUtils;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
@@ -537,6 +540,7 @@
public static final byte CMD_START = 4;
public static final byte CMD_CURRENT_TIME = 5;
public static final byte CMD_OVERFLOW = 6;
+ public static final byte CMD_RESET = 7;
public byte cmd = CMD_NULL;
@@ -620,6 +624,8 @@
public static final int EVENT_SYNC = 0x0004;
// Number of event types.
public static final int EVENT_COUNT = 0x0005;
+ // Mask to extract out only the type part of the event.
+ public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
public static final int EVENT_PROC_START = EVENT_PROC | EVENT_FLAG_START;
public static final int EVENT_PROC_FINISH = EVENT_PROC | EVENT_FLAG_FINISH;
@@ -684,7 +690,7 @@
dest.writeInt(eventCode);
eventTag.writeToParcel(dest, flags);
}
- if (cmd == CMD_CURRENT_TIME) {
+ if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) {
dest.writeLong(currentTime);
}
}
@@ -722,7 +728,7 @@
eventCode = EVENT_NONE;
eventTag = null;
}
- if (cmd == CMD_CURRENT_TIME) {
+ if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) {
currentTime = src.readLong();
} else {
currentTime = 0;
@@ -833,7 +839,59 @@
return true;
}
}
-
+
+ public final static class HistoryEventTracker {
+ private final HashMap<String, SparseIntArray>[] mActiveEvents
+ = (HashMap<String, SparseIntArray>[]) new HashMap[HistoryItem.EVENT_COUNT];
+
+ public boolean updateState(int code, String name, int uid, int poolIdx) {
+ if ((code&HistoryItem.EVENT_FLAG_START) != 0) {
+ int idx = code&HistoryItem.EVENT_TYPE_MASK;
+ HashMap<String, SparseIntArray> active = mActiveEvents[idx];
+ if (active == null) {
+ active = new HashMap<String, SparseIntArray>();
+ mActiveEvents[idx] = active;
+ }
+ SparseIntArray uids = active.get(name);
+ if (uids == null) {
+ uids = new SparseIntArray();
+ active.put(name, uids);
+ }
+ if (uids.indexOfKey(uid) >= 0) {
+ // Already set, nothing to do!
+ return false;
+ }
+ uids.put(uid, poolIdx);
+ } else if ((code&HistoryItem.EVENT_FLAG_FINISH) != 0) {
+ int idx = code&HistoryItem.EVENT_TYPE_MASK;
+ HashMap<String, SparseIntArray> active = mActiveEvents[idx];
+ if (active == null) {
+ // not currently active, nothing to do.
+ return false;
+ }
+ SparseIntArray uids = active.get(name);
+ if (uids == null) {
+ // not currently active, nothing to do.
+ return false;
+ }
+ idx = uids.indexOfKey(uid);
+ if (idx < 0) {
+ // not currently active, nothing to do.
+ return false;
+ }
+ uids.removeAt(idx);
+ if (uids.size() <= 0) {
+ active.remove(name);
+ }
+ }
+ return true;
+ }
+
+ public HashMap<String, SparseIntArray> getStateForEvent(int code) {
+ return mActiveEvents[code];
+ }
+ }
+
public static final class BitDescription {
public final int mask;
public final int shift;
@@ -861,7 +919,7 @@
this.shortValues = shortValues;
}
}
-
+
public abstract int getHistoryTotalSize();
public abstract int getHistoryUsedSize();
@@ -2958,10 +3016,14 @@
pw.print(":");
}
pw.println("START");
- } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
+ } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
+ || rec.cmd == HistoryItem.CMD_RESET) {
if (checkin) {
pw.print(":");
}
+ if (rec.cmd == HistoryItem.CMD_RESET) {
+ pw.print("RESET:");
+ }
pw.print("TIME:");
if (checkin) {
pw.println(rec.currentTime);
@@ -3187,6 +3249,86 @@
public static final int DUMP_INCLUDE_HISTORY = 1<<3;
public static final int DUMP_VERBOSE = 1<<4;
+ private void dumpHistoryLocked(PrintWriter pw, int flags, long histStart, boolean checkin) {
+ final HistoryPrinter hprinter = new HistoryPrinter();
+ final HistoryItem rec = new HistoryItem();
+ long lastTime = -1;
+ long baseTime = -1;
+ boolean printed = false;
+ HistoryEventTracker tracker = null;
+ while (getNextHistoryLocked(rec)) {
+ lastTime = rec.time;
+ if (baseTime < 0) {
+ baseTime = lastTime;
+ }
+ if (rec.time >= histStart) {
+ if (histStart >= 0 && !printed) {
+ if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
+ || rec.cmd == HistoryItem.CMD_RESET) {
+ printed = true;
+ } else if (rec.currentTime != 0) {
+ printed = true;
+ byte cmd = rec.cmd;
+ rec.cmd = HistoryItem.CMD_CURRENT_TIME;
+ if (checkin) {
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(',');
+ }
+ hprinter.printNextItem(pw, rec, baseTime, checkin,
+ (flags&DUMP_VERBOSE) != 0);
+ rec.cmd = cmd;
+ }
+ if (tracker != null) {
+ int oldCode = rec.eventCode;
+ HistoryTag oldTag = rec.eventTag;
+ rec.eventTag = new HistoryTag();
+ for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
+ HashMap<String, SparseIntArray> active
+ = tracker.getStateForEvent(i);
+ if (active == null) {
+ continue;
+ }
+ for (HashMap.Entry<String, SparseIntArray> ent
+ : active.entrySet()) {
+ SparseIntArray uids = ent.getValue();
+ for (int j=0; j<uids.size(); j++) {
+ rec.eventCode = i;
+ rec.eventTag.string = ent.getKey();
+ rec.eventTag.uid = uids.keyAt(j);
+ rec.eventTag.poolIdx = uids.valueAt(j);
+ if (checkin) {
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(',');
+ }
+ hprinter.printNextItem(pw, rec, baseTime, checkin,
+ (flags&DUMP_VERBOSE) != 0);
+ }
+ }
+ }
+ rec.eventCode = oldCode;
+ rec.eventTag = oldTag;
+ tracker = null;
+ }
+ }
+ if (checkin) {
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(',');
+ }
+ hprinter.printNextItem(pw, rec, baseTime, checkin,
+ (flags&DUMP_VERBOSE) != 0);
+ } else if (rec.eventCode != HistoryItem.EVENT_NONE) {
+ if (tracker == null) {
+ tracker = new HistoryEventTracker();
+ }
+ tracker.updateState(rec.eventCode, rec.eventTag.string,
+ rec.eventTag.uid, rec.eventTag.poolIdx);
+ }
+ }
+ if (histStart >= 0) {
+ pw.print(checkin ? "NEXT: " : " NEXT: "); pw.println(lastTime+1);
+ }
+ }
+
/**
* Dumps a human-readable summary of the battery statistics to the given PrintWriter.
*
@@ -3200,9 +3342,6 @@
(flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
- long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
-
- final HistoryItem rec = new HistoryItem();
final long historyTotalSize = getHistoryTotalSize();
final long historyUsedSize = getHistoryUsedSize();
if (startIteratingHistoryLocked()) {
@@ -3218,35 +3357,7 @@
pw.print(" strings using ");
printSizeValue(pw, getHistoryStringPoolBytes());
pw.println("):");
- HistoryPrinter hprinter = new HistoryPrinter();
- long lastTime = -1;
- long baseTime = -1;
- boolean printed = false;
- while (getNextHistoryLocked(rec)) {
- lastTime = rec.time;
- if (baseTime < 0) {
- baseTime = lastTime;
- }
- if (rec.time >= histStart) {
- if (histStart >= 0 && !printed) {
- if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
- printed = true;
- } else if (rec.currentTime != 0) {
- printed = true;
- byte cmd = rec.cmd;
- rec.cmd = HistoryItem.CMD_CURRENT_TIME;
- hprinter.printNextItem(pw, rec, baseTime, false,
- (flags&DUMP_VERBOSE) != 0);
- rec.cmd = cmd;
- }
- }
- hprinter.printNextItem(pw, rec, baseTime, false,
- (flags&DUMP_VERBOSE) != 0);
- }
- }
- if (histStart >= 0) {
- pw.print(" NEXT: "); pw.println(lastTime+1);
- }
+ dumpHistoryLocked(pw, flags, histStart, false);
pw.println();
} finally {
finishIteratingHistoryLocked();
@@ -3255,6 +3366,7 @@
if (startIteratingOldHistoryLocked()) {
try {
+ final HistoryItem rec = new HistoryItem();
pw.println("Old battery History:");
HistoryPrinter hprinter = new HistoryPrinter();
long baseTime = -1;
@@ -3348,7 +3460,6 @@
(flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
- final HistoryItem rec = new HistoryItem();
if (startIteratingHistoryLocked()) {
try {
for (int i=0; i<getHistoryStringPoolSize(); i++) {
@@ -3365,37 +3476,7 @@
pw.print("\"");
pw.println();
}
- HistoryPrinter hprinter = new HistoryPrinter();
- long lastTime = -1;
- long baseTime = -1;
- boolean printed = false;
- while (getNextHistoryLocked(rec)) {
- lastTime = rec.time;
- if (baseTime < 0) {
- baseTime = lastTime;
- }
- if (rec.time >= histStart) {
- if (histStart >= 0 && !printed) {
- if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
- printed = true;
- } else if (rec.currentTime != 0) {
- printed = true;
- byte cmd = rec.cmd;
- rec.cmd = HistoryItem.CMD_CURRENT_TIME;
- pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
- pw.print(HISTORY_DATA); pw.print(',');
- hprinter.printNextItem(pw, rec, baseTime, true, false);
- rec.cmd = cmd;
- }
- }
- pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
- pw.print(HISTORY_DATA); pw.print(',');
- hprinter.printNextItem(pw, rec, baseTime, true, false);
- }
- }
- if (histStart >= 0) {
- pw.print("NEXT: "); pw.println(lastTime+1);
- }
+ dumpHistoryLocked(pw, flags, histStart, true);
} finally {
finishIteratingHistoryLocked();
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 1aff190..7bd5b12 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -188,8 +188,7 @@
boolean mShuttingDown;
- HashMap<String, SparseBooleanArray>[] mActiveEvents
- = (HashMap<String, SparseBooleanArray>[]) new HashMap[HistoryItem.EVENT_COUNT];
+ final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
long mHistoryBaseTime;
boolean mHaveBatteryLevel = false;
@@ -2297,44 +2296,8 @@
public void noteEventLocked(int code, String name, int uid) {
uid = mapUid(uid);
- if ((code&HistoryItem.EVENT_FLAG_START) != 0) {
- int idx = code&~HistoryItem.EVENT_FLAG_START;
- HashMap<String, SparseBooleanArray> active = mActiveEvents[idx];
- if (active == null) {
- active = new HashMap<String, SparseBooleanArray>();
- mActiveEvents[idx] = active;
- }
- SparseBooleanArray uids = active.get(name);
- if (uids == null) {
- uids = new SparseBooleanArray();
- active.put(name, uids);
- }
- if (uids.get(uid)) {
- // Already set, nothing to do!
- return;
- }
- uids.put(uid, true);
- } else if ((code&HistoryItem.EVENT_FLAG_FINISH) != 0) {
- int idx = code&~HistoryItem.EVENT_FLAG_FINISH;
- HashMap<String, SparseBooleanArray> active = mActiveEvents[idx];
- if (active == null) {
- // not currently active, nothing to do.
- return;
- }
- SparseBooleanArray uids = active.get(name);
- if (uids == null) {
- // not currently active, nothing to do.
- return;
- }
- idx = uids.indexOfKey(uid);
- if (idx < 0 || !uids.valueAt(idx)) {
- // not currently active, nothing to do.
- return;
- }
- uids.removeAt(idx);
- if (uids.size() <= 0) {
- active.remove(name);
- }
+ if (!mActiveEvents.updateState(code, name, uid, 0)) {
+ return;
}
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
@@ -2348,6 +2311,9 @@
}
}
+ private String mInitialAcquireWakeName;
+ private int mInitialAcquireWakeUid = -1;
+
public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type,
boolean unimportantForLogging, long elapsedRealtime, long uptime) {
uid = mapUid(uid);
@@ -2360,8 +2326,9 @@
if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
+ Integer.toHexString(mHistoryCur.states));
mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
- mHistoryCur.wakelockTag.string = historyName != null ? historyName : name;
- mHistoryCur.wakelockTag.uid = uid;
+ mHistoryCur.wakelockTag.string = mInitialAcquireWakeName
+ = historyName != null ? historyName : name;
+ mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
mWakeLockImportant = !unimportantForLogging;
addHistoryRecordLocked(elapsedRealtime, uptime);
} else if (!mWakeLockImportant && !unimportantForLogging) {
@@ -2369,8 +2336,9 @@
// We'll try to update the last tag.
mHistoryLastWritten.wakelockTag = null;
mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
- mHistoryCur.wakelockTag.string = historyName != null ? historyName : name;
- mHistoryCur.wakelockTag.uid = uid;
+ mHistoryCur.wakelockTag.string = mInitialAcquireWakeName
+ = historyName != null ? historyName : name;
+ mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
addHistoryRecordLocked(elapsedRealtime, uptime);
}
mWakeLockImportant = true;
@@ -2395,6 +2363,14 @@
mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
+ Integer.toHexString(mHistoryCur.states));
+ if ((name != null && !name.equals(mInitialAcquireWakeName))
+ || uid != mInitialAcquireWakeUid) {
+ mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
+ mHistoryCur.wakelockTag.string = name;
+ mHistoryCur.wakelockTag.uid = uid;
+ }
+ mInitialAcquireWakeName = null;
+ mInitialAcquireWakeUid = -1;
addHistoryRecordLocked(elapsedRealtime, uptime);
}
}
@@ -5699,7 +5675,8 @@
final long lastRealtime = out.time;
final long lastWalltime = out.currentTime;
readHistoryDelta(mHistoryBuffer, out);
- if (out.cmd != HistoryItem.CMD_CURRENT_TIME && lastWalltime != 0) {
+ if (out.cmd != HistoryItem.CMD_CURRENT_TIME
+ && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
out.currentTime = lastWalltime + (out.time - lastRealtime);
}
return true;
@@ -5845,17 +5822,15 @@
private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
- HashMap<String, SparseBooleanArray> active = mActiveEvents[i];
+ HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
if (active == null) {
continue;
}
- for (HashMap.Entry<String, SparseBooleanArray> ent : active.entrySet()) {
- SparseBooleanArray uids = ent.getValue();
+ for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
+ SparseIntArray uids = ent.getValue();
for (int j=0; j<uids.size(); j++) {
- if (uids.valueAt(j)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
- uids.keyAt(j));
- }
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
+ uids.keyAt(j));
}
}
}
@@ -5971,7 +5946,8 @@
boolean reset) {
mRecordingHistory = true;
mHistoryCur.currentTime = System.currentTimeMillis();
- addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
+ addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
+ reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
mHistoryCur);
mHistoryCur.currentTime = 0;
if (reset) {