Merge "More battery stats improvements."
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d7483ba..b0f3ac3 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -26,6 +26,7 @@
import android.telephony.SignalStrength;
import android.util.Log;
import android.util.Printer;
+import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -408,16 +409,19 @@
}
public final static class HistoryItem implements Parcelable {
+ static final String TAG = "HistoryItem";
+ static final boolean DEBUG = false;
+
public HistoryItem next;
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;
+ public static final byte CMD_NULL = 0;
+ public static final byte CMD_UPDATE = 1;
+ public static final byte CMD_START = 2;
+ public static final byte CMD_OVERFLOW = 3;
- public byte cmd;
+ public byte cmd = CMD_NULL;
public byte batteryLevel;
public byte batteryStatus;
@@ -428,33 +432,38 @@
public char batteryVoltage;
// Constants from SCREEN_BRIGHTNESS_*
- public static final int STATE_BRIGHTNESS_MASK = 0x000000f;
+ public static final int STATE_BRIGHTNESS_MASK = 0x0000000f;
public static final int STATE_BRIGHTNESS_SHIFT = 0;
// Constants from SIGNAL_STRENGTH_*
- public static final int STATE_SIGNAL_STRENGTH_MASK = 0x00000f0;
+ public static final int STATE_SIGNAL_STRENGTH_MASK = 0x000000f0;
public static final int STATE_SIGNAL_STRENGTH_SHIFT = 4;
// Constants from ServiceState.STATE_*
- public static final int STATE_PHONE_STATE_MASK = 0x0000f00;
+ public static final int STATE_PHONE_STATE_MASK = 0x00000f00;
public static final int STATE_PHONE_STATE_SHIFT = 8;
// Constants from DATA_CONNECTION_*
- public static final int STATE_DATA_CONNECTION_MASK = 0x000f000;
+ public static final int STATE_DATA_CONNECTION_MASK = 0x0000f000;
public static final int STATE_DATA_CONNECTION_SHIFT = 12;
- public static final int STATE_BATTERY_PLUGGED_FLAG = 1<<30;
- public static final int STATE_SCREEN_ON_FLAG = 1<<29;
+ // 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<<30;
+ public static final int STATE_SENSOR_ON_FLAG = 1<<29;
public static final int STATE_GPS_ON_FLAG = 1<<28;
- public static final int STATE_PHONE_IN_CALL_FLAG = 1<<27;
- public static final int STATE_PHONE_SCANNING_FLAG = 1<<26;
- public static final int STATE_WIFI_ON_FLAG = 1<<25;
- public static final int STATE_WIFI_RUNNING_FLAG = 1<<24;
- public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<23;
- public static final int STATE_WIFI_SCAN_LOCK_FLAG = 1<<22;
- public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<21;
- public static final int STATE_BLUETOOTH_ON_FLAG = 1<<20;
- public static final int STATE_AUDIO_ON_FLAG = 1<<19;
- public static final int STATE_VIDEO_ON_FLAG = 1<<18;
- public static final int STATE_WAKE_LOCK_FLAG = 1<<17;
- public static final int STATE_SENSOR_ON_FLAG = 1<<16;
+ public static final int STATE_PHONE_SCANNING_FLAG = 1<<27;
+ public static final int STATE_WIFI_RUNNING_FLAG = 1<<26;
+ public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<25;
+ public static final int STATE_WIFI_SCAN_LOCK_FLAG = 1<<24;
+ public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<23;
+ // 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_AUDIO_ON_FLAG = 1<<22;
+ public static final int STATE_VIDEO_ON_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;
+ public static final int STATE_WIFI_ON_FLAG = 1<<17;
+ public static final int STATE_BLUETOOTH_ON_FLAG = 1<<16;
public static final int MOST_INTERESTING_STATES =
STATE_BATTERY_PLUGGED_FLAG | STATE_SCREEN_ON_FLAG
@@ -487,10 +496,6 @@
dest.writeInt(bat);
dest.writeInt(states);
}
-
- public void writeDelta(Parcel dest, HistoryItem last) {
- writeToParcel(dest, 0);
- }
private void readFromParcel(Parcel src) {
int bat = src.readInt();
@@ -505,11 +510,161 @@
states = src.readInt();
}
- public void readDelta(Parcel src, HistoryItem last) {
- time = src.readLong();
- readFromParcel(src);
+ // Part of initial delta int that specifies the time delta.
+ static final int DELTA_TIME_MASK = 0x3ffff;
+ static final int DELTA_TIME_ABS = 0x3fffd; // Following is an entire abs update.
+ static final int DELTA_TIME_INT = 0x3fffe; // The delta is a following int
+ static final int DELTA_TIME_LONG = 0x3ffff; // The delta is a following long
+ // Part of initial delta int holding the command code.
+ static final int DELTA_CMD_MASK = 0x3;
+ static final int DELTA_CMD_SHIFT = 18;
+ // Flag in delta int: a new battery level int follows.
+ static final int DELTA_BATTERY_LEVEL_FLAG = 1<<20;
+ // Flag in delta int: a new full state and battery status int follows.
+ static final int DELTA_STATE_FLAG = 1<<21;
+ static final int DELTA_STATE_MASK = 0xffc00000;
+
+ public void writeDelta(Parcel dest, HistoryItem last) {
+ if (last == null || last.cmd != CMD_UPDATE) {
+ dest.writeInt(DELTA_TIME_ABS);
+ writeToParcel(dest, 0);
+ return;
+ }
+
+ final long deltaTime = time - last.time;
+ final int lastBatteryLevelInt = last.buildBatteryLevelInt();
+ final int lastStateInt = last.buildStateInt();
+
+ int deltaTimeToken;
+ if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
+ deltaTimeToken = DELTA_TIME_LONG;
+ } else if (deltaTime >= DELTA_TIME_ABS) {
+ deltaTimeToken = DELTA_TIME_INT;
+ } else {
+ deltaTimeToken = (int)deltaTime;
+ }
+ int firstToken = deltaTimeToken
+ | (cmd<<DELTA_CMD_SHIFT)
+ | (states&DELTA_STATE_MASK);
+ final int batteryLevelInt = buildBatteryLevelInt();
+ final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
+ if (batteryLevelIntChanged) {
+ firstToken |= DELTA_BATTERY_LEVEL_FLAG;
+ }
+ final int stateInt = buildStateInt();
+ final boolean stateIntChanged = stateInt != lastStateInt;
+ if (stateIntChanged) {
+ firstToken |= DELTA_STATE_FLAG;
+ }
+ dest.writeInt(firstToken);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
+ + " deltaTime=" + deltaTime);
+
+ if (deltaTimeToken >= DELTA_TIME_INT) {
+ if (deltaTimeToken == DELTA_TIME_INT) {
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
+ dest.writeInt((int)deltaTime);
+ } else {
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
+ dest.writeLong(deltaTime);
+ }
+ }
+ if (batteryLevelIntChanged) {
+ dest.writeInt(batteryLevelInt);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
+ + Integer.toHexString(batteryLevelInt)
+ + " batteryLevel=" + batteryLevel
+ + " batteryTemp=" + (int)batteryTemperature
+ + " batteryVolt=" + (int)batteryVoltage);
+ }
+ if (stateIntChanged) {
+ dest.writeInt(stateInt);
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
+ + Integer.toHexString(stateInt)
+ + " batteryStatus=" + batteryStatus
+ + " batteryHealth=" + batteryHealth
+ + " batteryPlugType=" + batteryPlugType
+ + " states=0x" + Integer.toHexString(states));
+ }
+ }
+
+ private int buildBatteryLevelInt() {
+ return ((((int)batteryLevel)<<24)&0xff000000)
+ | ((((int)batteryTemperature)<<14)&0x00ffc000)
+ | (((int)batteryVoltage)&0x00003fff);
+ }
+
+ private int buildStateInt() {
+ return ((((int)batteryStatus)<<28)&0xf0000000)
+ | ((((int)batteryHealth)<<24)&0x0f000000)
+ | ((((int)batteryPlugType)<<22)&0x00c00000)
+ | (states&(~DELTA_STATE_MASK));
+ }
+
+ public void readDelta(Parcel src) {
+ int firstToken = src.readInt();
+ int deltaTimeToken = firstToken&DELTA_TIME_MASK;
+ cmd = (byte)((firstToken>>DELTA_CMD_SHIFT)&DELTA_CMD_MASK);
+ if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
+ + " deltaTimeToken=" + deltaTimeToken);
+
+ if (deltaTimeToken < DELTA_TIME_ABS) {
+ time += deltaTimeToken;
+ } else if (deltaTimeToken == DELTA_TIME_ABS) {
+ time = src.readLong();
+ readFromParcel(src);
+ return;
+ } else if (deltaTimeToken == DELTA_TIME_INT) {
+ int delta = src.readInt();
+ time += delta;
+ if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + time);
+ } else {
+ long delta = src.readLong();
+ if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + time);
+ time += delta;
+ }
+
+ if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
+ int batteryLevelInt = src.readInt();
+ batteryLevel = (byte)((batteryLevelInt>>24)&0xff);
+ batteryTemperature = (char)((batteryLevelInt>>14)&0x3ff);
+ batteryVoltage = (char)(batteryLevelInt&0x3fff);
+ if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
+ + Integer.toHexString(batteryLevelInt)
+ + " batteryLevel=" + batteryLevel
+ + " batteryTemp=" + (int)batteryTemperature
+ + " batteryVolt=" + (int)batteryVoltage);
+ }
+
+ if ((firstToken&DELTA_STATE_FLAG) != 0) {
+ int stateInt = src.readInt();
+ states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~DELTA_STATE_MASK));
+ batteryStatus = (byte)((stateInt>>28)&0xf);
+ batteryHealth = (byte)((stateInt>>24)&0xf);
+ batteryPlugType = (byte)((stateInt>>22)&0x3);
+ if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
+ + Integer.toHexString(stateInt)
+ + " batteryStatus=" + batteryStatus
+ + " batteryHealth=" + batteryHealth
+ + " batteryPlugType=" + batteryPlugType
+ + " states=0x" + Integer.toHexString(states));
+ } else {
+ states = (firstToken&DELTA_STATE_MASK) | (states&(~DELTA_STATE_MASK));
+ }
}
+ public void clear() {
+ time = 0;
+ cmd = CMD_NULL;
+ batteryLevel = 0;
+ batteryStatus = 0;
+ batteryHealth = 0;
+ batteryPlugType = 0;
+ batteryTemperature = 0;
+ batteryVoltage = 0;
+ states = 0;
+ }
+
public void setTo(HistoryItem o) {
time = o.time;
cmd = o.cmd;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index fcda673..7cf33fc 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -71,7 +71,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 57;
+ private static final int VERSION = 60;
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -156,11 +156,12 @@
boolean mRecordingHistory = true;
int mNumHistoryItems;
- static final int MAX_HISTORY_BUFFER = 64*1024; // 64KB
- static final int MAX_MAX_HISTORY_BUFFER = 92*1024; // 92KB
+ static final int MAX_HISTORY_BUFFER = 128*1024; // 128KB
+ static final int MAX_MAX_HISTORY_BUFFER = 144*1024; // 144KB
final Parcel mHistoryBuffer = Parcel.obtain();
final HistoryItem mHistoryLastWritten = new HistoryItem();
final HistoryItem mHistoryLastLastWritten = new HistoryItem();
+ final HistoryItem mHistoryReadTmp = new HistoryItem();
int mHistoryBufferLastPos = -1;
boolean mHistoryOverflow = false;
long mLastHistoryTime = 0;
@@ -1212,8 +1213,9 @@
return;
}
+ final long timeDiff = (mHistoryBaseTime+curTime) - mHistoryLastWritten.time;
if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
- && (mHistoryBaseTime+curTime) < (mHistoryLastWritten.time+2000)
+ && timeDiff < 2000
&& ((mHistoryLastWritten.states^mHistoryCur.states)&mChangedBufferStates) == 0) {
// If the current is the same as the one before, then we no
// longer need the entry.
@@ -1221,7 +1223,7 @@
mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
mHistoryBufferLastPos = -1;
if (mHistoryLastLastWritten.cmd == HistoryItem.CMD_UPDATE
- && mHistoryLastLastWritten.same(mHistoryCur)) {
+ && timeDiff < 500 && 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.
@@ -1231,6 +1233,7 @@
}
mChangedBufferStates |= mHistoryLastWritten.states^mHistoryCur.states;
curTime = mHistoryLastWritten.time - mHistoryBaseTime;
+ mHistoryLastWritten.setTo(mHistoryLastLastWritten);
} else {
mChangedBufferStates = 0;
}
@@ -1295,6 +1298,7 @@
// 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+curTime) < (mHistoryEnd.time+500)
&& mHistoryLastEnd.same(mHistoryCur)) {
mHistoryLastEnd.next = null;
mHistoryEnd.next = mHistoryCache;
@@ -4038,6 +4042,7 @@
if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
+ " pos=" + mHistoryBuffer.dataPosition());
mHistoryBuffer.setDataPosition(0);
+ mHistoryReadTmp.clear();
mReadOverflow = false;
mIteratingHistory = true;
return (mHistoryIterator = mHistory) != null;
@@ -4047,8 +4052,8 @@
public boolean getNextOldHistoryLocked(HistoryItem out) {
boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
if (!end) {
- mHistoryLastWritten.readDelta(mHistoryBuffer, null);
- mReadOverflow |= mHistoryLastWritten.cmd == HistoryItem.CMD_OVERFLOW;
+ mHistoryReadTmp.readDelta(mHistoryBuffer);
+ mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
}
HistoryItem cur = mHistoryIterator;
if (cur == null) {
@@ -4062,14 +4067,14 @@
if (!mReadOverflow) {
if (end) {
Slog.w(TAG, "New history ends before old history!");
- } else if (!out.same(mHistoryLastWritten)) {
+ } else if (!out.same(mHistoryReadTmp)) {
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);
+ (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, now);
}
}
return true;
@@ -4093,12 +4098,16 @@
@Override
public boolean getNextHistoryLocked(HistoryItem out) {
- boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
+ final int pos = mHistoryBuffer.dataPosition();
+ if (pos == 0) {
+ out.clear();
+ }
+ boolean end = pos >= mHistoryBuffer.dataSize();
if (end) {
return false;
}
- out.readDelta(mHistoryBuffer, null);
+ out.readDelta(mHistoryBuffer);
return true;
}