diff options
| author | 2014-03-21 11:07:11 -0700 | |
|---|---|---|
| committer | 2014-03-21 16:14:59 -0700 | |
| commit | a1bd79268be693f04f4adee90673d6ed400cc9fd (patch) | |
| tree | 7392f2015cd8ea477bd5a0b3b5e81236c31e2e93 | |
| parent | e9c77aee60fbb781db916d32fe1db81e1d973f8f (diff) | |
Battery stats: track actually running time
Use the uptime while creating the battery stats history to
generate a new event indicating when the CPU is actually running.
We can do this in combination with the new event reporting when
the CPU comes awake, looking at the difference between the
uptime and elapsed time at that point to determine when it last
when to sleep.
Also use this information to generate a new set of aggregated
states, the uptime caused by each wake reason.
Finally use new radio down timestamp to adjust the times we
compute for radio use. Note that this information is not (yet)
being used to adjust how these are recorded in the history.
Change-Id: I723b3b526c8e7d64de0cac9d1193e04132d5a3e4
7 files changed, 430 insertions, 131 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index b0d94d59a70e..87beb95479c5 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -155,6 +155,7 @@ public abstract class BatteryStats implements Parcelable { private static final String FOREGROUND_DATA = "fg"; private static final String WAKELOCK_DATA = "wl"; private static final String KERNEL_WAKELOCK_DATA = "kwl"; + private static final String WAKEUP_REASON_DATA = "wr"; private static final String NETWORK_DATA = "nt"; private static final String USER_ACTIVITY_DATA = "ua"; private static final String BATTERY_DATA = "bt"; @@ -201,6 +202,25 @@ public abstract class BatteryStats implements Parcelable { } /** + * State for keeping track of long counting information. + */ + public static abstract class LongCounter { + + /** + * Returns the count associated with this Counter for the + * selected type of statistics. + * + * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT + */ + public abstract long getCountLocked(int which); + + /** + * Temporary for debugging. + */ + public abstract void logState(Printer pw, String prefix); + } + + /** * State for keeping track of timing information. */ public static abstract class Timer { @@ -552,8 +572,8 @@ public abstract class BatteryStats implements Parcelable { // These states always appear directly in the first int token // of a delta change; they should be ones that change relatively // frequently. - public static final int STATE_WAKE_LOCK_FLAG = 1<<31; - public static final int STATE_SENSOR_ON_FLAG = 1<<30; + public static final int STATE_CPU_RUNNING_FLAG = 1<<31; + public static final int STATE_WAKE_LOCK_FLAG = 1<<30; public static final int STATE_GPS_ON_FLAG = 1<<29; public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<28; public static final int STATE_WIFI_SCAN_FLAG = 1<<27; @@ -562,9 +582,9 @@ public abstract class BatteryStats implements Parcelable { public static final int STATE_WIFI_RUNNING_FLAG = 1<<24; // These are on the lower bits used for the command; if they change // we need to write another int of data. - public static final int STATE_PHONE_SCANNING_FLAG = 1<<23; + public static final int STATE_SENSOR_ON_FLAG = 1<<23; public static final int STATE_AUDIO_ON_FLAG = 1<<22; - public static final int STATE_VIDEO_ON_FLAG = 1<<21; + public static final int STATE_PHONE_SCANNING_FLAG = 1<<21; public static final int STATE_SCREEN_ON_FLAG = 1<<20; public static final int STATE_BATTERY_PLUGGED_FLAG = 1<<19; public static final int STATE_PHONE_IN_CALL_FLAG = 1<<18; @@ -577,6 +597,7 @@ public abstract class BatteryStats implements Parcelable { public int states; + public static final int STATE2_VIDEO_ON_FLAG = 1<<0; public int states2; // The wake lock that was acquired at this point. @@ -653,6 +674,7 @@ public abstract class BatteryStats implements Parcelable { | ((((int)batteryVoltage)<<16)&0xffff0000); dest.writeInt(bat); dest.writeInt(states); + dest.writeInt(states2); if (wakelockTag != null) { wakelockTag.writeToParcel(dest, flags); } @@ -680,6 +702,7 @@ public abstract class BatteryStats implements Parcelable { batteryTemperature = (short)(bat2&0xffff); batteryVoltage = (char)((bat2>>16)&0xffff); states = src.readInt(); + states2 = src.readInt(); if ((bat&0x10000000) != 0) { wakelockTag = localWakelockTag; wakelockTag.readFromParcel(src); @@ -718,6 +741,7 @@ public abstract class BatteryStats implements Parcelable { batteryTemperature = 0; batteryVoltage = 0; states = 0; + states2 = 0; wakelockTag = null; wakeReasonTag = null; eventCode = EVENT_NONE; @@ -744,6 +768,7 @@ public abstract class BatteryStats implements Parcelable { batteryTemperature = o.batteryTemperature; batteryVoltage = o.batteryVoltage; states = o.states; + states2 = o.states2; if (o.wakelockTag != null) { wakelockTag = localWakelockTag; wakelockTag.setTo(o.wakelockTag); @@ -774,6 +799,7 @@ public abstract class BatteryStats implements Parcelable { && batteryTemperature == o.batteryTemperature && batteryVoltage == o.batteryVoltage && states == o.states + && states2 == o.states2 && currentTime == o.currentTime; } @@ -970,6 +996,15 @@ public abstract class BatteryStats implements Parcelable { public abstract int getMobileRadioActiveCount(int which); /** + * Returns the time in microseconds that is the difference between the mobile radio + * time we saw based on the elapsed timestamp when going down vs. the given time stamp + * from the radio. + * + * {@hide} + */ + public abstract long getMobileRadioActiveAdjustedTime(int which); + + /** * Returns the time in microseconds that the mobile network has been active * (in a high power state) but not being able to blame on an app. * @@ -1026,9 +1061,10 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public abstract int getPhoneDataConnectionCount(int dataType, int which); - + public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS = new BitDescription[] { + new BitDescription(HistoryItem.STATE_CPU_RUNNING_FLAG, "running", "r"), new BitDescription(HistoryItem.STATE_WAKE_LOCK_FLAG, "wake_lock", "w"), new BitDescription(HistoryItem.STATE_SENSOR_ON_FLAG, "sensor", "s"), new BitDescription(HistoryItem.STATE_GPS_ON_FLAG, "gps", "g"), @@ -1039,7 +1075,6 @@ public abstract class BatteryStats implements Parcelable { new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running", "Wr"), new BitDescription(HistoryItem.STATE_PHONE_SCANNING_FLAG, "phone_scanning", "Psc"), new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio", "a"), - new BitDescription(HistoryItem.STATE_VIDEO_ON_FLAG, "video", "v"), new BitDescription(HistoryItem.STATE_SCREEN_ON_FLAG, "screen", "S"), new BitDescription(HistoryItem.STATE_BATTERY_PLUGGED_FLAG, "plugged", "BP"), new BitDescription(HistoryItem.STATE_PHONE_IN_CALL_FLAG, "phone_in_call", "Pcl"), @@ -1062,6 +1097,11 @@ public abstract class BatteryStats implements Parcelable { SCREEN_BRIGHTNESS_NAMES, SCREEN_BRIGHTNESS_SHORT_NAMES), }; + public static final BitDescription[] HISTORY_STATE2_DESCRIPTIONS + = new BitDescription[] { + new BitDescription(HistoryItem.STATE2_VIDEO_ON_FLAG, "video", "v"), + }; + public static final String[] HISTORY_EVENT_NAMES = new String[] { "null", "proc", "fg", "top", "sync" }; @@ -1294,6 +1334,8 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long computeRealtime(long curTime, int which); + public abstract Map<String, ? extends LongCounter> getWakeupReasonStats(); + public abstract Map<String, ? extends Timer> getKernelWakelockStats(); /** Returns the number of different speeds that the CPU can run at */ @@ -1554,7 +1596,8 @@ public abstract class BatteryStats implements Parcelable { wifiRunningTime / 1000, bluetoothOnTime / 1000, mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes, fullWakeLockTimeTotal, partialWakeLockTimeTotal, - getInputEventCount(which), getMobileRadioActiveTime(rawRealtime, which)); + getInputEventCount(which), getMobileRadioActiveTime(rawRealtime, which), + getMobileRadioActiveAdjustedTime(which)); // Dump screen brightness stats Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS]; @@ -1626,16 +1669,22 @@ public abstract class BatteryStats implements Parcelable { } if (reqUid < 0) { - Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats(); + Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats(); if (kernelWakelocks.size() > 0) { - for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) { + for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) { sb.setLength(0); printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, ""); - - dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(), + dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(), sb.toString()); } } + Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats(); + if (wakeupReasons.size() > 0) { + for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) { + dumpLine(pw, 0 /* uid */, category, WAKEUP_REASON_DATA, + "\"" + ent.getKey() + "\"", ent.getValue().getCountLocked(which)); + } + } } BatteryStatsHelper helper = new BatteryStatsHelper(context); @@ -2111,6 +2160,18 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); } + final long mobileActiveAdjustedTime = getMobileRadioActiveAdjustedTime(which); + if (mobileActiveAdjustedTime != 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" Mobile radio active adjusted time: "); + formatTimeMs(sb, mobileActiveAdjustedTime / 1000); + sb.append("("); + sb.append(formatRatioLocked(mobileActiveAdjustedTime, whichBatteryRealtime)); + sb.append(")"); + pw.println(sb.toString()); + } + pw.print(prefix); pw.print(" Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes)); pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes)); @@ -2346,24 +2407,49 @@ public abstract class BatteryStats implements Parcelable { pw.println(); } } - } - if (timers.size() > 0) { - Collections.sort(timers, timerComparator); - pw.print(prefix); pw.println(" All partial wake locks:"); - for (int i=0; i<timers.size(); i++) { - TimerEntry timer = timers.get(i); - sb.setLength(0); - sb.append(" Wake lock "); - UserHandle.formatUid(sb, timer.mId); - sb.append(" "); - sb.append(timer.mName); - printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": "); - sb.append(" realtime"); - pw.println(sb.toString()); + if (timers.size() > 0) { + Collections.sort(timers, timerComparator); + pw.print(prefix); pw.println(" All partial wake locks:"); + for (int i=0; i<timers.size(); i++) { + TimerEntry timer = timers.get(i); + sb.setLength(0); + sb.append(" Wake lock "); + UserHandle.formatUid(sb, timer.mId); + sb.append(" "); + sb.append(timer.mName); + printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": "); + sb.append(" realtime"); + pw.println(sb.toString()); + } + timers.clear(); + pw.println(); + } + + Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats(); + if (wakeupReasons.size() > 0) { + pw.print(prefix); pw.println(" All wakeup reasons:"); + final ArrayList<TimerEntry> reasons = new ArrayList<TimerEntry>(); + for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) { + BatteryStats.LongCounter counter = ent.getValue(); + reasons.add(new TimerEntry(ent.getKey(), 0, null, + ent.getValue().getCountLocked(which))); + } + Collections.sort(reasons, timerComparator); + for (int i=0; i<reasons.size(); i++) { + TimerEntry timer = reasons.get(i); + String linePrefix = ": "; + sb.setLength(0); + sb.append(prefix); + sb.append(" Wakeup reason "); + sb.append(timer.mName); + sb.append(": "); + formatTimeMs(sb, timer.mTime); + sb.append("realtime"); + pw.println(sb.toString()); + } + pw.println(); } - timers.clear(); - pw.println(); } for (int iu=0; iu<NU; iu++) { @@ -2772,6 +2858,7 @@ public abstract class BatteryStats implements Parcelable { public static class HistoryPrinter { int oldState = 0; + int oldState2 = 0; int oldLevel = -1; int oldStatus = -1; int oldHealth = -1; @@ -2780,7 +2867,8 @@ public abstract class BatteryStats implements Parcelable { int oldVolt = -1; long lastTime = -1; - public void printNextItem(PrintWriter pw, HistoryItem rec, long now, boolean checkin) { + public void printNextItem(PrintWriter pw, HistoryItem rec, long now, boolean checkin, + boolean verbose) { if (!checkin) { pw.print(" "); if (now >= 0) { @@ -2831,16 +2919,18 @@ public abstract class BatteryStats implements Parcelable { if (rec.batteryLevel < 10) pw.print("00"); else if (rec.batteryLevel < 100) pw.print("0"); pw.print(rec.batteryLevel); - pw.print(" "); - if (rec.states < 0) ; - else if (rec.states < 0x10) pw.print("0000000"); - else if (rec.states < 0x100) pw.print("000000"); - else if (rec.states < 0x1000) pw.print("00000"); - else if (rec.states < 0x10000) pw.print("0000"); - else if (rec.states < 0x100000) pw.print("000"); - else if (rec.states < 0x1000000) pw.print("00"); - else if (rec.states < 0x10000000) pw.print("0"); - pw.print(Integer.toHexString(rec.states)); + if (verbose) { + pw.print(" "); + if (rec.states < 0) ; + else if (rec.states < 0x10) pw.print("0000000"); + else if (rec.states < 0x100) pw.print("000000"); + else if (rec.states < 0x1000) pw.print("00000"); + else if (rec.states < 0x10000) pw.print("0000"); + else if (rec.states < 0x100000) pw.print("000"); + else if (rec.states < 0x1000000) pw.print("00"); + else if (rec.states < 0x10000000) pw.print("0"); + pw.print(Integer.toHexString(rec.states)); + } } else { if (oldLevel != rec.batteryLevel) { oldLevel = rec.batteryLevel; @@ -2934,6 +3024,8 @@ public abstract class BatteryStats implements Parcelable { } printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag, HISTORY_STATE_DESCRIPTIONS, !checkin); + printBitDescriptions(pw, oldState2, rec.states2, null, + HISTORY_STATE2_DESCRIPTIONS, !checkin); if (rec.wakeReasonTag != null) { if (checkin) { pw.print(",Wr="); @@ -3010,6 +3102,7 @@ public abstract class BatteryStats implements Parcelable { public static final int DUMP_CHARGED_ONLY = 1<<1; public static final int DUMP_HISTORY_ONLY = 1<<2; public static final int DUMP_INCLUDE_HISTORY = 1<<3; + public static final int DUMP_VERBOSE = 1<<4; /** * Dumps a human-readable summary of the battery statistics to the given PrintWriter. @@ -3047,7 +3140,8 @@ public abstract class BatteryStats implements Parcelable { while (getNextHistoryLocked(rec)) { lastTime = rec.time; if (rec.time >= histStart) { - hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, false); + hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, false, + (flags&DUMP_VERBOSE) != 0); } } if (histStart >= 0) { @@ -3064,7 +3158,7 @@ public abstract class BatteryStats implements Parcelable { pw.println("Old battery History:"); HistoryPrinter hprinter = new HistoryPrinter(); while (getNextOldHistoryLocked(rec)) { - hprinter.printNextItem(pw, rec, now, false); + hprinter.printNextItem(pw, rec, now, false, (flags&DUMP_VERBOSE) != 0); } pw.println(); } finally { @@ -3150,7 +3244,7 @@ public abstract class BatteryStats implements Parcelable { if (rec.time >= histStart) { pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); pw.print(HISTORY_DATA); pw.print(','); - hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, true); + hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, true, false); } } if (histStart >= 0) { diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 5ba5c57ab90d..32f700d4517d 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -55,7 +55,7 @@ interface IBatteryStats { void noteScreenOff(); void noteInputEvent(); void noteUserActivity(int uid, int event); - void noteDataConnectionActive(int type, boolean active); + void noteDataConnectionActive(int type, boolean active, long timestampNs); void notePhoneOn(); void notePhoneOff(); void notePhoneSignalStrength(in SignalStrength signalStrength); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 082f1a583763..1d885338cea3 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -87,7 +87,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 99 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 101 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -191,7 +191,7 @@ public final class BatteryStatsImpl extends BatteryStats { long mHistoryBaseTime; boolean mHaveBatteryLevel = false; - boolean mRecordingHistory = true; + boolean mRecordingHistory = false; int mNumHistoryItems; static final int MAX_HISTORY_BUFFER = 128*1024; // 128KB @@ -200,6 +200,7 @@ public final class BatteryStatsImpl extends BatteryStats { final HistoryItem mHistoryLastWritten = new HistoryItem(); final HistoryItem mHistoryLastLastWritten = new HistoryItem(); final HistoryItem mHistoryReadTmp = new HistoryItem(); + final HistoryItem mHistoryAddTmp = new HistoryItem(); final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<HistoryTag, Integer>(); String[] mReadHistoryStrings; int[] mReadHistoryUids; @@ -209,7 +210,8 @@ public final class BatteryStatsImpl extends BatteryStats { int mHistoryBufferLastPos = -1; boolean mHistoryOverflow = false; long mLastHistoryElapsedRealtime = 0; - long mLastHistoryUptime = 0; + long mTrackRunningHistoryElapsedRealtime = 0; + long mTrackRunningHistoryUptime = 0; final HistoryItem mHistoryCur = new HistoryItem(); @@ -287,6 +289,7 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mMobileRadioActive; StopwatchTimer mMobileRadioActiveTimer; StopwatchTimer mMobileRadioActivePerAppTimer; + LongSamplingCounter mMobileRadioActiveAdjustedTime; LongSamplingCounter mMobileRadioActiveUnknownTime; LongSamplingCounter mMobileRadioActiveUnknownCount; @@ -330,12 +333,21 @@ public final class BatteryStatsImpl extends BatteryStats { private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<String, SamplingTimer>(); - public Map<String, ? extends SamplingTimer> getKernelWakelockStats() { + public Map<String, ? extends Timer> getKernelWakelockStats() { return mKernelWakelockStats; } private static int sKernelWakelockUpdateVersion = 0; + String mLastWakeupReason = null; + long mLastWakeupUptimeMs = 0; + private final HashMap<String, LongSamplingCounter> mWakeupReasonStats = + new HashMap<String, LongSamplingCounter>(); + + public Map<String, ? extends LongCounter> getWakeupReasonStats() { + return mWakeupReasonStats; + } + private static final int[] PROC_WAKELOCKS_FORMAT = new int[] { Process.PROC_TAB_TERM|Process.PROC_OUT_STRING| // 0: name Process.PROC_QUOTES, @@ -719,7 +731,7 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public static class LongSamplingCounter implements TimeBaseObs { + public static class LongSamplingCounter extends LongCounter implements TimeBaseObs { final TimeBase mTimeBase; long mCount; long mLoadedCount; @@ -775,6 +787,14 @@ public final class BatteryStatsImpl extends BatteryStats { return val; } + @Override + public void logState(Printer pw, String prefix) { + pw.println(prefix + "mCount=" + mCount + + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount + + " mUnpluggedCount=" + mUnpluggedCount + + " mPluggedCount=" + mPluggedCount); + } + void addCountLocked(long count) { mCount += count; } @@ -1409,6 +1429,10 @@ public final class BatteryStatsImpl extends BatteryStats { return 0; } + long getLastUpdateTimeMs() { + return mUpdateTime; + } + void stopRunningLocked(long elapsedRealtimeMs) { // Ignore attempt to stop a timer that isn't running if (mNesting == 0) { @@ -1502,6 +1526,19 @@ public final class BatteryStatsImpl extends BatteryStats { } } + /* + * Get the wakeup reason counter, and create a new one if one + * doesn't already exist. + */ + public LongSamplingCounter getWakeupReasonCounterLocked(String name) { + LongSamplingCounter counter = mWakeupReasonStats.get(name); + if (counter == null) { + counter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase); + mWakeupReasonStats.put(name, counter); + } + return counter; + } + private final Map<String, KernelWakelockStats> readKernelWakelockStats() { FileInputStream is; @@ -1759,6 +1796,10 @@ public final class BatteryStatsImpl extends BatteryStats { if (stateIntChanged) { firstToken |= DELTA_STATE_FLAG; } + final boolean state2IntChanged = cur.states2 != last.states2; + if (state2IntChanged) { + firstToken |= DELTA_STATE2_FLAG; + } if (cur.wakelockTag != null || cur.wakeReasonTag != null) { firstToken |= DELTA_WAKELOCK_FLAG; } @@ -1795,6 +1836,11 @@ public final class BatteryStatsImpl extends BatteryStats { + " batteryPlugType=" + cur.batteryPlugType + " states=0x" + Integer.toHexString(cur.states)); } + if (state2IntChanged) { + dest.writeInt(cur.states2); + if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x" + + Integer.toHexString(cur.states2)); + } if (cur.wakelockTag != null || cur.wakeReasonTag != null) { int wakeLockIndex; int wakeReasonIndex; @@ -1917,6 +1963,12 @@ public final class BatteryStatsImpl extends BatteryStats { cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~DELTA_STATE_MASK)); } + if ((firstToken&DELTA_STATE2_FLAG) != 0) { + cur.states2 = src.readInt(); + if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x" + + Integer.toHexString(cur.states2)); + } + if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) { int indexes = src.readInt(); int wakeLockIndex = indexes&0xffff; @@ -1958,29 +2010,34 @@ public final class BatteryStatsImpl extends BatteryStats { } } - void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs) { + void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) { if (!mHaveBatteryLevel || !mRecordingHistory) { return; } final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time; - final int diffStates = mHistoryLastWritten.states^mHistoryCur.states; + final int diffStates = mHistoryLastWritten.states^cur.states; + final int diffStates2 = mHistoryLastWritten.states2^cur.states2; final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states; + final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2; if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff=" + Integer.toHexString(diffStates) + " lastDiff=" - + Integer.toHexString(lastDiffStates)); + + Integer.toHexString(lastDiffStates) + " diff2=" + + Integer.toHexString(diffStates2) + " lastDiff2=" + + Integer.toHexString(lastDiffStates2)); if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE && timeDiff < 1000 && (diffStates&lastDiffStates) == 0 - && (mHistoryLastWritten.wakelockTag == null || mHistoryCur.wakelockTag == null) - && (mHistoryLastWritten.wakeReasonTag == null || mHistoryCur.wakeReasonTag == null) + && (diffStates2&lastDiffStates2) == 0 + && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null) + && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null) && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE - || mHistoryCur.eventCode == HistoryItem.EVENT_NONE) - && mHistoryLastWritten.batteryLevel == mHistoryCur.batteryLevel - && mHistoryLastWritten.batteryStatus == mHistoryCur.batteryStatus - && mHistoryLastWritten.batteryHealth == mHistoryCur.batteryHealth - && mHistoryLastWritten.batteryPlugType == mHistoryCur.batteryPlugType - && mHistoryLastWritten.batteryTemperature == mHistoryCur.batteryTemperature - && mHistoryLastWritten.batteryVoltage == mHistoryCur.batteryVoltage) { + || cur.eventCode == HistoryItem.EVENT_NONE) + && mHistoryLastWritten.batteryLevel == cur.batteryLevel + && mHistoryLastWritten.batteryStatus == cur.batteryStatus + && mHistoryLastWritten.batteryHealth == cur.batteryHealth + && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType + && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature + && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) { // We can merge this new change in with the last one. Merging is // allowed as long as only the states have changed, and within those states // as long as no bit has changed both between now and the last entry, as @@ -1994,23 +2051,23 @@ public final class BatteryStatsImpl extends BatteryStats { // Note that the condition above made sure that we aren't in a case where // both it and the current history item have a wakelock tag. if (mHistoryLastWritten.wakelockTag != null) { - mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag; - mHistoryCur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag); + cur.wakelockTag = cur.localWakelockTag; + cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag); } // If the last written history had a wake reason tag, we need to retain it. // Note that the condition above made sure that we aren't in a case where // both it and the current history item have a wakelock tag. if (mHistoryLastWritten.wakeReasonTag != null) { - mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag; - mHistoryCur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag); + cur.wakeReasonTag = cur.localWakeReasonTag; + cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag); } // If the last written history had an event, we need to retain it. // Note that the condition above made sure that we aren't in a case where // both it and the current history item have an event. if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) { - mHistoryCur.eventCode = mHistoryLastWritten.eventCode; - mHistoryCur.eventTag = mHistoryCur.localEventTag; - mHistoryCur.eventTag.setTo(mHistoryLastWritten.eventTag); + cur.eventCode = mHistoryLastWritten.eventCode; + cur.eventTag = cur.localEventTag; + cur.eventTag.setTo(mHistoryLastWritten.eventTag); } mHistoryLastWritten.setTo(mHistoryLastLastWritten); } @@ -2019,8 +2076,8 @@ public final class BatteryStatsImpl extends BatteryStats { if (dataSize >= MAX_HISTORY_BUFFER) { if (!mHistoryOverflow) { mHistoryOverflow = true; - addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE); - addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_OVERFLOW); + addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur); + addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_OVERFLOW, cur); return; } @@ -2028,43 +2085,64 @@ public final class BatteryStatsImpl extends BatteryStats { // record changes to the battery level and the most interesting states. // Once we've reached the maximum maximum number of items, we only // record changes to the battery level. - if (mHistoryLastWritten.batteryLevel == mHistoryCur.batteryLevel && + if (mHistoryLastWritten.batteryLevel == cur.batteryLevel && (dataSize >= MAX_MAX_HISTORY_BUFFER - || ((mHistoryLastWritten.states^mHistoryCur.states) + || ((mHistoryLastWritten.states^cur.states) & HistoryItem.MOST_INTERESTING_STATES) == 0)) { return; } - addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE); + addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur); return; } - addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE); + addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur); } - private void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd) { + private void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, + HistoryItem cur) { if (mIteratingHistory) { throw new IllegalStateException("Can't do this while iterating history!"); } mHistoryBufferLastPos = mHistoryBuffer.dataPosition(); mHistoryLastLastWritten.setTo(mHistoryLastWritten); - mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, mHistoryCur); + mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur); writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten); mLastHistoryElapsedRealtime = elapsedRealtimeMs; - mLastHistoryUptime = uptimeMs; - mHistoryCur.wakelockTag = null; - mHistoryCur.wakeReasonTag = null; - mHistoryCur.eventCode = HistoryItem.EVENT_NONE; - mHistoryCur.eventTag = null; + cur.wakelockTag = null; + cur.wakeReasonTag = null; + cur.eventCode = HistoryItem.EVENT_NONE; + cur.eventTag = null; if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos + " now " + mHistoryBuffer.dataPosition() + " size is now " + mHistoryBuffer.dataSize()); } int mChangedStates = 0; + int mChangedStates2 = 0; void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) { - addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs); + if (mTrackRunningHistoryElapsedRealtime != 0) { + final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime; + final long diffUptime = uptimeMs - mTrackRunningHistoryUptime; + if (diffUptime < (diffElapsed-20)) { + final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime); + mHistoryAddTmp.setTo(mHistoryLastWritten); + mHistoryAddTmp.wakelockTag = null; + mHistoryAddTmp.wakeReasonTag = null; + mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE; + mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG; + addHistoryRecordInnerLocked(wakeElapsedTime, uptimeMs, mHistoryAddTmp); + } + } + mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG; + mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs; + mTrackRunningHistoryUptime = uptimeMs; + addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur); + } + + void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) { + addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur); if (!USE_OLD_HISTORY) { return; @@ -2080,25 +2158,28 @@ public final class BatteryStatsImpl extends BatteryStats { // into one record. if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000) - && ((mHistoryEnd.states^mHistoryCur.states)&mChangedStates) == 0) { + && ((mHistoryEnd.states^cur.states)&mChangedStates) == 0 + && ((mHistoryEnd.states2^cur.states2)&mChangedStates2) == 0) { // If the current is the same as the one before, then we no // longer need the entry. if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500) - && mHistoryLastEnd.sameNonEvent(mHistoryCur)) { + && mHistoryLastEnd.sameNonEvent(cur)) { mHistoryLastEnd.next = null; mHistoryEnd.next = mHistoryCache; mHistoryCache = mHistoryEnd; mHistoryEnd = mHistoryLastEnd; mHistoryLastEnd = null; } else { - mChangedStates |= mHistoryEnd.states^mHistoryCur.states; - mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, mHistoryCur); + mChangedStates |= mHistoryEnd.states^cur.states; + mChangedStates2 |= mHistoryEnd.states^cur.states2; + mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur); } return; } mChangedStates = 0; + mChangedStates2 = 0; if (mNumHistoryItems == MAX_HISTORY_ITEMS || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) { @@ -2111,9 +2192,9 @@ public final class BatteryStatsImpl extends BatteryStats { // Once we've reached the maximum maximum number of items, we only // record changes to the battery level. if (mHistoryEnd != null && mHistoryEnd.batteryLevel - == mHistoryCur.batteryLevel && + == cur.batteryLevel && (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS - || ((mHistoryEnd.states^mHistoryCur.states) + || ((mHistoryEnd.states^cur.states) & HistoryItem.MOST_INTERESTING_STATES) == 0)) { return; } @@ -2128,17 +2209,18 @@ public final class BatteryStatsImpl extends BatteryStats { mHistoryCur.eventTag = mHistoryCur.localEventTag; mHistoryCur.eventTag.string = name; mHistoryCur.eventTag.uid = uid; - addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs); + // XXX should be calling addHistoryRecordLocked()? + addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur); } - void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd) { + void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) { HistoryItem rec = mHistoryCache; if (rec != null) { mHistoryCache = rec.next; } else { rec = new HistoryItem(); } - rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, mHistoryCur); + rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur); addHistoryRecordLocked(rec); } @@ -2168,7 +2250,8 @@ public final class BatteryStatsImpl extends BatteryStats { mHistoryBaseTime = 0; mLastHistoryElapsedRealtime = 0; - mLastHistoryUptime = 0; + mTrackRunningHistoryElapsedRealtime = 0; + mTrackRunningHistoryUptime = 0; mHistoryBuffer.setDataSize(0); mHistoryBuffer.setDataPosition(0); @@ -2284,6 +2367,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (type == WAKE_TYPE_PARTIAL) { // Only care about partial wake locks, since full wake locks // will be canceled when the user puts the screen to sleep. + aggregateLastWakeupUptimeLocked(uptime); if (mWakeLockNesting == 0) { mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: " @@ -2372,14 +2456,26 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public void noteWakeupReasonLocked(int irq, String reason) { + void aggregateLastWakeupUptimeLocked(long uptimeMs) { + if (mLastWakeupReason != null) { + long deltaUptime = uptimeMs - mLastWakeupUptimeMs; + LongSamplingCounter timer = getWakeupReasonCounterLocked(mLastWakeupReason); + timer.addCountLocked(deltaUptime); + mLastWakeupReason = null; + } + } + + public void noteWakeupReasonLocked(String reason) { final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); - if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason irq #" + irq + "\"" + reason +"\": " + if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason reason \"" + reason +"\": " + Integer.toHexString(mHistoryCur.states)); + aggregateLastWakeupUptimeLocked(uptime); mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag; mHistoryCur.wakeReasonTag.string = reason; - mHistoryCur.wakeReasonTag.uid = irq; + mHistoryCur.wakeReasonTag.uid = 0; + mLastWakeupReason = reason; + mLastWakeupUptimeMs = uptime; addHistoryRecordLocked(elapsedRealtime, uptime); } @@ -2670,13 +2766,28 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public void noteDataConnectionActive(int type, boolean active) { + public void noteDataConnectionActive(int type, boolean active, long timestampNs) { if (ConnectivityManager.isNetworkTypeMobile(type)) { final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); if (mMobileRadioActive != active) { - if (active) mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG; - else mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG; + long realElapsedRealtimeMs; + if (active) { + realElapsedRealtimeMs = elapsedRealtime; + mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG; + } else { + realElapsedRealtimeMs = timestampNs / (1000*1000); + long lastUpdateTimeMs = mMobileRadioActiveTimer.getLastUpdateTimeMs(); + if (realElapsedRealtimeMs < lastUpdateTimeMs) { + Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs + + " is before start time " + lastUpdateTimeMs); + realElapsedRealtimeMs = elapsedRealtime; + } else if (realElapsedRealtimeMs < elapsedRealtime) { + mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime + - realElapsedRealtimeMs); + } + mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG; + } if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: " + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime, uptime); @@ -2685,9 +2796,9 @@ public final class BatteryStatsImpl extends BatteryStats { mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime); mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime); } else { - updateNetworkActivityLocked(NET_UPDATE_MOBILE, elapsedRealtime); - mMobileRadioActiveTimer.stopRunningLocked(elapsedRealtime); - mMobileRadioActivePerAppTimer.stopRunningLocked(elapsedRealtime); + mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs); + mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs); + updateNetworkActivityLocked(NET_UPDATE_MOBILE, realElapsedRealtimeMs); } } } @@ -2978,7 +3089,7 @@ public final class BatteryStatsImpl extends BatteryStats { final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); if (!mVideoOn) { - mHistoryCur.states |= HistoryItem.STATE_VIDEO_ON_FLAG; + mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: " + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime, uptime); @@ -2993,7 +3104,7 @@ public final class BatteryStatsImpl extends BatteryStats { final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); if (mVideoOn) { - mHistoryCur.states &= ~HistoryItem.STATE_VIDEO_ON_FLAG; + mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: " + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime, uptime); @@ -3398,6 +3509,10 @@ public final class BatteryStatsImpl extends BatteryStats { return mMobileRadioActiveTimer.getCountLocked(which); } + @Override public long getMobileRadioActiveAdjustedTime(int which) { + return mMobileRadioActiveAdjustedTime.getCountLocked(which); + } + @Override public long getMobileRadioActiveUnknownTime(int which) { return mMobileRadioActiveUnknownTime.getCountLocked(which); } @@ -5458,6 +5573,7 @@ public final class BatteryStatsImpl extends BatteryStats { } mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase); mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase); + mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase); mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase); mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase); mWifiOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase); @@ -5543,9 +5659,9 @@ public final class BatteryStatsImpl extends BatteryStats { PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG)); pw.println("Histories differ!"); pw.println("Old history:"); - (new HistoryPrinter()).printNextItem(pw, out, now, false); + (new HistoryPrinter()).printNextItem(pw, out, now, false, true); pw.println("New history:"); - (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, now, false); + (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, now, false, true); pw.flush(); } } @@ -5719,6 +5835,7 @@ public final class BatteryStatsImpl extends BatteryStats { } mMobileRadioActiveTimer.reset(false); mMobileRadioActivePerAppTimer.reset(false); + mMobileRadioActiveAdjustedTime.reset(false); mMobileRadioActiveUnknownTime.reset(false); mMobileRadioActiveUnknownCount.reset(false); mWifiOnTimer.reset(false); @@ -5744,7 +5861,14 @@ public final class BatteryStatsImpl extends BatteryStats { } mKernelWakelockStats.clear(); } - + + if (mWakeupReasonStats.size() > 0) { + for (LongSamplingCounter timer : mWakeupReasonStats.values()) { + mOnBatteryScreenOffTimeBase.remove(timer); + } + mWakeupReasonStats.clear(); + } + initDischarge(); clearHistoryLocked(); @@ -5828,9 +5952,10 @@ public final class BatteryStatsImpl extends BatteryStats { mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: " + Integer.toHexString(mHistoryCur.states)); - mHistoryCur.currentTime = System.currentTimeMillis(); - addHistoryBufferLocked(mSecRealtime, mSecUptime, HistoryItem.CMD_CURRENT_TIME); - mHistoryCur.currentTime = 0; + if (reset) { + mRecordingHistory = true; + startRecordingHistory(mSecRealtime, mSecUptime, reset); + } addHistoryRecordLocked(mSecRealtime, mSecUptime); mDischargeCurrentLevel = mDischargeUnplugLevel = level; if (mScreenOn) { @@ -5843,9 +5968,6 @@ public final class BatteryStatsImpl extends BatteryStats { mDischargeAmountScreenOn = 0; mDischargeAmountScreenOff = 0; updateTimeBasesLocked(true, !mScreenOn, uptime, realtime); - if (reset) { - initActiveHistoryEventsLocked(mSecRealtime, mSecUptime); - } } else { pullPendingStateUpdatesLocked(); mHistoryCur.batteryLevel = (byte)level; @@ -5868,6 +5990,18 @@ public final class BatteryStatsImpl extends BatteryStats { } } + private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs, + boolean reset) { + mRecordingHistory = true; + mHistoryCur.currentTime = System.currentTimeMillis(); + addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME, + mHistoryCur); + mHistoryCur.currentTime = 0; + if (reset) { + initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs); + } + } + // This should probably be exposed in the API, though it's not critical private static final int BATTERY_PLUGGED_NONE = 0; @@ -5895,7 +6029,15 @@ public final class BatteryStatsImpl extends BatteryStats { } if (onBattery) { mDischargeCurrentLevel = level; - mRecordingHistory = true; + if (!mRecordingHistory) { + mRecordingHistory = true; + startRecordingHistory(elapsedRealtime, uptime, true); + } + } else if (level < 96) { + if (!mRecordingHistory) { + mRecordingHistory = true; + startRecordingHistory(elapsedRealtime, uptime, true); + } } if (onBattery != mOnBattery) { mHistoryCur.batteryLevel = (byte)level; @@ -6497,15 +6639,14 @@ public final class BatteryStatsImpl extends BatteryStats { } if (mHistoryBuffer.dataPosition() > 0) { + mRecordingHistory = true; final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); if (USE_OLD_HISTORY) { - addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START); + addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur); } - addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START); - mHistoryCur.currentTime = System.currentTimeMillis(); - addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_CURRENT_TIME); - mHistoryCur.currentTime = 0; + addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur); + startRecordingHistory(elapsedRealtime, uptime, false); } } @@ -6681,6 +6822,7 @@ public final class BatteryStatsImpl extends BatteryStats { mMobileRadioActive = false; mMobileRadioActiveTimer.readSummaryFromParcelLocked(in); mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in); + mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in); mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in); mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in); mWifiOn = false; @@ -6708,6 +6850,18 @@ public final class BatteryStatsImpl extends BatteryStats { } } + int NWR = in.readInt(); + if (NWR > 10000) { + Slog.w(TAG, "File corrupt: too many wakeup reasons " + NWR); + return; + } + for (int iwr = 0; iwr < NWR; iwr++) { + if (in.readInt() != 0) { + String reasonName = in.readString(); + getWakeupReasonCounterLocked(reasonName).readSummaryFromParcelLocked(in); + } + } + sNumSpeedSteps = in.readInt(); if (sNumSpeedSteps < 0 || sNumSpeedSteps > 100) { throw new BadParcelableException("Bad speed steps in data: " + sNumSpeedSteps); @@ -6915,6 +7069,7 @@ public final class BatteryStatsImpl extends BatteryStats { } mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); + mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out); mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out); mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out); mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); @@ -6933,7 +7088,19 @@ public final class BatteryStatsImpl extends BatteryStats { if (kwlt != null) { out.writeInt(1); out.writeString(ent.getKey()); - ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL_SYS); + kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS); + } else { + out.writeInt(0); + } + } + + out.writeInt(mWakeupReasonStats.size()); + for (Map.Entry<String, LongSamplingCounter> ent : mWakeupReasonStats.entrySet()) { + LongSamplingCounter counter = ent.getValue(); + if (counter != null) { + out.writeInt(1); + out.writeString(ent.getKey()); + counter.writeSummaryFromParcelLocked(out); } else { out.writeInt(0); } @@ -7171,6 +7338,7 @@ public final class BatteryStatsImpl extends BatteryStats { mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase, in); mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase, in); + mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in); mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in); mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in); mWifiOn = false; @@ -7205,12 +7373,22 @@ public final class BatteryStatsImpl extends BatteryStats { for (int ikw = 0; ikw < NKW; ikw++) { if (in.readInt() != 0) { String wakelockName = in.readString(); - in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel SamplingTimer kwlt = new SamplingTimer(mOnBatteryTimeBase, in); mKernelWakelockStats.put(wakelockName, kwlt); } } + mWakeupReasonStats.clear(); + int NWR = in.readInt(); + for (int iwr = 0; iwr < NWR; iwr++) { + if (in.readInt() != 0) { + String reasonName = in.readString(); + LongSamplingCounter counter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, + in); + mWakeupReasonStats.put(reasonName, counter); + } + } + mPartialTimers.clear(); mFullTimers.clear(); mWindowTimers.clear(); @@ -7283,6 +7461,7 @@ public final class BatteryStatsImpl extends BatteryStats { } mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime); mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime); + mMobileRadioActiveAdjustedTime.writeToParcel(out); mMobileRadioActiveUnknownTime.writeToParcel(out); mMobileRadioActiveUnknownCount.writeToParcel(out); mWifiOnTimer.writeToParcel(out, uSecRealtime); @@ -7313,7 +7492,18 @@ public final class BatteryStatsImpl extends BatteryStats { if (kwlt != null) { out.writeInt(1); out.writeString(ent.getKey()); - Timer.writeTimerToParcel(out, kwlt, uSecRealtime); + kwlt.writeToParcel(out, uSecRealtime); + } else { + out.writeInt(0); + } + } + out.writeInt(mWakeupReasonStats.size()); + for (Map.Entry<String, LongSamplingCounter> ent : mWakeupReasonStats.entrySet()) { + LongSamplingCounter counter = ent.getValue(); + if (counter != null) { + out.writeInt(1); + out.writeString(ent.getKey()); + counter.writeToParcel(out); } else { out.writeInt(0); } @@ -7383,6 +7573,8 @@ public final class BatteryStatsImpl extends BatteryStats { } pr.println("*** Mobile network active timer:"); mMobileRadioActiveTimer.logState(pr, " "); + pr.println("*** Mobile network active adjusted timer:"); + mMobileRadioActiveAdjustedTime.logState(pr, " "); pr.println("*** Wifi timer:"); mWifiOnTimer.logState(pr, " "); pr.println("*** WifiRunning timer:"); diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 9de3efee3db6..41ffdc18ef13 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -103,6 +103,7 @@ class AlarmManagerService extends SystemService { private long mNextNonWakeup; int mBroadcastRefCount = 0; PowerManager.WakeLock mWakeLock; + boolean mLastWakeLockUnimportantForLogging; ArrayList<InFlight> mInFlight = new ArrayList<InFlight>(); final AlarmHandler mHandler = new AlarmHandler(); ClockReceiver mClockReceiver; @@ -1345,17 +1346,21 @@ class AlarmManagerService extends SystemService { */ void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, boolean first) { try { - mWakeLock.setUnimportantForLogging(pi == mTimeTickSender); + final boolean unimportant = pi == mTimeTickSender; + mWakeLock.setUnimportantForLogging(unimportant); if (ws != null) { - if (first) { + if (first || mLastWakeLockUnimportantForLogging) { mWakeLock.setHistoryTag(pi.getTag( type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP ? "*walarm*:" : "*alarm*:")); } else { mWakeLock.setHistoryTag(null); } + mLastWakeLockUnimportantForLogging = unimportant; mWakeLock.setWorkSource(ws); return; + } else { + mLastWakeLockUnimportantForLogging = false; } final int uid = ActivityManagerNative.getDefault() diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index a09d6059f281..5273cec092c8 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -348,7 +348,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub */ private void notifyInterfaceClassActivity(int type, boolean active, long tsNanos) { try { - getBatteryStats().noteDataConnectionActive(type, active); + getBatteryStats().noteDataConnectionActive(type, active, tsNanos); } catch (RemoteException e) { } diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index fa4a9d12feeb..0ddb8272cd5e 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -248,10 +248,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub { } } - public void noteDataConnectionActive(int type, boolean active) { + public void noteDataConnectionActive(int type, boolean active, long timestampNs) { enforceCallingPermission(); synchronized (mStats) { - mStats.noteDataConnectionActive(type, active); + mStats.noteDataConnectionActive(type, active, timestampNs); } } @@ -570,9 +570,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub { int num; while ((num=nativeWaitWakeup(mIrqs, mReasons)) >= 0) { synchronized (mStats) { - for (int i=0; i<num; i++) { - //Slog.i(TAG, "Wakeup: irq #" + mIrqs[i] + " reason=" + mReasons[i]); - mStats.noteWakeupReasonLocked(mIrqs[i], mReasons[i]); + if (num > 0) { + for (int i=0; i<num; i++) { + mStats.noteWakeupReasonLocked(mReasons[i]); + } + } else { + mStats.noteWakeupReasonLocked("unknown"); } } } @@ -653,7 +656,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub { dumpHelp(pw); return; } else if ("-a".equals(arg)) { - // fall through + flags |= BatteryStats.DUMP_VERBOSE; } else if (arg.length() > 0 && arg.charAt(0) == '-'){ pw.println("Unknown option: " + arg); dumpHelp(pw); diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp index 22cc5191b4b8..da4cc48793ab 100644 --- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp +++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp @@ -139,16 +139,21 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jintArray outIrqs, } endpos++; } - if (i == 0) { + // For now we are not separating out the first irq. + // This is because in practice there are always multiple + // lines of wakeup reasons, so it is better to just treat + // them all together as a single string. + if (false && i == 0) { firstirq = irq; } else { - int len = snprintf(mergedreasonpos, remainreasonlen, ":%d", irq); + int len = snprintf(mergedreasonpos, remainreasonlen, + i == 0 ? "%d" : ":%d", irq); if (len >= 0 && len < remainreasonlen) { mergedreasonpos += len; remainreasonlen -= len; } } - int len = snprintf(mergedreasonpos, remainreasonlen, i == 0 ? "%s" : ":%s", pos); + int len = snprintf(mergedreasonpos, remainreasonlen, ":%s", pos); if (len >= 0 && len < remainreasonlen) { mergedreasonpos += len; remainreasonlen -= len; |