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

Commit 17be86c4 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov Committed by Android (Google) Code Review
Browse files

Merge "Writing battery history tags into the history buffer"

parents 5154782c d9bf639e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1908,6 +1908,10 @@ public abstract class BatteryStats implements Parcelable {
        public final HistoryTag localWakeReasonTag = new HistoryTag();
        public final HistoryTag localEventTag = new HistoryTag();

        // Includes a tag's first occurrence in the parcel, so the value of the tag is written
        // rather than just its index in the history tag pool.
        public boolean tagsFirstOccurrence;

        @UnsupportedAppUsage
        public HistoryItem() {
        }
@@ -2014,6 +2018,7 @@ public abstract class BatteryStats implements Parcelable {
            wakeReasonTag = null;
            eventCode = EVENT_NONE;
            eventTag = null;
            tagsFirstOccurrence = false;
        }

        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -2061,6 +2066,7 @@ public abstract class BatteryStats implements Parcelable {
            } else {
                eventTag = null;
            }
            tagsFirstOccurrence = o.tagsFirstOccurrence;
            currentTime = o.currentTime;
        }

+3 −27
Original line number Diff line number Diff line
@@ -133,7 +133,6 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
    private final List<UserBatteryConsumer> mUserBatteryConsumers;
    private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
    private final Parcel mHistoryBuffer;
    private final List<BatteryStats.HistoryTag> mHistoryTagPool;
    private CursorWindow mBatteryConsumersCursorWindow;

    private BatteryUsageStats(@NonNull Builder builder) {
@@ -145,7 +144,6 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
        mDischargedPowerLowerBound = builder.mDischargedPowerLowerBoundMah;
        mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah;
        mHistoryBuffer = builder.mHistoryBuffer;
        mHistoryTagPool = builder.mHistoryTagPool;
        mBatteryTimeRemainingMs = builder.mBatteryTimeRemainingMs;
        mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs;
        mCustomPowerComponentNames = builder.mCustomPowerComponentNames;
@@ -283,7 +281,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
    /**
     * Returns the names of custom power components in order, so the first name in the array
     * corresponds to the custom componentId
     * {@link BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID}.
     * {@link BatteryConsumer#FIRST_CUSTOM_POWER_COMPONENT_ID}.
     */
    @NonNull
    public String[] getCustomPowerComponentNames() {
@@ -299,8 +297,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
            throw new IllegalStateException(
                    "Battery history was not requested in the BatteryUsageStatsQuery");
        }
        return new BatteryStatsHistoryIterator(new BatteryStatsHistory(mHistoryBuffer),
                mHistoryTagPool);
        return new BatteryStatsHistoryIterator(new BatteryStatsHistory(mHistoryBuffer));
    }

    @Override
@@ -361,19 +358,8 @@ public final class BatteryUsageStats implements Parcelable, Closeable {

            mHistoryBuffer = Parcel.obtain();
            mHistoryBuffer.unmarshall(historyBlob, 0, historyBlob.length);

            int historyTagCount = source.readInt();
            mHistoryTagPool = new ArrayList<>(historyTagCount);
            for (int i = 0; i < historyTagCount; i++) {
                BatteryStats.HistoryTag tag = new BatteryStats.HistoryTag();
                tag.string = source.readString();
                tag.uid = source.readInt();
                tag.poolIdx = source.readInt();
                mHistoryTagPool.add(tag);
            }
        } else {
            mHistoryBuffer = null;
            mHistoryTagPool = null;
        }
    }

@@ -395,13 +381,6 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
        if (mHistoryBuffer != null) {
            dest.writeBoolean(true);
            dest.writeBlob(mHistoryBuffer.marshall());
            dest.writeInt(mHistoryTagPool.size());
            for (int i = mHistoryTagPool.size() - 1; i >= 0; i--) {
                final BatteryStats.HistoryTag tag = mHistoryTagPool.get(i);
                dest.writeString(tag.string);
                dest.writeInt(tag.uid);
                dest.writeInt(tag.poolIdx);
            }
        } else {
            dest.writeBoolean(false);
        }
@@ -769,7 +748,6 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
        private final SparseArray<UserBatteryConsumer.Builder> mUserBatteryConsumerBuilders =
                new SparseArray<>();
        private Parcel mHistoryBuffer;
        private List<BatteryStats.HistoryTag> mHistoryTagPool;

        public Builder(@NonNull String[] customPowerComponentNames) {
            this(customPowerComponentNames, false);
@@ -888,10 +866,8 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
         * Sets the parceled recent history.
         */
        @NonNull
        public Builder setBatteryHistory(Parcel historyBuffer,
                List<BatteryStats.HistoryTag> historyTagPool) {
        public Builder setBatteryHistory(Parcel historyBuffer) {
            mHistoryBuffer = historyBuffer;
            mHistoryTagPool = historyTagPool;
            return this;
        }

+31 −61
Original line number Diff line number Diff line
@@ -21,8 +21,7 @@ import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Parcel;
import android.util.Slog;

import java.util.List;
import android.util.SparseArray;

/**
 * An iterator for {@link BatteryStats.HistoryItem}'s.
@@ -33,23 +32,11 @@ public class BatteryStatsHistoryIterator {
    private final BatteryStatsHistory mBatteryStatsHistory;
    private final BatteryStats.HistoryStepDetails mReadHistoryStepDetails =
            new BatteryStats.HistoryStepDetails();
    private final String[] mReadHistoryStrings;
    private final int[] mReadHistoryUids;
    private final SparseArray<BatteryStats.HistoryTag> mHistoryTags = new SparseArray<>();

    public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history,
            @NonNull List<BatteryStats.HistoryTag> historyTagPool) {
    public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history) {
        mBatteryStatsHistory = history;

        mBatteryStatsHistory.startIteratingHistory();

        mReadHistoryStrings = new String[historyTagPool.size()];
        mReadHistoryUids = new int[historyTagPool.size()];
        for (int i = historyTagPool.size() - 1; i >= 0; i--) {
            BatteryStats.HistoryTag tag = historyTagPool.get(i);
            final int idx = tag.poolIdx;
            mReadHistoryStrings[idx] = tag.string;
            mReadHistoryUids[idx] = tag.uid;
        }
    }

    /**
@@ -161,26 +148,16 @@ public class BatteryStatsHistoryIterator {
        }

        if ((firstToken & BatteryStatsImpl.DELTA_WAKELOCK_FLAG) != 0) {
            int indexes = src.readInt();
            int wakeLockIndex = indexes & 0xffff;
            int wakeReasonIndex = (indexes >> 16) & 0xffff;
            if (wakeLockIndex != 0xffff) {
            final int indexes = src.readInt();
            final int wakeLockIndex = indexes & 0xffff;
            final int wakeReasonIndex = (indexes >> 16) & 0xffff;
            if (readHistoryTag(src, wakeLockIndex, cur.localWakelockTag)) {
                cur.wakelockTag = cur.localWakelockTag;
                readHistoryTag(wakeLockIndex, cur.wakelockTag);
                if (DEBUG) {
                    Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
                            + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
                }
            } else {
                cur.wakelockTag = null;
            }
            if (wakeReasonIndex != 0xffff) {
            if (readHistoryTag(src, wakeReasonIndex, cur.localWakeReasonTag)) {
                cur.wakeReasonTag = cur.localWakeReasonTag;
                readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
                if (DEBUG) {
                    Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
                            + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
                }
            } else {
                cur.wakeReasonTag = null;
            }
@@ -195,7 +172,11 @@ public class BatteryStatsHistoryIterator {
            final int codeAndIndex = src.readInt();
            cur.eventCode = (codeAndIndex & 0xffff);
            final int index = ((codeAndIndex >> 16) & 0xffff);
            readHistoryTag(index, cur.eventTag);
            if (readHistoryTag(src, index, cur.localEventTag)) {
                cur.eventTag = cur.localEventTag;
            } else {
                cur.eventTag = null;
            }
            cur.numReadInts += 1;
            if (DEBUG) {
                Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
@@ -220,40 +201,29 @@ public class BatteryStatsHistoryIterator {
        cur.wifiRailChargeMah = src.readDouble();
    }

    int getHistoryStringPoolSize() {
        return mReadHistoryStrings.length;
    }

    int getHistoryStringPoolBytes() {
        int totalChars = 0;
        for (int i = mReadHistoryStrings.length - 1; i >= 0; i--) {
            if (mReadHistoryStrings[i] != null) {
                totalChars += mReadHistoryStrings[i].length() + 1;
            }
        }

        // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
        // Each string character is 2 bytes.
        return (mReadHistoryStrings.length * 12) + (totalChars * 2);
    }

    String getHistoryTagPoolString(int index) {
        return mReadHistoryStrings[index];
    private boolean readHistoryTag(Parcel src, int index, BatteryStats.HistoryTag outTag) {
        if (index == 0xffff) {
            return false;
        }

    int getHistoryTagPoolUid(int index) {
        return mReadHistoryUids[index];
    }
        if ((index & BatteryStatsImpl.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
            BatteryStats.HistoryTag tag = new BatteryStats.HistoryTag();
            tag.readFromParcel(src);
            tag.poolIdx = index & ~BatteryStatsImpl.TAG_FIRST_OCCURRENCE_FLAG;
            mHistoryTags.put(tag.poolIdx, tag);

    private void readHistoryTag(int index, BatteryStats.HistoryTag tag) {
        if (index < mReadHistoryStrings.length) {
            tag.string = mReadHistoryStrings[index];
            tag.uid = mReadHistoryUids[index];
            outTag.setTo(tag);
        } else {
            BatteryStats.HistoryTag historyTag = mHistoryTags.get(index);
            if (historyTag != null) {
                outTag.setTo(historyTag);
            } else {
            tag.string = null;
            tag.uid = 0;
                outTag.string = null;
                outTag.uid = 0;
            }
        tag.poolIdx = index;
            outTag.poolIdx = index;
        }
        return true;
    }

    private static void readBatteryLevelInt(int batteryLevelInt, BatteryStats.HistoryItem out) {
+92 −23
Original line number Diff line number Diff line
@@ -160,7 +160,7 @@ public class BatteryStatsImpl extends BatteryStats {
    private static final int MAGIC = 0xBA757475; // 'BATSTATS'
    // Current on-disk Parcel version
    static final int VERSION = 201;
    static final int VERSION = 202;
    // The maximum number of names wakelocks we will keep track of
    // per uid; once the limit is reached, we batch the remaining wakelocks
@@ -757,7 +757,11 @@ public class BatteryStatsImpl extends BatteryStats {
    protected boolean mRecordingHistory = false;
    int mNumHistoryItems;
    private static final int HISTORY_TAG_INDEX_LIMIT = 0x7ffe;
    private static final int MAX_HISTORY_TAG_STRING_LENGTH = 256;
    final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
    private SparseArray<HistoryTag> mHistoryTags;
    final Parcel mHistoryBuffer = Parcel.obtain();
    final HistoryItem mHistoryLastWritten = new HistoryItem();
    final HistoryItem mHistoryLastLastWritten = new HistoryItem();
@@ -816,7 +820,6 @@ public class BatteryStatsImpl extends BatteryStats {
    private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator;
    private HistoryItem mHistoryIterator;
    private boolean mReadOverflow;
    int mStartCount;
@@ -1191,12 +1194,21 @@ public class BatteryStatsImpl extends BatteryStats {
    }
    public BatteryStatsImpl(Clock clock) {
        this(clock, (File) null);
    }
    public BatteryStatsImpl(Clock clock, File historyDirectory) {
        init(clock);
        mStartClockTimeMs = clock.currentTimeMillis();
        mStatsFile = null;
        mCheckinFile = null;
        mDailyFile = null;
        if (historyDirectory == null) {
            mStatsFile = null;
            mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
        } else {
            mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
            mBatteryStatsHistory = new BatteryStatsHistory(this, historyDirectory, mHistoryBuffer);
        }
        mHandler = null;
        mPlatformIdleStateCallback = null;
        mMeasuredEnergyRetriever = null;
@@ -3321,21 +3333,43 @@ public class BatteryStatsImpl extends BatteryStats {
        return kmt;
    }
    /**
     * Returns the index for the specified tag. If this is the first time the tag is encountered
     * while writing the current history buffer, the method returns
     * <code>(index | TAG_FIRST_OCCURRENCE_FLAG)</code>
     */
    private int writeHistoryTag(HistoryTag tag) {
        Integer idxObj = mHistoryTagPool.get(tag);
        int idx;
        if (idxObj != null) {
            idx = idxObj;
        } else {
            if ((idx & TAG_FIRST_OCCURRENCE_FLAG) != 0) {
                idx &= ~TAG_FIRST_OCCURRENCE_FLAG;
                mHistoryTagPool.put(tag, idx);
            }
            return idx;
        } else if (mNextHistoryTagIdx < HISTORY_TAG_INDEX_LIMIT) {
            idx = mNextHistoryTagIdx;
            HistoryTag key = new HistoryTag();
            key.setTo(tag);
            tag.poolIdx = idx;
            mHistoryTagPool.put(key, idx);
            mNextHistoryTagIdx++;
            mNumHistoryTagChars += key.string.length() + 1;
            final int stringLength = key.string.length();
            if (stringLength > MAX_HISTORY_TAG_STRING_LENGTH) {
                Slog.wtf(TAG, "Long battery history tag: " + key.string);
            }
            mNumHistoryTagChars += stringLength + 1;
            if (mHistoryTags != null) {
                mHistoryTags.put(idx, key);
            }
            return idx | TAG_FIRST_OCCURRENCE_FLAG;
        } else {
            // Tag pool overflow: include the tag itself in the parcel
            return HISTORY_TAG_INDEX_LIMIT | TAG_FIRST_OCCURRENCE_FLAG;
        }
        return idx;
    }
    /*
@@ -3439,6 +3473,10 @@ public class BatteryStatsImpl extends BatteryStats {
    // These upper bits are the frequently changing state bits.
    static final int DELTA_STATE_MASK                       = 0xfe000000;
    // Flag in history tag index: indicates that this is the first occurrence of this tag,
    // therefore the tag value is written in the parcel
    static final int TAG_FIRST_OCCURRENCE_FLAG = 0x8000;
    // These are the pieces of battery state that are packed in to the upper bits of
    // the state int that have been packed in to the first delta int.  They must fit
    // in STATE_BATTERY_MASK.
@@ -3556,11 +3594,23 @@ public class BatteryStatsImpl extends BatteryStats {
                wakeReasonIndex = 0xffff;
            }
            dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
            if (cur.wakelockTag != null && (wakeLockIndex & TAG_FIRST_OCCURRENCE_FLAG) != 0) {
                cur.wakelockTag.writeToParcel(dest, 0);
                cur.tagsFirstOccurrence = true;
            }
            if (cur.wakeReasonTag != null && (wakeReasonIndex & TAG_FIRST_OCCURRENCE_FLAG) != 0) {
                cur.wakeReasonTag.writeToParcel(dest, 0);
                cur.tagsFirstOccurrence = true;
            }
        }
        if (cur.eventCode != HistoryItem.EVENT_NONE) {
            int index = writeHistoryTag(cur.eventTag);
            int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
            final int index = writeHistoryTag(cur.eventTag);
            final int codeAndIndex = (cur.eventCode & 0xffff) | (index << 16);
            dest.writeInt(codeAndIndex);
            if ((index & TAG_FIRST_OCCURRENCE_FLAG) != 0) {
                cur.eventTag.writeToParcel(dest, 0);
                cur.tagsFirstOccurrence = true;
            }
            if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
                    + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
                    + cur.eventTag.string);
@@ -3750,6 +3800,7 @@ public class BatteryStatsImpl extends BatteryStats {
        if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
                && timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0
                && (diffStates2&lastDiffStates2) == 0
                && (!mHistoryLastWritten.tagsFirstOccurrence && !cur.tagsFirstOccurrence)
                && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
                && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
                && mHistoryLastWritten.stepDetails == null
@@ -3809,9 +3860,17 @@ public class BatteryStatsImpl extends BatteryStats {
            mHistoryBuffer.setDataPosition(0);
            mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
            mHistoryBufferLastPos = -1;
            mHistoryLastWritten.clear();
            mHistoryLastLastWritten.clear();
            // Mark every entry in the pool with a flag indicating that the tag
            // has not yet been encountered while writing the current history buffer.
            for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
                entry.setValue(entry.getValue() | TAG_FIRST_OCCURRENCE_FLAG);
            }
            startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
            HistoryItem newItem = new HistoryItem();
            newItem.setTo(cur);
            startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem);
            return;
        }
@@ -3830,7 +3889,9 @@ public class BatteryStatsImpl extends BatteryStats {
        }
        mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
        mHistoryLastLastWritten.setTo(mHistoryLastWritten);
        final boolean hasTags = mHistoryLastWritten.tagsFirstOccurrence || cur.tagsFirstOccurrence;
        mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
        mHistoryLastWritten.tagsFirstOccurrence = hasTags;
        mHistoryLastWritten.states &= mActiveHistoryStates;
        mHistoryLastWritten.states2 &= mActiveHistoryStates2;
        writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
@@ -3839,6 +3900,7 @@ public class BatteryStatsImpl extends BatteryStats {
        cur.wakeReasonTag = null;
        cur.eventCode = HistoryItem.EVENT_NONE;
        cur.eventTag = null;
        cur.tagsFirstOccurrence = false;
        if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
                + " now " + mHistoryBuffer.dataPosition()
                + " size is now " + mHistoryBuffer.dataSize());
@@ -11281,7 +11343,6 @@ public class BatteryStatsImpl extends BatteryStats {
    @Override
    @UnsupportedAppUsage
    public boolean startIteratingHistoryLocked() {
        mReadOverflow = false;
        mBatteryStatsHistoryIterator = createBatteryStatsHistoryIterator();
        return true;
    }
@@ -11291,34 +11352,42 @@ public class BatteryStatsImpl extends BatteryStats {
     */
    @VisibleForTesting
    public BatteryStatsHistoryIterator createBatteryStatsHistoryIterator() {
        ArrayList<HistoryTag> tags = new ArrayList<>(mHistoryTagPool.size());
        for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
            final HistoryTag tag = entry.getKey();
            tag.poolIdx = entry.getValue();
            tags.add(tag);
        }
        return new BatteryStatsHistoryIterator(mBatteryStatsHistory, tags);
        return new BatteryStatsHistoryIterator(mBatteryStatsHistory);
    }
    @Override
    public int getHistoryStringPoolSize() {
        return mBatteryStatsHistoryIterator.getHistoryStringPoolSize();
        return mHistoryTagPool.size();
    }
    @Override
    public int getHistoryStringPoolBytes() {
        return mBatteryStatsHistoryIterator.getHistoryStringPoolBytes();
        return mNumHistoryTagChars;
    }
    @Override
    public String getHistoryTagPoolString(int index) {
        return mBatteryStatsHistoryIterator.getHistoryTagPoolString(index);
        ensureHistoryTagArray();
        HistoryTag historyTag = mHistoryTags.get(index);
        return historyTag != null ? historyTag.string : null;
    }
    @Override
    public int getHistoryTagPoolUid(int index) {
        return mBatteryStatsHistoryIterator.getHistoryTagPoolUid(index);
        ensureHistoryTagArray();
        HistoryTag historyTag = mHistoryTags.get(index);
        return historyTag != null ? historyTag.uid : Process.INVALID_UID;
    }
    private void ensureHistoryTagArray() {
        if (mHistoryTags != null) {
            return;
        }
        mHistoryTags = new SparseArray<>(mHistoryTagPool.size());
        for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
            mHistoryTags.put(entry.getValue(), entry.getKey());
        }
    }
    @Override
+1 −11
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * Uses accumulated battery stats data and PowerCalculators to produce power
@@ -186,16 +185,7 @@ public class BatteryUsageStatsProvider {
            }

            BatteryStatsImpl batteryStatsImpl = (BatteryStatsImpl) mStats;
            ArrayList<BatteryStats.HistoryTag> tags = new ArrayList<>(
                    batteryStatsImpl.mHistoryTagPool.size());
            for (Map.Entry<BatteryStats.HistoryTag, Integer> entry :
                    batteryStatsImpl.mHistoryTagPool.entrySet()) {
                final BatteryStats.HistoryTag tag = entry.getKey();
                tag.poolIdx = entry.getValue();
                tags.add(tag);
            }

            batteryUsageStatsBuilder.setBatteryHistory(batteryStatsImpl.mHistoryBuffer, tags);
            batteryUsageStatsBuilder.setBatteryHistory(batteryStatsImpl.mHistoryBuffer);
        }

        return batteryUsageStatsBuilder.build();
Loading