Loading core/java/android/os/BatteryStats.java +171 −127 Original line number Diff line number Diff line Loading @@ -412,6 +412,7 @@ public abstract class BatteryStats implements Parcelable { public long time; public static final byte CMD_NULL = -1; public static final byte CMD_UPDATE = 0; public static final byte CMD_START = 1; public static final byte CMD_OVERFLOW = 2; Loading Loading @@ -466,16 +467,7 @@ public abstract class BatteryStats implements Parcelable { public HistoryItem(long time, Parcel src) { this.time = time; int bat = src.readInt(); cmd = (byte)(bat&0xff); batteryLevel = (byte)((bat>>8)&0xff); batteryStatus = (byte)((bat>>16)&0xf); batteryHealth = (byte)((bat>>20)&0xf); batteryPlugType = (byte)((bat>>24)&0xf); bat = src.readInt(); batteryTemperature = (char)(bat&0xffff); batteryVoltage = (char)((bat>>16)&0xffff); states = src.readInt(); readFromParcel(src); } public int describeContents() { Loading @@ -496,6 +488,28 @@ public abstract class BatteryStats implements Parcelable { dest.writeInt(states); } public void writeDelta(Parcel dest, HistoryItem last) { writeToParcel(dest, 0); } private void readFromParcel(Parcel src) { int bat = src.readInt(); cmd = (byte)(bat&0xff); batteryLevel = (byte)((bat>>8)&0xff); batteryStatus = (byte)((bat>>16)&0xf); batteryHealth = (byte)((bat>>20)&0xf); batteryPlugType = (byte)((bat>>24)&0xf); bat = src.readInt(); batteryTemperature = (char)(bat&0xffff); batteryVoltage = (char)((bat>>16)&0xffff); states = src.readInt(); } public void readDelta(Parcel src, HistoryItem last) { time = src.readLong(); readFromParcel(src); } public void setTo(HistoryItem o) { time = o.time; cmd = o.cmd; Loading Loading @@ -556,10 +570,13 @@ public abstract class BatteryStats implements Parcelable { public abstract boolean getNextHistoryLocked(HistoryItem out); /** * Return the current history of battery state changes. */ public abstract HistoryItem getHistory(); public abstract void finishIteratingHistoryLocked(); public abstract boolean startIteratingOldHistoryLocked(); public abstract boolean getNextOldHistoryLocked(HistoryItem out); public abstract void finishIteratingOldHistoryLocked(); /** * Return the base time offset for the battery history. Loading Loading @@ -1729,7 +1746,7 @@ public abstract class BatteryStats implements Parcelable { } } void printBitDescriptions(PrintWriter pw, int oldval, int newval, BitDescription[] descriptions) { static void printBitDescriptions(PrintWriter pw, int oldval, int newval, BitDescription[] descriptions) { int diff = oldval ^ newval; if (diff == 0) return; for (int i=0; i<descriptions.length; i++) { Loading @@ -1753,24 +1770,18 @@ public abstract class BatteryStats implements Parcelable { } } /** * Dumps a human-readable summary of the battery statistics to the given PrintWriter. * * @param pw a Printer to receive the dump output. */ @SuppressWarnings("unused") public void dumpLocked(PrintWriter pw) { final HistoryItem rec = new HistoryItem(); if (startIteratingHistoryLocked()) { pw.println("Battery History:"); long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); public void prepareForDumpLocked() { } public static class HistoryPrinter { int oldState = 0; int oldStatus = -1; int oldHealth = -1; int oldPlug = -1; int oldTemp = -1; int oldVolt = -1; while (getNextHistoryLocked(rec)) { public void printNextItem(PrintWriter pw, HistoryItem rec, long now) { pw.print(" "); TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN); pw.print(" "); Loading Loading @@ -1876,6 +1887,37 @@ public abstract class BatteryStats implements Parcelable { } oldState = rec.states; } } /** * Dumps a human-readable summary of the battery statistics to the given PrintWriter. * * @param pw a Printer to receive the dump output. */ @SuppressWarnings("unused") public void dumpLocked(PrintWriter pw) { prepareForDumpLocked(); long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); final HistoryItem rec = new HistoryItem(); if (startIteratingHistoryLocked()) { pw.println("Battery History:"); HistoryPrinter hprinter = new HistoryPrinter(); while (getNextHistoryLocked(rec)) { hprinter.printNextItem(pw, rec, now); } finishIteratingHistoryLocked(); pw.println(""); } if (startIteratingOldHistoryLocked()) { pw.println("Old battery History:"); HistoryPrinter hprinter = new HistoryPrinter(); while (getNextOldHistoryLocked(rec)) { hprinter.printNextItem(pw, rec, now); } finishIteratingOldHistoryLocked(); pw.println(""); } Loading Loading @@ -1918,6 +1960,8 @@ public abstract class BatteryStats implements Parcelable { @SuppressWarnings("unused") public void dumpCheckinLocked(PrintWriter pw, String[] args, List<ApplicationInfo> apps) { prepareForDumpLocked(); boolean isUnpluggedOnly = false; for (String arg : args) { Loading core/java/com/android/internal/os/BatteryStatsImpl.java +214 −20 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.util.Log; import android.util.LogWriter; import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.Slog; Loading Loading @@ -70,7 +71,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version private static final int VERSION = 54; private static final int VERSION = 57; // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; Loading Loading @@ -154,11 +155,26 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mHaveBatteryLevel = false; boolean mRecordingHistory = true; int mNumHistoryItems; static final int MAX_HISTORY_BUFFER = 64*1024; // 64KB static final int MAX_MAX_HISTORY_BUFFER = 92*1024; // 92KB final Parcel mHistoryBuffer = Parcel.obtain(); final HistoryItem mHistoryLastWritten = new HistoryItem(); final HistoryItem mHistoryLastLastWritten = new HistoryItem(); int mHistoryBufferLastPos = -1; boolean mHistoryOverflow = false; long mLastHistoryTime = 0; final HistoryItem mHistoryCur = new HistoryItem(); HistoryItem mHistory; HistoryItem mHistoryEnd; HistoryItem mHistoryLastEnd; HistoryItem mHistoryCache; final HistoryItem mHistoryCur = new HistoryItem(); private HistoryItem mHistoryIterator; private boolean mReadOverflow; private boolean mIteratingHistory; int mStartCount; Loading Loading @@ -1189,9 +1205,82 @@ public final class BatteryStatsImpl extends BatteryStats { mBtHeadset = headset; } int mChangedBufferStates = 0; void addHistoryBufferLocked(long curTime) { if (!mHaveBatteryLevel || !mRecordingHistory) { return; } if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE && (mHistoryBaseTime+curTime) < (mHistoryLastWritten.time+2000) && ((mHistoryLastWritten.states^mHistoryCur.states)&mChangedBufferStates) == 0) { // If the current is the same as the one before, then we no // longer need the entry. mHistoryBuffer.setDataSize(mHistoryBufferLastPos); mHistoryBuffer.setDataPosition(mHistoryBufferLastPos); mHistoryBufferLastPos = -1; if (mHistoryLastLastWritten.cmd == HistoryItem.CMD_UPDATE && mHistoryLastLastWritten.same(mHistoryCur)) { // If this results in us returning to the state written // prior to the last one, then we can just delete the last // written one and drop the new one. Nothing more to do. mHistoryLastWritten.setTo(mHistoryLastLastWritten); mHistoryLastLastWritten.cmd = HistoryItem.CMD_NULL; return; } mChangedBufferStates |= mHistoryLastWritten.states^mHistoryCur.states; curTime = mHistoryLastWritten.time - mHistoryBaseTime; } else { mChangedBufferStates = 0; } final int dataSize = mHistoryBuffer.dataSize(); if (dataSize >= MAX_HISTORY_BUFFER) { if (!mHistoryOverflow) { mHistoryOverflow = true; addHistoryBufferLocked(curTime, HistoryItem.CMD_OVERFLOW); } // Once we've reached the maximum number of items, we only // 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 && (dataSize >= MAX_MAX_HISTORY_BUFFER || ((mHistoryEnd.states^mHistoryCur.states) & HistoryItem.MOST_INTERESTING_STATES) == 0)) { return; } } addHistoryBufferLocked(curTime, HistoryItem.CMD_UPDATE); } void addHistoryBufferLocked(long curTime, byte cmd) { int origPos = 0; if (mIteratingHistory) { origPos = mHistoryBuffer.dataPosition(); mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize()); } mHistoryBufferLastPos = mHistoryBuffer.dataPosition(); mHistoryLastLastWritten.setTo(mHistoryLastWritten); mHistoryLastWritten.setTo(mHistoryBaseTime + curTime, cmd, mHistoryCur); mHistoryLastWritten.writeDelta(mHistoryBuffer, mHistoryLastLastWritten); mLastHistoryTime = curTime; if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos + " now " + mHistoryBuffer.dataPosition() + " size is now " + mHistoryBuffer.dataSize()); if (mIteratingHistory) { mHistoryBuffer.setDataPosition(origPos); } } int mChangedStates = 0; void addHistoryRecordLocked(long curTime) { addHistoryBufferLocked(curTime); if (!mHaveBatteryLevel || !mRecordingHistory) { return; } Loading Loading @@ -1268,6 +1357,7 @@ public final class BatteryStatsImpl extends BatteryStats { } void clearHistoryLocked() { if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!"); if (mHistory != null) { mHistoryEnd.next = mHistoryCache; mHistoryCache = mHistory; Loading @@ -1275,6 +1365,15 @@ public final class BatteryStatsImpl extends BatteryStats { } mNumHistoryItems = 0; mHistoryBaseTime = 0; mLastHistoryTime = 0; mHistoryBuffer.setDataSize(0); mHistoryBuffer.setDataPosition(0); mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER/2); mHistoryLastLastWritten.cmd = HistoryItem.CMD_NULL; mHistoryLastWritten.cmd = HistoryItem.CMD_NULL; mHistoryBufferLastPos = -1; mHistoryOverflow = false; } public void doUnplugLocked(long batteryUptime, long batteryRealtime) { Loading Loading @@ -3910,11 +4009,13 @@ public final class BatteryStatsImpl extends BatteryStats { mDischargeUnplugLevel = 0; mDischargeCurrentLevel = 0; initDischarge(); clearHistoryLocked(); } public BatteryStatsImpl(Parcel p) { mFile = null; mHandler = null; clearHistoryLocked(); readFromParcel(p); } Loading @@ -3932,25 +4033,79 @@ public final class BatteryStatsImpl extends BatteryStats { } } private HistoryItem mHistoryIterator; public boolean startIteratingHistoryLocked() { @Override public boolean startIteratingOldHistoryLocked() { if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize() + " pos=" + mHistoryBuffer.dataPosition()); mHistoryBuffer.setDataPosition(0); mReadOverflow = false; mIteratingHistory = true; return (mHistoryIterator = mHistory) != null; } public boolean getNextHistoryLocked(HistoryItem out) { @Override public boolean getNextOldHistoryLocked(HistoryItem out) { boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize(); if (!end) { mHistoryLastWritten.readDelta(mHistoryBuffer, null); mReadOverflow |= mHistoryLastWritten.cmd == HistoryItem.CMD_OVERFLOW; } HistoryItem cur = mHistoryIterator; if (cur == null) { if (!mReadOverflow && !end) { Slog.w(TAG, "Old history ends before new history!"); } return false; } out.setTo(cur); mHistoryIterator = cur.next; if (!mReadOverflow) { if (end) { Slog.w(TAG, "New history ends before old history!"); } else if (!out.same(mHistoryLastWritten)) { long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); PrintWriter pw = new PrintWriter(new LogWriter(android.util.Log.WARN, TAG)); pw.println("Histories differ!"); pw.println("Old history:"); (new HistoryPrinter()).printNextItem(pw, out, now); pw.println("New history:"); (new HistoryPrinter()).printNextItem(pw, mHistoryLastWritten, now); } } return true; } @Override public HistoryItem getHistory() { return mHistory; public void finishIteratingOldHistoryLocked() { mIteratingHistory = false; mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize()); } @Override public boolean startIteratingHistoryLocked() { if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize() + " pos=" + mHistoryBuffer.dataPosition()); mHistoryBuffer.setDataPosition(0); mReadOverflow = false; mIteratingHistory = true; return mHistoryBuffer.dataSize() > 0; } @Override public boolean getNextHistoryLocked(HistoryItem out) { boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize(); if (end) { return false; } out.readDelta(mHistoryBuffer, null); return true; } @Override public void finishIteratingHistoryLocked() { mIteratingHistory = false; mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize()); } @Override Loading Loading @@ -4697,7 +4852,9 @@ public final class BatteryStatsImpl extends BatteryStats { Slog.e("BatteryStats", "Error reading battery statistics", e); } addHistoryRecordLocked(SystemClock.elapsedRealtime(), HistoryItem.CMD_START); long now = SystemClock.elapsedRealtime(); addHistoryRecordLocked(now, HistoryItem.CMD_START); addHistoryBufferLocked(now, HistoryItem.CMD_START); } public int describeContents() { Loading @@ -4705,30 +4862,54 @@ public final class BatteryStatsImpl extends BatteryStats { } void readHistory(Parcel in) { mHistory = mHistoryEnd = mHistoryCache = null; mHistoryBaseTime = 0; long time; while ((time=in.readLong()) >= 0) { HistoryItem rec = new HistoryItem(time, in); addHistoryRecordLocked(rec); if (rec.time > mHistoryBaseTime) { mHistoryBaseTime = rec.time; } mHistoryBaseTime = in.readLong(); mHistoryBuffer.setDataSize(0); mHistoryBuffer.setDataPosition(0); int bufSize = in.readInt(); int curPos = in.dataPosition(); if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) { Slog.w(TAG, "File corrupt: history data buffer too large " + bufSize); } else if ((bufSize&~3) != bufSize) { Slog.w(TAG, "File corrupt: history data buffer not aligned " + bufSize); } else { if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize + " bytes at " + curPos); mHistoryBuffer.appendFrom(in, curPos, bufSize); in.setDataPosition(curPos + bufSize); } long oldnow = SystemClock.elapsedRealtime() - (5*60*100); long oldnow = SystemClock.elapsedRealtime() - (5*60*1000); if (oldnow > 0) { // If the system process has restarted, but not the entire // system, then the mHistoryBaseTime already accounts for // much of the elapsed time. We thus want to adjust it back, // to avoid large gaps in the data. We determine we are // in this case by arbitrarily saying it is so if at this // point in boot the elapsed time is already more than 5 seconds. // point in boot the elapsed time is already more than 5 minutes. mHistoryBaseTime -= oldnow; } } void readOldHistory(Parcel in) { mHistory = mHistoryEnd = mHistoryCache = null; long time; while ((time=in.readLong()) >= 0) { HistoryItem rec = new HistoryItem(time, in); addHistoryRecordLocked(rec); } } void writeHistory(Parcel out) { out.writeLong(mLastHistoryTime); out.writeInt(mHistoryBuffer.dataSize()); if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: " + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition()); out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize()); } void writeOldHistory(Parcel out) { HistoryItem rec = mHistory; while (rec != null) { if (rec.time >= 0) rec.writeToParcel(out, 0); Loading @@ -4746,6 +4927,7 @@ public final class BatteryStatsImpl extends BatteryStats { } readHistory(in); readOldHistory(in); mStartCount = in.readInt(); mBatteryUptime = in.readLong(); Loading Loading @@ -4935,6 +5117,9 @@ public final class BatteryStatsImpl extends BatteryStats { * @param out the Parcel to be written to. */ public void writeSummaryToParcel(Parcel out) { // Need to update with current kernel wake lock counts. updateKernelWakelocksLocked(); final long NOW_SYS = SystemClock.uptimeMillis() * 1000; final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; final long NOW = getBatteryUptimeLocked(NOW_SYS); Loading @@ -4943,6 +5128,7 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(VERSION); writeHistory(out); writeOldHistory(out); out.writeInt(mStartCount); out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED)); Loading Loading @@ -5256,6 +5442,9 @@ public final class BatteryStatsImpl extends BatteryStats { @SuppressWarnings("unused") void writeToParcelLocked(Parcel out, boolean inclUids, int flags) { // Need to update with current kernel wake lock counts. updateKernelWakelocksLocked(); final long uSecUptime = SystemClock.uptimeMillis() * 1000; final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; final long batteryUptime = getBatteryUptimeLocked(uSecUptime); Loading Loading @@ -5358,6 +5547,11 @@ public final class BatteryStatsImpl extends BatteryStats { } }; public void prepareForDumpLocked() { // Need to retrieve current kernel wake lock stats before printing. updateKernelWakelocksLocked(); } public void dumpLocked(PrintWriter pw) { if (DEBUG) { Printer pr = new PrintWriterPrinter(pw); Loading libs/binder/Parcel.cpp +11 −7 Original line number Diff line number Diff line Loading @@ -338,7 +338,7 @@ void Parcel::setDataPosition(size_t pos) const status_t Parcel::setDataCapacity(size_t size) { if (size > mDataSize) return continueWrite(size); if (size > mDataCapacity) return continueWrite(size); return NO_ERROR; } Loading Loading @@ -386,11 +386,13 @@ status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len) } int numObjects = lastIndex - firstIndex + 1; if ((mDataSize+len) > mDataCapacity) { // grow data err = growData(len); if (err != NO_ERROR) { return err; } } // append data memcpy(mData + mDataPos, data + offset, len); Loading Loading @@ -1384,8 +1386,10 @@ status_t Parcel::continueWrite(size_t desired) return NO_MEMORY; } } else { if (mDataSize > desired) { mDataSize = desired; LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize); } if (mDataPos > desired) { mDataPos = desired; LOGV("continueWrite Setting data pos of %p to %d\n", this, mDataPos); Loading services/java/com/android/server/am/BatteryStatsService.java +13 −0 Original line number Diff line number Diff line Loading @@ -449,6 +449,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { boolean isCheckin = false; boolean noOutput = false; if (args != null) { for (String arg : args) { if ("--checkin".equals(arg)) { Loading @@ -457,10 +458,22 @@ public final class BatteryStatsService extends IBatteryStats.Stub { synchronized (mStats) { mStats.resetAllStatsLocked(); pw.println("Battery stats reset."); noOutput = true; } } else if ("--write".equals(arg)) { synchronized (mStats) { mStats.writeSyncLocked(); pw.println("Battery stats written."); noOutput = true; } } else { pw.println("Unknown option: " + arg); } } } if (noOutput) { return; } if (isCheckin) { List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0); synchronized (mStats) { Loading Loading
core/java/android/os/BatteryStats.java +171 −127 Original line number Diff line number Diff line Loading @@ -412,6 +412,7 @@ public abstract class BatteryStats implements Parcelable { public long time; public static final byte CMD_NULL = -1; public static final byte CMD_UPDATE = 0; public static final byte CMD_START = 1; public static final byte CMD_OVERFLOW = 2; Loading Loading @@ -466,16 +467,7 @@ public abstract class BatteryStats implements Parcelable { public HistoryItem(long time, Parcel src) { this.time = time; int bat = src.readInt(); cmd = (byte)(bat&0xff); batteryLevel = (byte)((bat>>8)&0xff); batteryStatus = (byte)((bat>>16)&0xf); batteryHealth = (byte)((bat>>20)&0xf); batteryPlugType = (byte)((bat>>24)&0xf); bat = src.readInt(); batteryTemperature = (char)(bat&0xffff); batteryVoltage = (char)((bat>>16)&0xffff); states = src.readInt(); readFromParcel(src); } public int describeContents() { Loading @@ -496,6 +488,28 @@ public abstract class BatteryStats implements Parcelable { dest.writeInt(states); } public void writeDelta(Parcel dest, HistoryItem last) { writeToParcel(dest, 0); } private void readFromParcel(Parcel src) { int bat = src.readInt(); cmd = (byte)(bat&0xff); batteryLevel = (byte)((bat>>8)&0xff); batteryStatus = (byte)((bat>>16)&0xf); batteryHealth = (byte)((bat>>20)&0xf); batteryPlugType = (byte)((bat>>24)&0xf); bat = src.readInt(); batteryTemperature = (char)(bat&0xffff); batteryVoltage = (char)((bat>>16)&0xffff); states = src.readInt(); } public void readDelta(Parcel src, HistoryItem last) { time = src.readLong(); readFromParcel(src); } public void setTo(HistoryItem o) { time = o.time; cmd = o.cmd; Loading Loading @@ -556,10 +570,13 @@ public abstract class BatteryStats implements Parcelable { public abstract boolean getNextHistoryLocked(HistoryItem out); /** * Return the current history of battery state changes. */ public abstract HistoryItem getHistory(); public abstract void finishIteratingHistoryLocked(); public abstract boolean startIteratingOldHistoryLocked(); public abstract boolean getNextOldHistoryLocked(HistoryItem out); public abstract void finishIteratingOldHistoryLocked(); /** * Return the base time offset for the battery history. Loading Loading @@ -1729,7 +1746,7 @@ public abstract class BatteryStats implements Parcelable { } } void printBitDescriptions(PrintWriter pw, int oldval, int newval, BitDescription[] descriptions) { static void printBitDescriptions(PrintWriter pw, int oldval, int newval, BitDescription[] descriptions) { int diff = oldval ^ newval; if (diff == 0) return; for (int i=0; i<descriptions.length; i++) { Loading @@ -1753,24 +1770,18 @@ public abstract class BatteryStats implements Parcelable { } } /** * Dumps a human-readable summary of the battery statistics to the given PrintWriter. * * @param pw a Printer to receive the dump output. */ @SuppressWarnings("unused") public void dumpLocked(PrintWriter pw) { final HistoryItem rec = new HistoryItem(); if (startIteratingHistoryLocked()) { pw.println("Battery History:"); long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); public void prepareForDumpLocked() { } public static class HistoryPrinter { int oldState = 0; int oldStatus = -1; int oldHealth = -1; int oldPlug = -1; int oldTemp = -1; int oldVolt = -1; while (getNextHistoryLocked(rec)) { public void printNextItem(PrintWriter pw, HistoryItem rec, long now) { pw.print(" "); TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN); pw.print(" "); Loading Loading @@ -1876,6 +1887,37 @@ public abstract class BatteryStats implements Parcelable { } oldState = rec.states; } } /** * Dumps a human-readable summary of the battery statistics to the given PrintWriter. * * @param pw a Printer to receive the dump output. */ @SuppressWarnings("unused") public void dumpLocked(PrintWriter pw) { prepareForDumpLocked(); long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); final HistoryItem rec = new HistoryItem(); if (startIteratingHistoryLocked()) { pw.println("Battery History:"); HistoryPrinter hprinter = new HistoryPrinter(); while (getNextHistoryLocked(rec)) { hprinter.printNextItem(pw, rec, now); } finishIteratingHistoryLocked(); pw.println(""); } if (startIteratingOldHistoryLocked()) { pw.println("Old battery History:"); HistoryPrinter hprinter = new HistoryPrinter(); while (getNextOldHistoryLocked(rec)) { hprinter.printNextItem(pw, rec, now); } finishIteratingOldHistoryLocked(); pw.println(""); } Loading Loading @@ -1918,6 +1960,8 @@ public abstract class BatteryStats implements Parcelable { @SuppressWarnings("unused") public void dumpCheckinLocked(PrintWriter pw, String[] args, List<ApplicationInfo> apps) { prepareForDumpLocked(); boolean isUnpluggedOnly = false; for (String arg : args) { Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +214 −20 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.util.Log; import android.util.LogWriter; import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.Slog; Loading Loading @@ -70,7 +71,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version private static final int VERSION = 54; private static final int VERSION = 57; // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; Loading Loading @@ -154,11 +155,26 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mHaveBatteryLevel = false; boolean mRecordingHistory = true; int mNumHistoryItems; static final int MAX_HISTORY_BUFFER = 64*1024; // 64KB static final int MAX_MAX_HISTORY_BUFFER = 92*1024; // 92KB final Parcel mHistoryBuffer = Parcel.obtain(); final HistoryItem mHistoryLastWritten = new HistoryItem(); final HistoryItem mHistoryLastLastWritten = new HistoryItem(); int mHistoryBufferLastPos = -1; boolean mHistoryOverflow = false; long mLastHistoryTime = 0; final HistoryItem mHistoryCur = new HistoryItem(); HistoryItem mHistory; HistoryItem mHistoryEnd; HistoryItem mHistoryLastEnd; HistoryItem mHistoryCache; final HistoryItem mHistoryCur = new HistoryItem(); private HistoryItem mHistoryIterator; private boolean mReadOverflow; private boolean mIteratingHistory; int mStartCount; Loading Loading @@ -1189,9 +1205,82 @@ public final class BatteryStatsImpl extends BatteryStats { mBtHeadset = headset; } int mChangedBufferStates = 0; void addHistoryBufferLocked(long curTime) { if (!mHaveBatteryLevel || !mRecordingHistory) { return; } if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE && (mHistoryBaseTime+curTime) < (mHistoryLastWritten.time+2000) && ((mHistoryLastWritten.states^mHistoryCur.states)&mChangedBufferStates) == 0) { // If the current is the same as the one before, then we no // longer need the entry. mHistoryBuffer.setDataSize(mHistoryBufferLastPos); mHistoryBuffer.setDataPosition(mHistoryBufferLastPos); mHistoryBufferLastPos = -1; if (mHistoryLastLastWritten.cmd == HistoryItem.CMD_UPDATE && mHistoryLastLastWritten.same(mHistoryCur)) { // If this results in us returning to the state written // prior to the last one, then we can just delete the last // written one and drop the new one. Nothing more to do. mHistoryLastWritten.setTo(mHistoryLastLastWritten); mHistoryLastLastWritten.cmd = HistoryItem.CMD_NULL; return; } mChangedBufferStates |= mHistoryLastWritten.states^mHistoryCur.states; curTime = mHistoryLastWritten.time - mHistoryBaseTime; } else { mChangedBufferStates = 0; } final int dataSize = mHistoryBuffer.dataSize(); if (dataSize >= MAX_HISTORY_BUFFER) { if (!mHistoryOverflow) { mHistoryOverflow = true; addHistoryBufferLocked(curTime, HistoryItem.CMD_OVERFLOW); } // Once we've reached the maximum number of items, we only // 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 && (dataSize >= MAX_MAX_HISTORY_BUFFER || ((mHistoryEnd.states^mHistoryCur.states) & HistoryItem.MOST_INTERESTING_STATES) == 0)) { return; } } addHistoryBufferLocked(curTime, HistoryItem.CMD_UPDATE); } void addHistoryBufferLocked(long curTime, byte cmd) { int origPos = 0; if (mIteratingHistory) { origPos = mHistoryBuffer.dataPosition(); mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize()); } mHistoryBufferLastPos = mHistoryBuffer.dataPosition(); mHistoryLastLastWritten.setTo(mHistoryLastWritten); mHistoryLastWritten.setTo(mHistoryBaseTime + curTime, cmd, mHistoryCur); mHistoryLastWritten.writeDelta(mHistoryBuffer, mHistoryLastLastWritten); mLastHistoryTime = curTime; if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos + " now " + mHistoryBuffer.dataPosition() + " size is now " + mHistoryBuffer.dataSize()); if (mIteratingHistory) { mHistoryBuffer.setDataPosition(origPos); } } int mChangedStates = 0; void addHistoryRecordLocked(long curTime) { addHistoryBufferLocked(curTime); if (!mHaveBatteryLevel || !mRecordingHistory) { return; } Loading Loading @@ -1268,6 +1357,7 @@ public final class BatteryStatsImpl extends BatteryStats { } void clearHistoryLocked() { if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!"); if (mHistory != null) { mHistoryEnd.next = mHistoryCache; mHistoryCache = mHistory; Loading @@ -1275,6 +1365,15 @@ public final class BatteryStatsImpl extends BatteryStats { } mNumHistoryItems = 0; mHistoryBaseTime = 0; mLastHistoryTime = 0; mHistoryBuffer.setDataSize(0); mHistoryBuffer.setDataPosition(0); mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER/2); mHistoryLastLastWritten.cmd = HistoryItem.CMD_NULL; mHistoryLastWritten.cmd = HistoryItem.CMD_NULL; mHistoryBufferLastPos = -1; mHistoryOverflow = false; } public void doUnplugLocked(long batteryUptime, long batteryRealtime) { Loading Loading @@ -3910,11 +4009,13 @@ public final class BatteryStatsImpl extends BatteryStats { mDischargeUnplugLevel = 0; mDischargeCurrentLevel = 0; initDischarge(); clearHistoryLocked(); } public BatteryStatsImpl(Parcel p) { mFile = null; mHandler = null; clearHistoryLocked(); readFromParcel(p); } Loading @@ -3932,25 +4033,79 @@ public final class BatteryStatsImpl extends BatteryStats { } } private HistoryItem mHistoryIterator; public boolean startIteratingHistoryLocked() { @Override public boolean startIteratingOldHistoryLocked() { if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize() + " pos=" + mHistoryBuffer.dataPosition()); mHistoryBuffer.setDataPosition(0); mReadOverflow = false; mIteratingHistory = true; return (mHistoryIterator = mHistory) != null; } public boolean getNextHistoryLocked(HistoryItem out) { @Override public boolean getNextOldHistoryLocked(HistoryItem out) { boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize(); if (!end) { mHistoryLastWritten.readDelta(mHistoryBuffer, null); mReadOverflow |= mHistoryLastWritten.cmd == HistoryItem.CMD_OVERFLOW; } HistoryItem cur = mHistoryIterator; if (cur == null) { if (!mReadOverflow && !end) { Slog.w(TAG, "Old history ends before new history!"); } return false; } out.setTo(cur); mHistoryIterator = cur.next; if (!mReadOverflow) { if (end) { Slog.w(TAG, "New history ends before old history!"); } else if (!out.same(mHistoryLastWritten)) { long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); PrintWriter pw = new PrintWriter(new LogWriter(android.util.Log.WARN, TAG)); pw.println("Histories differ!"); pw.println("Old history:"); (new HistoryPrinter()).printNextItem(pw, out, now); pw.println("New history:"); (new HistoryPrinter()).printNextItem(pw, mHistoryLastWritten, now); } } return true; } @Override public HistoryItem getHistory() { return mHistory; public void finishIteratingOldHistoryLocked() { mIteratingHistory = false; mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize()); } @Override public boolean startIteratingHistoryLocked() { if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize() + " pos=" + mHistoryBuffer.dataPosition()); mHistoryBuffer.setDataPosition(0); mReadOverflow = false; mIteratingHistory = true; return mHistoryBuffer.dataSize() > 0; } @Override public boolean getNextHistoryLocked(HistoryItem out) { boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize(); if (end) { return false; } out.readDelta(mHistoryBuffer, null); return true; } @Override public void finishIteratingHistoryLocked() { mIteratingHistory = false; mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize()); } @Override Loading Loading @@ -4697,7 +4852,9 @@ public final class BatteryStatsImpl extends BatteryStats { Slog.e("BatteryStats", "Error reading battery statistics", e); } addHistoryRecordLocked(SystemClock.elapsedRealtime(), HistoryItem.CMD_START); long now = SystemClock.elapsedRealtime(); addHistoryRecordLocked(now, HistoryItem.CMD_START); addHistoryBufferLocked(now, HistoryItem.CMD_START); } public int describeContents() { Loading @@ -4705,30 +4862,54 @@ public final class BatteryStatsImpl extends BatteryStats { } void readHistory(Parcel in) { mHistory = mHistoryEnd = mHistoryCache = null; mHistoryBaseTime = 0; long time; while ((time=in.readLong()) >= 0) { HistoryItem rec = new HistoryItem(time, in); addHistoryRecordLocked(rec); if (rec.time > mHistoryBaseTime) { mHistoryBaseTime = rec.time; } mHistoryBaseTime = in.readLong(); mHistoryBuffer.setDataSize(0); mHistoryBuffer.setDataPosition(0); int bufSize = in.readInt(); int curPos = in.dataPosition(); if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) { Slog.w(TAG, "File corrupt: history data buffer too large " + bufSize); } else if ((bufSize&~3) != bufSize) { Slog.w(TAG, "File corrupt: history data buffer not aligned " + bufSize); } else { if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize + " bytes at " + curPos); mHistoryBuffer.appendFrom(in, curPos, bufSize); in.setDataPosition(curPos + bufSize); } long oldnow = SystemClock.elapsedRealtime() - (5*60*100); long oldnow = SystemClock.elapsedRealtime() - (5*60*1000); if (oldnow > 0) { // If the system process has restarted, but not the entire // system, then the mHistoryBaseTime already accounts for // much of the elapsed time. We thus want to adjust it back, // to avoid large gaps in the data. We determine we are // in this case by arbitrarily saying it is so if at this // point in boot the elapsed time is already more than 5 seconds. // point in boot the elapsed time is already more than 5 minutes. mHistoryBaseTime -= oldnow; } } void readOldHistory(Parcel in) { mHistory = mHistoryEnd = mHistoryCache = null; long time; while ((time=in.readLong()) >= 0) { HistoryItem rec = new HistoryItem(time, in); addHistoryRecordLocked(rec); } } void writeHistory(Parcel out) { out.writeLong(mLastHistoryTime); out.writeInt(mHistoryBuffer.dataSize()); if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: " + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition()); out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize()); } void writeOldHistory(Parcel out) { HistoryItem rec = mHistory; while (rec != null) { if (rec.time >= 0) rec.writeToParcel(out, 0); Loading @@ -4746,6 +4927,7 @@ public final class BatteryStatsImpl extends BatteryStats { } readHistory(in); readOldHistory(in); mStartCount = in.readInt(); mBatteryUptime = in.readLong(); Loading Loading @@ -4935,6 +5117,9 @@ public final class BatteryStatsImpl extends BatteryStats { * @param out the Parcel to be written to. */ public void writeSummaryToParcel(Parcel out) { // Need to update with current kernel wake lock counts. updateKernelWakelocksLocked(); final long NOW_SYS = SystemClock.uptimeMillis() * 1000; final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; final long NOW = getBatteryUptimeLocked(NOW_SYS); Loading @@ -4943,6 +5128,7 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(VERSION); writeHistory(out); writeOldHistory(out); out.writeInt(mStartCount); out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED)); Loading Loading @@ -5256,6 +5442,9 @@ public final class BatteryStatsImpl extends BatteryStats { @SuppressWarnings("unused") void writeToParcelLocked(Parcel out, boolean inclUids, int flags) { // Need to update with current kernel wake lock counts. updateKernelWakelocksLocked(); final long uSecUptime = SystemClock.uptimeMillis() * 1000; final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; final long batteryUptime = getBatteryUptimeLocked(uSecUptime); Loading Loading @@ -5358,6 +5547,11 @@ public final class BatteryStatsImpl extends BatteryStats { } }; public void prepareForDumpLocked() { // Need to retrieve current kernel wake lock stats before printing. updateKernelWakelocksLocked(); } public void dumpLocked(PrintWriter pw) { if (DEBUG) { Printer pr = new PrintWriterPrinter(pw); Loading
libs/binder/Parcel.cpp +11 −7 Original line number Diff line number Diff line Loading @@ -338,7 +338,7 @@ void Parcel::setDataPosition(size_t pos) const status_t Parcel::setDataCapacity(size_t size) { if (size > mDataSize) return continueWrite(size); if (size > mDataCapacity) return continueWrite(size); return NO_ERROR; } Loading Loading @@ -386,11 +386,13 @@ status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len) } int numObjects = lastIndex - firstIndex + 1; if ((mDataSize+len) > mDataCapacity) { // grow data err = growData(len); if (err != NO_ERROR) { return err; } } // append data memcpy(mData + mDataPos, data + offset, len); Loading Loading @@ -1384,8 +1386,10 @@ status_t Parcel::continueWrite(size_t desired) return NO_MEMORY; } } else { if (mDataSize > desired) { mDataSize = desired; LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize); } if (mDataPos > desired) { mDataPos = desired; LOGV("continueWrite Setting data pos of %p to %d\n", this, mDataPos); Loading
services/java/com/android/server/am/BatteryStatsService.java +13 −0 Original line number Diff line number Diff line Loading @@ -449,6 +449,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { boolean isCheckin = false; boolean noOutput = false; if (args != null) { for (String arg : args) { if ("--checkin".equals(arg)) { Loading @@ -457,10 +458,22 @@ public final class BatteryStatsService extends IBatteryStats.Stub { synchronized (mStats) { mStats.resetAllStatsLocked(); pw.println("Battery stats reset."); noOutput = true; } } else if ("--write".equals(arg)) { synchronized (mStats) { mStats.writeSyncLocked(); pw.println("Battery stats written."); noOutput = true; } } else { pw.println("Unknown option: " + arg); } } } if (noOutput) { return; } if (isCheckin) { List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0); synchronized (mStats) { Loading