diff options
author | Dianne Hackborn <hackbod@google.com> | 2011-04-13 18:15:56 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2011-04-14 10:57:22 -0700 |
commit | 0ffc988a7f47013805d5abeed1c20f159b3bd799 (patch) | |
tree | f9873ba8872388b88d75a3d83144e03e7c3f59f4 | |
parent | 5cde33b7d14841677414fa9f43a043bb4a89ffa7 (diff) | |
download | frameworks_base-0ffc988a7f47013805d5abeed1c20f159b3bd799.zip frameworks_base-0ffc988a7f47013805d5abeed1c20f159b3bd799.tar.gz frameworks_base-0ffc988a7f47013805d5abeed1c20f159b3bd799.tar.bz2 |
Rewrite battery history storage.
We now write battery history directly into a buffer, instead of
creating objects. This allows for more efficient storage; later
it can be even better because we can only write deltas.
The old code is still there temporarily for validation.
Change-Id: I9707d4d8ff30855be8ebdc93bc078911040d8e0b
-rw-r--r-- | core/java/android/os/BatteryStats.java | 298 | ||||
-rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 234 | ||||
-rw-r--r-- | libs/binder/Parcel.cpp | 18 | ||||
-rw-r--r-- | services/java/com/android/server/am/BatteryStatsService.java | 13 |
4 files changed, 409 insertions, 154 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 90e2e79..d7483ba 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -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; @@ -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() { @@ -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; @@ -556,11 +570,14 @@ 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. */ @@ -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++) { @@ -1753,6 +1770,125 @@ public abstract class BatteryStats implements Parcelable { } } + 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; + + public void printNextItem(PrintWriter pw, HistoryItem rec, long now) { + pw.print(" "); + TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN); + pw.print(" "); + if (rec.cmd == HistoryItem.CMD_START) { + pw.println(" START"); + } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) { + pw.println(" *OVERFLOW*"); + } else { + if (rec.batteryLevel < 10) pw.print("00"); + else if (rec.batteryLevel < 100) pw.print("0"); + pw.print(rec.batteryLevel); + pw.print(" "); + 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 (oldStatus != rec.batteryStatus) { + oldStatus = rec.batteryStatus; + pw.print(" status="); + switch (oldStatus) { + case BatteryManager.BATTERY_STATUS_UNKNOWN: + pw.print("unknown"); + break; + case BatteryManager.BATTERY_STATUS_CHARGING: + pw.print("charging"); + break; + case BatteryManager.BATTERY_STATUS_DISCHARGING: + pw.print("discharging"); + break; + case BatteryManager.BATTERY_STATUS_NOT_CHARGING: + pw.print("not-charging"); + break; + case BatteryManager.BATTERY_STATUS_FULL: + pw.print("full"); + break; + default: + pw.print(oldStatus); + break; + } + } + if (oldHealth != rec.batteryHealth) { + oldHealth = rec.batteryHealth; + pw.print(" health="); + switch (oldHealth) { + case BatteryManager.BATTERY_HEALTH_UNKNOWN: + pw.print("unknown"); + break; + case BatteryManager.BATTERY_HEALTH_GOOD: + pw.print("good"); + break; + case BatteryManager.BATTERY_HEALTH_OVERHEAT: + pw.print("overheat"); + break; + case BatteryManager.BATTERY_HEALTH_DEAD: + pw.print("dead"); + break; + case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE: + pw.print("over-voltage"); + break; + case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE: + pw.print("failure"); + break; + default: + pw.print(oldHealth); + break; + } + } + if (oldPlug != rec.batteryPlugType) { + oldPlug = rec.batteryPlugType; + pw.print(" plug="); + switch (oldPlug) { + case 0: + pw.print("none"); + break; + case BatteryManager.BATTERY_PLUGGED_AC: + pw.print("ac"); + break; + case BatteryManager.BATTERY_PLUGGED_USB: + pw.print("usb"); + break; + default: + pw.print(oldPlug); + break; + } + } + if (oldTemp != rec.batteryTemperature) { + oldTemp = rec.batteryTemperature; + pw.print(" temp="); + pw.print(oldTemp); + } + if (oldVolt != rec.batteryVoltage) { + oldVolt = rec.batteryVoltage; + pw.print(" volt="); + pw.print(oldVolt); + } + printBitDescriptions(pw, oldState, rec.states, + HISTORY_STATE_DESCRIPTIONS); + pw.println(); + } + oldState = rec.states; + } + } + /** * Dumps a human-readable summary of the battery statistics to the given PrintWriter. * @@ -1760,122 +1896,28 @@ public abstract class BatteryStats implements Parcelable { */ @SuppressWarnings("unused") public void dumpLocked(PrintWriter pw) { + prepareForDumpLocked(); + + long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); + final HistoryItem rec = new HistoryItem(); if (startIteratingHistoryLocked()) { pw.println("Battery History:"); - long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); - int oldState = 0; - int oldStatus = -1; - int oldHealth = -1; - int oldPlug = -1; - int oldTemp = -1; - int oldVolt = -1; + HistoryPrinter hprinter = new HistoryPrinter(); while (getNextHistoryLocked(rec)) { - pw.print(" "); - TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN); - pw.print(" "); - if (rec.cmd == HistoryItem.CMD_START) { - pw.println(" START"); - } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) { - pw.println(" *OVERFLOW*"); - } else { - if (rec.batteryLevel < 10) pw.print("00"); - else if (rec.batteryLevel < 100) pw.print("0"); - pw.print(rec.batteryLevel); - pw.print(" "); - 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 (oldStatus != rec.batteryStatus) { - oldStatus = rec.batteryStatus; - pw.print(" status="); - switch (oldStatus) { - case BatteryManager.BATTERY_STATUS_UNKNOWN: - pw.print("unknown"); - break; - case BatteryManager.BATTERY_STATUS_CHARGING: - pw.print("charging"); - break; - case BatteryManager.BATTERY_STATUS_DISCHARGING: - pw.print("discharging"); - break; - case BatteryManager.BATTERY_STATUS_NOT_CHARGING: - pw.print("not-charging"); - break; - case BatteryManager.BATTERY_STATUS_FULL: - pw.print("full"); - break; - default: - pw.print(oldStatus); - break; - } - } - if (oldHealth != rec.batteryHealth) { - oldHealth = rec.batteryHealth; - pw.print(" health="); - switch (oldHealth) { - case BatteryManager.BATTERY_HEALTH_UNKNOWN: - pw.print("unknown"); - break; - case BatteryManager.BATTERY_HEALTH_GOOD: - pw.print("good"); - break; - case BatteryManager.BATTERY_HEALTH_OVERHEAT: - pw.print("overheat"); - break; - case BatteryManager.BATTERY_HEALTH_DEAD: - pw.print("dead"); - break; - case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE: - pw.print("over-voltage"); - break; - case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE: - pw.print("failure"); - break; - default: - pw.print(oldHealth); - break; - } - } - if (oldPlug != rec.batteryPlugType) { - oldPlug = rec.batteryPlugType; - pw.print(" plug="); - switch (oldPlug) { - case 0: - pw.print("none"); - break; - case BatteryManager.BATTERY_PLUGGED_AC: - pw.print("ac"); - break; - case BatteryManager.BATTERY_PLUGGED_USB: - pw.print("usb"); - break; - default: - pw.print(oldPlug); - break; - } - } - if (oldTemp != rec.batteryTemperature) { - oldTemp = rec.batteryTemperature; - pw.print(" temp="); - pw.print(oldTemp); - } - if (oldVolt != rec.batteryVoltage) { - oldVolt = rec.batteryVoltage; - pw.print(" volt="); - pw.print(oldVolt); - } - printBitDescriptions(pw, oldState, rec.states, - HISTORY_STATE_DESCRIPTIONS); - pw.println(); - } - oldState = rec.states; + 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(""); } @@ -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) { diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index d86504d..fcda673 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -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; @@ -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; @@ -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; @@ -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; } @@ -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; @@ -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) { @@ -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); } @@ -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 @@ -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() { @@ -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); @@ -4746,6 +4927,7 @@ public final class BatteryStatsImpl extends BatteryStats { } readHistory(in); + readOldHistory(in); mStartCount = in.readInt(); mBatteryUptime = in.readLong(); @@ -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); @@ -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)); @@ -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); @@ -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); diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index d57f2c9..6ed85d7 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -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; } @@ -386,10 +386,12 @@ status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len) } int numObjects = lastIndex - firstIndex + 1; - // grow data - err = growData(len); - if (err != NO_ERROR) { - return err; + if ((mDataSize+len) > mDataCapacity) { + // grow data + err = growData(len); + if (err != NO_ERROR) { + return err; + } } // append data @@ -1384,8 +1386,10 @@ status_t Parcel::continueWrite(size_t desired) return NO_MEMORY; } } else { - mDataSize = desired; - LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize); + 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); diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index 963a691..b4fdc9f 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -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)) { @@ -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) { |