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

Commit 820f9d71 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Synchronize access to BatteryStatsHistory

This CL closes an overlooked concurrency issue, namely that when
we create a copy of BH we clone the buffer Parcel inside. If the
parcel is resized, especially relocated, during this operation,
we get a disastrous crash.

Bug: 320475371
Test: atest PowerStatsTests
Change-Id: Ied409ea5cd7d083c2f191604530f52dc48999bf1
parent 97d24320
Loading
Loading
Loading
Loading
+351 −240
Original line number Diff line number Diff line
@@ -490,7 +490,7 @@ public class BatteryStatsHistory {
     * Returns true if this instance only supports reading history.
     */
    public boolean isReadOnly() {
        return mActiveFile == null || mHistoryDir == null;
        return !mMutable || mActiveFile == null || mHistoryDir == null;
    }

    /**
@@ -508,6 +508,13 @@ public class BatteryStatsHistory {
     * create next history file.
     */
    public void startNextFile(long elapsedRealtimeMs) {
        synchronized (this) {
            startNextFileLocked(elapsedRealtimeMs);
        }
    }

    @GuardedBy("this")
    private void startNextFileLocked(long elapsedRealtimeMs) {
        if (mMaxHistoryFiles == 0) {
            Slog.wtf(TAG, "mMaxHistoryFiles should not be zero when writing history");
            return;
@@ -548,11 +555,8 @@ public class BatteryStatsHistory {
        }

        mWrittenPowerStatsDescriptors.clear();

        synchronized (this) {
        cleanupLocked();
    }
    }

    @GuardedBy("this")
    private void setCleanupEnabledLocked(boolean enabled) {
@@ -599,6 +603,7 @@ public class BatteryStatsHistory {
     * number 0 again.
     */
    public void reset() {
        synchronized (this) {
            if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!");
            for (BatteryHistoryFile file : mHistoryFiles) {
                file.atomicFile.delete();
@@ -611,17 +616,20 @@ public class BatteryStatsHistory {

            initHistoryBuffer();
        }
    }

    /**
     * Returns the monotonic clock time when the available battery history collection started.
     */
    public long getStartTime() {
        synchronized (this) {
            if (!mHistoryFiles.isEmpty()) {
                return mHistoryFiles.get(0).monotonicTimeMs;
            } else {
                return mHistoryBufferStartTime;
            }
        }
    }

    /**
     * Start iterating history files and history buffer.
@@ -633,11 +641,14 @@ public class BatteryStatsHistory {
     */
    @NonNull
    public BatteryStatsHistoryIterator iterate(long startTimeMs, long endTimeMs) {
        if (mMutable) {
            return copy().iterate(startTimeMs, endTimeMs);
        }

        mCurrentFileIndex = 0;
        mCurrentParcel = null;
        mCurrentParcelEnd = 0;
        mParcelIndex = 0;
        mMutable = false;
        if (mWritableHistory != null) {
            synchronized (mWritableHistory) {
                mWritableHistory.setCleanupEnabledLocked(false);
@@ -650,14 +661,11 @@ public class BatteryStatsHistory {
     * Finish iterating history files and history buffer.
     */
    void iteratorFinished() {
        // setDataPosition so mHistoryBuffer Parcel can be written.
        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
        if (mWritableHistory != null) {
            synchronized (mWritableHistory) {
                mWritableHistory.setCleanupEnabledLocked(true);
            }
        } else {
            mMutable = true;
        }
    }

@@ -671,6 +679,8 @@ public class BatteryStatsHistory {
     */
    @Nullable
    public Parcel getNextParcel(long startTimeMs, long endTimeMs) {
        checkImmutable();

        // First iterate through all records in current parcel.
        if (mCurrentParcel != null) {
            if (mCurrentParcel.dataPosition() < mCurrentParcelEnd) {
@@ -754,6 +764,12 @@ public class BatteryStatsHistory {
        return mCurrentParcel;
    }

    private void checkImmutable() {
        if (mMutable) {
            throw new IllegalStateException("Iterating over a mutable battery history");
        }
    }

    /**
     * Read history file into a parcel.
     *
@@ -863,9 +879,11 @@ public class BatteryStatsHistory {
     * @param out the output parcel
     */
    public void writeToParcel(Parcel out) {
        synchronized (this) {
            writeHistoryBuffer(out);
            writeToParcel(out, false /* useBlobs */);
        }
    }

    /**
     * This is for Settings app, when Settings app receives big history parcel, it call
@@ -874,9 +892,11 @@ public class BatteryStatsHistory {
     * @param out the output parcel
     */
    public void writeToBatteryUsageStatsParcel(Parcel out) {
        synchronized (this) {
            out.writeBlob(mHistoryBuffer.marshall());
            writeToParcel(out, true /* useBlobs */);
        }
    }

    private void writeToParcel(Parcel out, boolean useBlobs) {
        final long start = SystemClock.uptimeMillis();
@@ -1022,41 +1042,50 @@ public class BatteryStatsHistory {
     * Enables/disables recording of history.  When disabled, all "record*" calls are a no-op.
     */
    public void setHistoryRecordingEnabled(boolean enabled) {
        synchronized (this) {
            mRecordingHistory = enabled;
        }
    }

    /**
     * Returns true if history recording is enabled.
     */
    public boolean isRecordingHistory() {
        synchronized (this) {
            return mRecordingHistory;
        }
    }

    /**
     * Forces history recording regardless of charging state.
     */
    @VisibleForTesting
    public void forceRecordAllHistory() {
        synchronized (this) {
            mHaveBatteryLevel = true;
            mRecordingHistory = true;
        }
    }

    /**
     * Starts a history buffer by recording the current wall-clock time.
     */
    public void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
            boolean reset) {
        synchronized (this) {
            mRecordingHistory = true;
            mHistoryCur.currentTime = mClock.currentTimeMillis();
            writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur,
                    reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME);
            mHistoryCur.currentTime = 0;
        }
    }

    /**
     * Prepares to continue recording after restoring previous history from persistent storage.
     */
    public void continueRecordingHistory() {
        synchronized (this) {
            if (mHistoryBuffer.dataPosition() <= 0 && mHistoryFiles.size() <= 1) {
                return;
            }
@@ -1067,23 +1096,27 @@ public class BatteryStatsHistory {
            writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur, HistoryItem.CMD_START);
            startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
        }
    }

    /**
     * Notes the current battery state to be reflected in the next written history item.
     */
    public void setBatteryState(boolean charging, int status, int level, int chargeUah) {
        synchronized (this) {
            mHaveBatteryLevel = true;
            setChargingState(charging);
            mHistoryCur.batteryStatus = (byte) status;
            mHistoryCur.batteryLevel = (byte) level;
            mHistoryCur.batteryChargeUah = chargeUah;
        }
    }

    /**
     * Notes the current battery state to be reflected in the next written history item.
     */
    public void setBatteryState(int status, int level, int health, int plugType, int temperature,
            int voltageMv, int chargeUah) {
        synchronized (this) {
            mHaveBatteryLevel = true;
            mHistoryCur.batteryStatus = (byte) status;
            mHistoryCur.batteryLevel = (byte) level;
@@ -1093,45 +1126,53 @@ public class BatteryStatsHistory {
            mHistoryCur.batteryVoltage = (char) voltageMv;
            mHistoryCur.batteryChargeUah = chargeUah;
        }
    }

    /**
     * Notes the current power plugged-in state to be reflected in the next written history item.
     */
    public void setPluggedInState(boolean pluggedIn) {
        synchronized (this) {
            if (pluggedIn) {
                mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
            } else {
                mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
            }
        }
    }

    /**
     * Notes the current battery charging state to be reflected in the next written history item.
     */
    public void setChargingState(boolean charging) {
        synchronized (this) {
            if (charging) {
                mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
            } else {
                mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
            }
        }
    }

    /**
     * Records a history event with the given code, name and UID.
     */
    public void recordEvent(long elapsedRealtimeMs, long uptimeMs, int code, String name,
            int uid) {
        synchronized (this) {
            mHistoryCur.eventCode = code;
            mHistoryCur.eventTag = mHistoryCur.localEventTag;
            mHistoryCur.eventTag.string = name;
            mHistoryCur.eventTag.uid = uid;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a time change event.
     */
    public void recordCurrentTimeChange(long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
        synchronized (this) {
            if (!mRecordingHistory) {
                return;
            }
@@ -1141,11 +1182,13 @@ public class BatteryStatsHistory {
                    HistoryItem.CMD_CURRENT_TIME);
            mHistoryCur.currentTime = 0;
        }
    }

    /**
     * Records a system shutdown event.
     */
    public void recordShutdownEvent(long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
        synchronized (this) {
            if (!mRecordingHistory) {
                return;
            }
@@ -1154,12 +1197,14 @@ public class BatteryStatsHistory {
            writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur, HistoryItem.CMD_SHUTDOWN);
            mHistoryCur.currentTime = 0;
        }
    }

    /**
     * Records a battery state change event.
     */
    public void recordBatteryState(long elapsedRealtimeMs, long uptimeMs, int batteryLevel,
            boolean isPlugged) {
        synchronized (this) {
            mHistoryCur.batteryLevel = (byte) batteryLevel;
            setPluggedInState(isPlugged);
            if (DEBUG) {
@@ -1168,28 +1213,33 @@ public class BatteryStatsHistory {
            }
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a PowerStats snapshot.
     */
    public void recordPowerStats(long elapsedRealtimeMs, long uptimeMs,
            PowerStats powerStats) {
        synchronized (this) {
            mHistoryCur.powerStats = powerStats;
            mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records the change of a UID's proc state.
     */
    public void recordProcessStateChange(long elapsedRealtimeMs, long uptimeMs,
            int uid, @BatteryConsumer.ProcessState int processState) {
        synchronized (this) {
            mHistoryCur.processStateChange = mHistoryCur.localProcessStateChange;
            mHistoryCur.processStateChange.uid = uid;
            mHistoryCur.processStateChange.processState = processState;
            mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a history item with the amount of charge consumed by WiFi.  Used on certain devices
@@ -1197,26 +1247,31 @@ public class BatteryStatsHistory {
     */
    public void recordWifiConsumedCharge(long elapsedRealtimeMs, long uptimeMs,
            double monitoredRailChargeMah) {
        synchronized (this) {
            mHistoryCur.wifiRailChargeMah += monitoredRailChargeMah;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a wakelock start event.
     */
    public void recordWakelockStartEvent(long elapsedRealtimeMs, long uptimeMs, String historyName,
            int uid) {
        synchronized (this) {
            mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
            mHistoryCur.wakelockTag.string = historyName;
            mHistoryCur.wakelockTag.uid = uid;
            recordStateStartEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.STATE_WAKE_LOCK_FLAG);
        }
    }

    /**
     * Updates the previous history event with a wakelock name and UID.
     */
    public boolean maybeUpdateWakelockTag(long elapsedRealtimeMs, long uptimeMs, String historyName,
            int uid) {
        synchronized (this) {
            if (mHistoryLastWritten.cmd != HistoryItem.CMD_UPDATE) {
                return false;
            }
@@ -1230,106 +1285,128 @@ public class BatteryStatsHistory {
            }
            return true;
        }
    }

    /**
     * Records a wakelock release event.
     */
    public void recordWakelockStopEvent(long elapsedRealtimeMs, long uptimeMs, String historyName,
            int uid) {
        synchronized (this) {
            mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
            mHistoryCur.wakelockTag.string = historyName != null ? historyName : "";
            mHistoryCur.wakelockTag.uid = uid;
            recordStateStopEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.STATE_WAKE_LOCK_FLAG);
        }
    }

    /**
     * Records an event when some state flag changes to true.
     */
    public void recordStateStartEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
        synchronized (this) {
            mHistoryCur.states |= stateFlags;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records an event when some state flag changes to false.
     */
    public void recordStateStopEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
        synchronized (this) {
            mHistoryCur.states &= ~stateFlags;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records an event when some state flags change to true and some to false.
     */
    public void recordStateChangeEvent(long elapsedRealtimeMs, long uptimeMs, int stateStartFlags,
            int stateStopFlags) {
        synchronized (this) {
            mHistoryCur.states = (mHistoryCur.states | stateStartFlags) & ~stateStopFlags;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records an event when some state2 flag changes to true.
     */
    public void recordState2StartEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
        synchronized (this) {
            mHistoryCur.states2 |= stateFlags;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records an event when some state2 flag changes to false.
     */
    public void recordState2StopEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
        synchronized (this) {
            mHistoryCur.states2 &= ~stateFlags;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records an wakeup event.
     */
    public void recordWakeupEvent(long elapsedRealtimeMs, long uptimeMs, String reason) {
        synchronized (this) {
            mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
            mHistoryCur.wakeReasonTag.string = reason;
            mHistoryCur.wakeReasonTag.uid = 0;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a screen brightness change event.
     */
    public void recordScreenBrightnessEvent(long elapsedRealtimeMs, long uptimeMs,
            int brightnessBin) {
        synchronized (this) {
            mHistoryCur.states = setBitField(mHistoryCur.states, brightnessBin,
                    HistoryItem.STATE_BRIGHTNESS_SHIFT,
                    HistoryItem.STATE_BRIGHTNESS_MASK);
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a GNSS signal level change event.
     */
    public void recordGpsSignalQualityEvent(long elapsedRealtimeMs, long uptimeMs,
            int signalLevel) {
        synchronized (this) {
            mHistoryCur.states2 = setBitField(mHistoryCur.states2, signalLevel,
                    HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT,
                    HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK);
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a device idle mode change event.
     */
    public void recordDeviceIdleEvent(long elapsedRealtimeMs, long uptimeMs, int mode) {
        synchronized (this) {
            mHistoryCur.states2 = setBitField(mHistoryCur.states2, mode,
                    HistoryItem.STATE2_DEVICE_IDLE_SHIFT,
                    HistoryItem.STATE2_DEVICE_IDLE_MASK);
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a telephony state change event.
     */
    public void recordPhoneStateChangeEvent(long elapsedRealtimeMs, long uptimeMs, int addStateFlag,
            int removeStateFlag, int state, int signalStrength) {
        synchronized (this) {
            mHistoryCur.states = (mHistoryCur.states | addStateFlag) & ~removeStateFlag;
            if (state != -1) {
                mHistoryCur.states =
@@ -1345,52 +1422,61 @@ public class BatteryStatsHistory {
            }
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a data connection type change event.
     */
    public void recordDataConnectionTypeChangeEvent(long elapsedRealtimeMs, long uptimeMs,
            int dataConnectionType) {
        synchronized (this) {
            mHistoryCur.states = setBitField(mHistoryCur.states, dataConnectionType,
                    HistoryItem.STATE_DATA_CONNECTION_SHIFT,
                    HistoryItem.STATE_DATA_CONNECTION_MASK);
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a data connection type change event.
     */
    public void recordNrStateChangeEvent(long elapsedRealtimeMs, long uptimeMs,
            int nrState) {
        synchronized (this) {
            mHistoryCur.states2 = setBitField(mHistoryCur.states2, nrState,
                    HistoryItem.STATE2_NR_STATE_SHIFT,
                    HistoryItem.STATE2_NR_STATE_MASK);
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a WiFi supplicant state change event.
     */
    public void recordWifiSupplicantStateChangeEvent(long elapsedRealtimeMs, long uptimeMs,
            int supplState) {
        synchronized (this) {
            mHistoryCur.states2 =
                    setBitField(mHistoryCur.states2, supplState,
                            HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT,
                            HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK);
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Records a WiFi signal strength change event.
     */
    public void recordWifiSignalStrengthChangeEvent(long elapsedRealtimeMs, long uptimeMs,
            int strengthBin) {
        synchronized (this) {
            mHistoryCur.states2 =
                    setBitField(mHistoryCur.states2, strengthBin,
                            HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT,
                            HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK);
            writeHistoryItem(elapsedRealtimeMs, uptimeMs);
        }
    }

    /**
     * Writes event details into Atrace.
@@ -1446,11 +1532,14 @@ public class BatteryStatsHistory {
     * Writes the current history item to history.
     */
    public void writeHistoryItem(long elapsedRealtimeMs, long uptimeMs) {
        synchronized (this) {
            if (mTrackRunningHistoryElapsedRealtimeMs != 0) {
            final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
                final long diffElapsedMs =
                        elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
                final long diffUptimeMs = uptimeMs - mTrackRunningHistoryUptimeMs;
                if (diffUptimeMs < (diffElapsedMs - 20)) {
                final long wakeElapsedTimeMs = elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs);
                    final long wakeElapsedTimeMs =
                            elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs);
                    mHistoryAddTmp.setTo(mHistoryLastWritten);
                    mHistoryAddTmp.wakelockTag = null;
                    mHistoryAddTmp.wakeReasonTag = null;
@@ -1464,7 +1553,9 @@ public class BatteryStatsHistory {
            mTrackRunningHistoryUptimeMs = uptimeMs;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur);
        }
    }

    @GuardedBy("this")
    private void writeHistoryItem(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
        if (mTracer != null && mTracer.tracingEnabled()) {
            recordTraceEvents(cur.eventCode, cur.eventTag);
@@ -1591,6 +1682,7 @@ public class BatteryStatsHistory {
        writeHistoryItem(elapsedRealtimeMs, uptimeMs, cur, HistoryItem.CMD_UPDATE);
    }

    @GuardedBy("this")
    private void writeHistoryItem(long elapsedRealtimeMs,
            @SuppressWarnings("UnusedVariable") long uptimeMs, HistoryItem cur, byte cmd) {
        if (!mMutable) {
@@ -1701,7 +1793,8 @@ public class BatteryStatsHistory {
    /**
     * Writes the delta between the previous and current history items into history buffer.
     */
    public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
    @GuardedBy("this")
    private void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
        if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
            dest.writeInt(BatteryStatsHistory.DELTA_TIME_ABS);
            cur.writeToParcel(dest, 0);
@@ -1921,6 +2014,7 @@ public class BatteryStatsHistory {
     * while writing the current history buffer, the method returns
     * <code>(index | TAG_FIRST_OCCURRENCE_FLAG)</code>
     */
    @GuardedBy("this")
    private int writeHistoryTag(HistoryTag tag) {
        if (tag.string == null) {
            Slog.wtfStack(TAG, "writeHistoryTag called with null name");
@@ -1964,13 +2058,16 @@ public class BatteryStatsHistory {
     * Don't allow any more batching in to the current history event.
     */
    public void commitCurrentHistoryBatchLocked() {
        synchronized (this) {
            mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
        }
    }

    /**
     * Saves the accumulated history buffer in the active file, see {@link #getActiveFile()} .
     */
    public void writeHistory() {
        synchronized (this) {
            if (isReadOnly()) {
                Slog.w(TAG, "writeHistory: this instance instance is read-only");
                return;
@@ -1993,11 +2090,13 @@ public class BatteryStatsHistory {
                p.recycle();
            }
        }
    }

    /**
     * Reads history buffer from a persisted Parcel.
     */
    public void readHistoryBuffer(Parcel in) throws ParcelFormatException {
        synchronized (this) {
            final int version = in.readInt();
            if (version != BatteryStatsHistory.VERSION) {
                Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
@@ -2026,7 +2125,9 @@ public class BatteryStatsHistory {
                in.setDataPosition(curPos + bufSize);
            }
        }
    }

    @GuardedBy("this")
    private void writeHistoryBuffer(Parcel out) {
        out.writeInt(BatteryStatsHistory.VERSION);
        out.writeLong(mHistoryBufferStartTime);
@@ -2038,6 +2139,7 @@ public class BatteryStatsHistory {
        out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
    }

    @GuardedBy("this")
    private void writeParcelToFileLocked(Parcel p, AtomicFile file) {
        FileOutputStream fos = null;
        mWriteLock.lock();
@@ -2066,34 +2168,43 @@ public class BatteryStatsHistory {
     * Returns the total number of history tags in the tag pool.
     */
    public int getHistoryStringPoolSize() {
        synchronized (this) {
            return mHistoryTagPool.size();
        }
    }

    /**
     * Returns the total number of bytes occupied by the history tag pool.
     */
    public int getHistoryStringPoolBytes() {
        synchronized (this) {
            return mNumHistoryTagChars;
        }
    }

    /**
     * Returns the string held by the requested history tag.
     */
    public String getHistoryTagPoolString(int index) {
        synchronized (this) {
            ensureHistoryTagArray();
            HistoryTag historyTag = mHistoryTags.get(index);
            return historyTag != null ? historyTag.string : null;
        }
    }

    /**
     * Returns the UID held by the requested history tag.
     */
    public int getHistoryTagPoolUid(int index) {
        synchronized (this) {
            ensureHistoryTagArray();
            HistoryTag historyTag = mHistoryTags.get(index);
            return historyTag != null ? historyTag.uid : Process.INVALID_UID;
        }
    }

    @GuardedBy("this")
    private void ensureHistoryTagArray() {
        if (mHistoryTags != null) {
            return;
+1 −1
Original line number Diff line number Diff line
@@ -11459,7 +11459,7 @@ public class BatteryStatsImpl extends BatteryStats {
    @Override
    public BatteryStatsHistoryIterator iterateBatteryStatsHistory(long startTimeMs,
            long endTimeMs) {
        return mHistory.copy().iterate(startTimeMs, endTimeMs);
        return mHistory.iterate(startTimeMs, endTimeMs);
    }
    @Override
+1 −2
Original line number Diff line number Diff line
@@ -74,8 +74,7 @@ public class PowerStatsAggregator {
            boolean clockUpdateAdded = false;
            long baseTime = startTimeMs > 0 ? startTimeMs : UNINITIALIZED;
            long lastTime = 0;
            try (BatteryStatsHistoryIterator iterator =
                         mHistory.copy().iterate(startTimeMs, endTimeMs)) {
            try (BatteryStatsHistoryIterator iterator = mHistory.iterate(startTimeMs, endTimeMs)) {
                while (iterator.hasNext()) {
                    BatteryStats.HistoryItem item = iterator.next();

+22 −8

File changed.

Preview size limit exceeded, changes collapsed.