Loading core/java/android/os/BatteryStats.java +6 −0 Original line number Diff line number Diff line Loading @@ -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() { } Loading Loading @@ -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) Loading Loading @@ -2061,6 +2066,7 @@ public abstract class BatteryStats implements Parcelable { } else { eventTag = null; } tagsFirstOccurrence = o.tagsFirstOccurrence; currentTime = o.currentTime; } Loading core/java/android/os/BatteryUsageStats.java +3 −27 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; Loading Loading @@ -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() { Loading @@ -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 Loading Loading @@ -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; } } Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -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; } Loading core/java/com/android/internal/os/BatteryStatsHistoryIterator.java +31 −61 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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; } } /** Loading Loading @@ -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; } Loading @@ -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=#" Loading @@ -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) { Loading core/java/com/android/internal/os/BatteryStatsImpl.java +92 −23 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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(); Loading Loading @@ -816,7 +820,6 @@ public class BatteryStatsImpl extends BatteryStats { private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator; private HistoryItem mHistoryIterator; private boolean mReadOverflow; int mStartCount; Loading Loading @@ -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; Loading Loading @@ -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; } /* Loading Loading @@ -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. Loading Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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; } Loading @@ -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); Loading @@ -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()); Loading Loading @@ -11281,7 +11343,6 @@ public class BatteryStatsImpl extends BatteryStats { @Override @UnsupportedAppUsage public boolean startIteratingHistoryLocked() { mReadOverflow = false; mBatteryStatsHistoryIterator = createBatteryStatsHistoryIterator(); return true; } Loading @@ -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 Loading core/java/com/android/internal/os/BatteryUsageStatsProvider.java +1 −11 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading
core/java/android/os/BatteryStats.java +6 −0 Original line number Diff line number Diff line Loading @@ -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() { } Loading Loading @@ -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) Loading Loading @@ -2061,6 +2066,7 @@ public abstract class BatteryStats implements Parcelable { } else { eventTag = null; } tagsFirstOccurrence = o.tagsFirstOccurrence; currentTime = o.currentTime; } Loading
core/java/android/os/BatteryUsageStats.java +3 −27 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; Loading Loading @@ -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() { Loading @@ -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 Loading Loading @@ -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; } } Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -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; } Loading
core/java/com/android/internal/os/BatteryStatsHistoryIterator.java +31 −61 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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; } } /** Loading Loading @@ -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; } Loading @@ -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=#" Loading @@ -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) { Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +92 −23 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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(); Loading Loading @@ -816,7 +820,6 @@ public class BatteryStatsImpl extends BatteryStats { private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator; private HistoryItem mHistoryIterator; private boolean mReadOverflow; int mStartCount; Loading Loading @@ -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; Loading Loading @@ -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; } /* Loading Loading @@ -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. Loading Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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; } Loading @@ -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); Loading @@ -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()); Loading Loading @@ -11281,7 +11343,6 @@ public class BatteryStatsImpl extends BatteryStats { @Override @UnsupportedAppUsage public boolean startIteratingHistoryLocked() { mReadOverflow = false; mBatteryStatsHistoryIterator = createBatteryStatsHistoryIterator(); return true; } Loading @@ -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 Loading
core/java/com/android/internal/os/BatteryUsageStatsProvider.java +1 −11 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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