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

Commit 230c3232 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "More battery stats improvements."

parents 3ad604b3 1fadab5c
Loading
Loading
Loading
Loading
+185 −30
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.content.pm.ApplicationInfo;
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 abstract class BatteryStats implements Parcelable {
    }

    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 abstract class BatteryStats implements Parcelable {
        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
@@ -488,10 +497,6 @@ 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);
@@ -505,9 +510,159 @@ public abstract class BatteryStats implements Parcelable {
            states = src.readInt();
        }

        public void readDelta(Parcel src, HistoryItem last) {
        // 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) {
+20 −11
Original line number Diff line number Diff line
@@ -71,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 = 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 @@ public final class BatteryStatsImpl extends BatteryStats {
    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 @@ public final class BatteryStatsImpl extends BatteryStats {
            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 @@ public final class BatteryStatsImpl extends BatteryStats {
            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 @@ public final class BatteryStatsImpl extends BatteryStats {
            }
            mChangedBufferStates |= mHistoryLastWritten.states^mHistoryCur.states;
            curTime = mHistoryLastWritten.time - mHistoryBaseTime;
            mHistoryLastWritten.setTo(mHistoryLastLastWritten);
        } else {
            mChangedBufferStates = 0;
        }
@@ -1295,6 +1298,7 @@ public final class BatteryStatsImpl extends BatteryStats {
            // 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 @@ public final class BatteryStatsImpl extends BatteryStats {
        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 final class BatteryStatsImpl extends BatteryStats {
    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 @@ public final class BatteryStatsImpl extends BatteryStats {
        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 @@ public final class BatteryStatsImpl extends BatteryStats {

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