Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37de0989 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

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
parent 0f94e3f5
Loading
Loading
Loading
Loading
+150 −69
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import java.util.ArrayList;
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.telephony.SignalStrength;
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 abstract class BatteryStats implements Parcelable {
        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 abstract class BatteryStats implements Parcelable {
        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 @@ public abstract class BatteryStats implements Parcelable {
                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 @@ public abstract class BatteryStats implements Parcelable {
                eventCode = EVENT_NONE;
                eventTag = null;
            }
            if (cmd == CMD_CURRENT_TIME) {
            if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) {
                currentTime = src.readLong();
            } else {
                currentTime = 0;
@@ -834,6 +840,58 @@ public abstract class BatteryStats implements Parcelable {
        }
    }

    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;
@@ -2958,10 +3016,14 @@ public abstract class BatteryStats implements Parcelable {
                    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 abstract class BatteryStats implements Parcelable {
    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 @@ public abstract class BatteryStats implements Parcelable {
                (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 @@ public abstract class BatteryStats implements Parcelable {
                    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 @@ public abstract class BatteryStats implements Parcelable {

            if (startIteratingOldHistoryLocked()) {
                try {
                    final HistoryItem rec = new HistoryItem();
                    pw.println("Old battery History:");
                    HistoryPrinter hprinter = new HistoryPrinter();
                    long baseTime = -1;
@@ -3348,7 +3460,6 @@ public abstract class BatteryStats implements Parcelable {
                (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 @@ public abstract class BatteryStats implements Parcelable {
                        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();
                }
+29 −53
Original line number Diff line number Diff line
@@ -188,8 +188,7 @@ public final class BatteryStatsImpl extends BatteryStats {

    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,45 +2296,9 @@ public final class BatteryStatsImpl extends BatteryStats {

    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.
        if (!mActiveEvents.updateState(code, name, uid, 0)) {
            return;
        }
            uids.removeAt(idx);
            if (uids.size() <= 0) {
                active.remove(name);
            }
        }
        final long elapsedRealtime = SystemClock.elapsedRealtime();
        final long uptime = SystemClock.uptimeMillis();
        addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
@@ -2348,6 +2311,9 @@ public final class BatteryStatsImpl extends BatteryStats {
        }
    }

    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 @@ public final class BatteryStatsImpl extends BatteryStats {
                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 @@ public final class BatteryStatsImpl extends BatteryStats {
                    // 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 @@ public final class BatteryStatsImpl extends BatteryStats {
                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 @@ public final class BatteryStatsImpl extends BatteryStats {
        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,21 +5822,19 @@ public final class BatteryStatsImpl extends BatteryStats {

    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));
                }
            }
        }
    }
    }

    void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) {
        if (oldScreenOn) {
@@ -5971,7 +5946,8 @@ public final class BatteryStatsImpl extends BatteryStats {
            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) {