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

Commit 0e2f3922 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Include PowerStats snapshots in battery history

Bug: 285646152
Test: atest FrameworksCoreTests:BatteryStatsTests FrameworksServicesTests:BatteryStatsTests
Change-Id: I7f202b2012844395c43e559819ff371bbaf2161e
parent 478d1436
Loading
Loading
Loading
Loading
+10 −150
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.internal.os.CpuScalingPolicies;
import com.android.internal.os.PowerStats;

import com.google.android.collect.Lists;

@@ -1792,79 +1793,6 @@ public abstract class BatteryStats {
        }
    }

    /**
     * Measured energy delta from the previous reading.
     */
    public static final class EnergyConsumerDetails {
        /**
         * Description of the energy consumer, such as CPU, DISPLAY etc
         */
        public static final class EnergyConsumer {
            /**
             * See android.hardware.power.stats.EnergyConsumerType
             */
            public int type;
            /**
             * Used when there are multipe energy consumers of the same type, such
             * as CPU clusters, multiple displays on foldable devices etc.
             */
            public int ordinal;
            /**
             * Human-readable name of the energy consumer, e.g. "CPU"
             */
            public String name;
        }
        public EnergyConsumer[] consumers;
        public long[] chargeUC;

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder();
            for (int i = 0; i < consumers.length; i++) {
                if (chargeUC[i] == POWER_DATA_UNAVAILABLE) {
                    continue;
                }
                if (sb.length() != 0) {
                    sb.append(' ');
                }
                sb.append(consumers[i].name);
                sb.append('=');
                sb.append(chargeUC[i]);
            }
            return sb.toString();
        }
    }

    /**
     * CPU usage for a given UID.
     */
    public static final class CpuUsageDetails {
        /**
         * Descriptions of CPU power brackets, see PowerProfile.getCpuPowerBracketDescription
         */
        public String[] cpuBracketDescriptions;
        public int uid;
        /**
         *  The delta, in milliseconds, per CPU power bracket, from the previous record for the
         *  same UID.
         */
        public long[] cpuUsageMs;

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder();
            UserHandle.formatUid(sb, uid);
            sb.append(": ");
            for (int bracket = 0; bracket < cpuUsageMs.length; bracket++) {
                if (bracket != 0) {
                    sb.append(", ");
                }
                sb.append(cpuUsageMs[bracket]);
            }
            return sb.toString();
        }
    }

    /**
     * Battery history record.
     */
@@ -2008,11 +1936,8 @@ public abstract class BatteryStats {
        // Non-null when there is more detailed information at this step.
        public HistoryStepDetails stepDetails;

        // Non-null when there is energy consumer information
        public EnergyConsumerDetails energyConsumerDetails;

        // Non-null when there is CPU usage information
        public CpuUsageDetails cpuUsageDetails;
        // Non-null when there are power stats to be written to history
        public PowerStats powerStats;

        public static final int EVENT_FLAG_START = 0x8000;
        public static final int EVENT_FLAG_FINISH = 0x4000;
@@ -2222,8 +2147,7 @@ public abstract class BatteryStats {
            eventCode = EVENT_NONE;
            eventTag = null;
            tagsFirstOccurrence = false;
            energyConsumerDetails = null;
            cpuUsageDetails = null;
            powerStats = null;
        }

        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -2273,8 +2197,7 @@ public abstract class BatteryStats {
            }
            tagsFirstOccurrence = o.tagsFirstOccurrence;
            currentTime = o.currentTime;
            energyConsumerDetails = o.energyConsumerDetails;
            cpuUsageDetails = o.cpuUsageDetails;
            powerStats = o.powerStats;
        }

        public boolean sameNonEvent(HistoryItem o) {
@@ -6911,25 +6834,6 @@ public abstract class BatteryStats {
        private String printNextItem(HistoryItem rec, long baseTime, boolean checkin,
                boolean verbose) {
            StringBuilder item = new StringBuilder();

            if (rec.cpuUsageDetails != null
                    && rec.cpuUsageDetails.cpuBracketDescriptions != null
                    && checkin) {
                String[] descriptions = rec.cpuUsageDetails.cpuBracketDescriptions;
                for (int bracket = 0; bracket < descriptions.length; bracket++) {
                    item.append(BATTERY_STATS_CHECKIN_VERSION);
                    item.append(',');
                    item.append(HISTORY_DATA);
                    item.append(",0,XB,");
                    item.append(descriptions.length);
                    item.append(',');
                    item.append(bracket);
                    item.append(',');
                    item.append(descriptions[bracket]);
                    item.append("\n");
                }
            }

            if (!checkin) {
                item.append("  ");
                TimeUtils.formatDuration(
@@ -7165,57 +7069,13 @@ public abstract class BatteryStats {
                        item.append("\"");
                    }
                }
                boolean firstExtension = true;
                if (rec.energyConsumerDetails != null) {
                    firstExtension = false;
                if (rec.powerStats != null && verbose) {
                    if (!checkin) {
                        item.append(" ext=energy:");
                        item.append(rec.energyConsumerDetails);
                    } else {
                        item.append(",XE");
                        for (int i = 0; i < rec.energyConsumerDetails.consumers.length; i++) {
                            if (rec.energyConsumerDetails.chargeUC[i] != POWER_DATA_UNAVAILABLE) {
                                item.append(',');
                                item.append(rec.energyConsumerDetails.consumers[i].name);
                                item.append('=');
                                item.append(rec.energyConsumerDetails.chargeUC[i]);
                            }
                        }
                    }
                }
                if (rec.cpuUsageDetails != null) {
                    if (!checkin) {
                        if (!firstExtension) {
                            item.append("\n                ");
                        }
                        String[] descriptions = rec.cpuUsageDetails.cpuBracketDescriptions;
                        if (descriptions != null) {
                            for (int bracket = 0; bracket < descriptions.length; bracket++) {
                                item.append(" ext=cpu-bracket:");
                                item.append(bracket);
                                item.append(":");
                                item.append(descriptions[bracket]);
                                item.append("\n                ");
                            }
                        }
                        item.append(" ext=cpu:");
                        item.append(rec.cpuUsageDetails);
                    } else {
                        if (!firstExtension) {
                            item.append('\n');
                            item.append(BATTERY_STATS_CHECKIN_VERSION);
                            item.append(',');
                            item.append(HISTORY_DATA);
                            item.append(",0");
                        }
                        item.append(",XC,");
                        item.append(rec.cpuUsageDetails.uid);
                        for (int i = 0; i < rec.cpuUsageDetails.cpuUsageMs.length; i++) {
                            item.append(',');
                            item.append(rec.cpuUsageDetails.cpuUsageMs[i]);
                        }
                        item.append(
                                "\n                 Stats: ");
                        item.append(rec.powerStats.formatForBatteryHistory(
                                "\n                    "));
                    }
                    firstExtension = false;
                }
                item.append("\n");
                if (rec.stepDetails != null) {
+29 −76
Original line number Diff line number Diff line
@@ -21,8 +21,6 @@ import android.annotation.Nullable;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.BatteryStats.BitDescription;
import android.os.BatteryStats.CpuUsageDetails;
import android.os.BatteryStats.EnergyConsumerDetails;
import android.os.BatteryStats.HistoryItem;
import android.os.BatteryStats.HistoryStepDetails;
import android.os.BatteryStats.HistoryTag;
@@ -124,10 +122,8 @@ public class BatteryStatsHistory {
    // therefore the tag value is written in the parcel
    static final int TAG_FIRST_OCCURRENCE_FLAG = 0x8000;

    static final int EXTENSION_MEASURED_ENERGY_HEADER_FLAG = 0x00000001;
    static final int EXTENSION_MEASURED_ENERGY_FLAG = 0x00000002;
    static final int EXTENSION_CPU_USAGE_HEADER_FLAG = 0x00000004;
    static final int EXTENSION_CPU_USAGE_FLAG = 0x00000008;
    static final int EXTENSION_POWER_STATS_DESCRIPTOR_FLAG = 0x00000001;
    static final int EXTENSION_POWER_STATS_FLAG = 0x00000002;

    // For state1, trace everything except the wakelock bit (which can race with
    // suspend) and the running bit (which isn't meaningful in traces).
@@ -200,9 +196,7 @@ public class BatteryStatsHistory {
    private long mTrackRunningHistoryElapsedRealtimeMs = 0;
    private long mTrackRunningHistoryUptimeMs = 0;
    private long mHistoryBaseTimeMs;
    private boolean mMeasuredEnergyHeaderWritten = false;
    private boolean mCpuUsageHeaderWritten = false;
    private final VarintParceler mVarintParceler = new VarintParceler();
    private ArraySet<PowerStats.Descriptor> mWrittenPowerStatsDescriptors = new ArraySet<>();
    private byte mLastHistoryStepLevel = 0;
    private boolean mMutable = true;
    private final BatteryStatsHistory mWritableHistory;
@@ -384,8 +378,7 @@ public class BatteryStatsHistory {
        mLastHistoryElapsedRealtimeMs = 0;
        mTrackRunningHistoryElapsedRealtimeMs = 0;
        mTrackRunningHistoryUptimeMs = 0;
        mMeasuredEnergyHeaderWritten = false;
        mCpuUsageHeaderWritten = false;
        mWrittenPowerStatsDescriptors.clear();

        mHistoryBuffer.setDataSize(0);
        mHistoryBuffer.setDataPosition(0);
@@ -1050,11 +1043,11 @@ public class BatteryStatsHistory {
    }

    /**
     * Records measured energy data.
     * Records a PowerStats snapshot.
     */
    public void recordEnergyConsumerDetails(long elapsedRealtimeMs, long uptimeMs,
            EnergyConsumerDetails energyConsumerDetails) {
        mHistoryCur.energyConsumerDetails = energyConsumerDetails;
    public void recordPowerStats(long elapsedRealtimeMs, long uptimeMs,
            PowerStats powerStats) {
        mHistoryCur.powerStats = powerStats;
        mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG;
        writeHistoryItem(elapsedRealtimeMs, uptimeMs);
    }
@@ -1278,17 +1271,6 @@ public class BatteryStatsHistory {
        mTracer.traceInstantEvent(track, name);
    }

    /**
     * Records CPU usage by a specific UID.  The recorded data is the delta from
     * the previous record for the same UID.
     */
    public void recordCpuUsage(long elapsedRealtimeMs, long uptimeMs,
            CpuUsageDetails cpuUsageDetails) {
        mHistoryCur.cpuUsageDetails = cpuUsageDetails;
        mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG;
        writeHistoryItem(elapsedRealtimeMs, uptimeMs);
    }

    /**
     * Writes changes to a HistoryItem state bitmap to Atrace.
     */
@@ -1355,7 +1337,7 @@ public class BatteryStatsHistory {
            mTraceLastState2 = cur.states2;
        }

        if (!mHaveBatteryLevel || !mRecordingHistory) {
        if ((!mHaveBatteryLevel || !mRecordingHistory) && cur.powerStats == null) {
            return;
        }

@@ -1391,8 +1373,7 @@ public class BatteryStatsHistory {
                && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
                && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
                && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage
                && mHistoryLastWritten.energyConsumerDetails == null
                && mHistoryLastWritten.cpuUsageDetails == null) {
                && mHistoryLastWritten.powerStats == null) {
            // We can merge this new change in with the last one.  Merging is
            // allowed as long as only the states have changed, and within those states
            // as long as no bit has changed both between now and the last entry, as
@@ -1454,8 +1435,7 @@ public class BatteryStatsHistory {
            for (Map.Entry<HistoryTag, Integer> entry : mHistoryTagPool.entrySet()) {
                entry.setValue(entry.getValue() | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG);
            }
            mMeasuredEnergyHeaderWritten = false;
            mCpuUsageHeaderWritten = false;
            mWrittenPowerStatsDescriptors.clear();

            // Make a copy of mHistoryCur.
            HistoryItem copy = new HistoryItem();
@@ -1477,8 +1457,7 @@ public class BatteryStatsHistory {
            copy.eventCode = HistoryItem.EVENT_NONE;
            copy.eventTag = null;
            copy.tagsFirstOccurrence = false;
            copy.energyConsumerDetails = null;
            copy.cpuUsageDetails = null;
            copy.powerStats = null;
            writeHistoryItem(elapsedRealtimeMs, uptimeMs, copy, HistoryItem.CMD_RESET);
        }
        writeHistoryItem(elapsedRealtimeMs, uptimeMs, cur, HistoryItem.CMD_UPDATE);
@@ -1506,8 +1485,7 @@ public class BatteryStatsHistory {
        cur.eventCode = HistoryItem.EVENT_NONE;
        cur.eventTag = null;
        cur.tagsFirstOccurrence = false;
        cur.energyConsumerDetails = null;
        cur.cpuUsageDetails = null;
        cur.powerStats = null;
        if (DEBUG) {
            Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
                    + " now " + mHistoryBuffer.dataPosition()
@@ -1638,16 +1616,10 @@ public class BatteryStatsHistory {
        if (stateIntChanged) {
            firstToken |= BatteryStatsHistory.DELTA_STATE_FLAG;
        }
        if (cur.energyConsumerDetails != null) {
            extensionFlags |= BatteryStatsHistory.EXTENSION_MEASURED_ENERGY_FLAG;
            if (!mMeasuredEnergyHeaderWritten) {
                extensionFlags |= BatteryStatsHistory.EXTENSION_MEASURED_ENERGY_HEADER_FLAG;
            }
        }
        if (cur.cpuUsageDetails != null) {
            extensionFlags |= EXTENSION_CPU_USAGE_FLAG;
            if (!mCpuUsageHeaderWritten) {
                extensionFlags |= BatteryStatsHistory.EXTENSION_CPU_USAGE_HEADER_FLAG;
        if (cur.powerStats != null) {
            extensionFlags |= BatteryStatsHistory.EXTENSION_POWER_STATS_FLAG;
            if (!mWrittenPowerStatsDescriptors.contains(cur.powerStats.descriptor)) {
                extensionFlags |= BatteryStatsHistory.EXTENSION_POWER_STATS_DESCRIPTOR_FLAG;
            }
        }
        if (extensionFlags != 0) {
@@ -1773,37 +1745,13 @@ public class BatteryStatsHistory {
        dest.writeDouble(cur.wifiRailChargeMah);
        if (extensionFlags != 0) {
            dest.writeInt(extensionFlags);
            if (cur.energyConsumerDetails != null) {
                if (DEBUG) {
                    Slog.i(TAG, "WRITE DELTA: measuredEnergyDetails=" + cur.energyConsumerDetails);
            if (cur.powerStats != null) {
                if ((extensionFlags & BatteryStatsHistory.EXTENSION_POWER_STATS_DESCRIPTOR_FLAG)
                        != 0) {
                    cur.powerStats.descriptor.writeSummaryToParcel(dest);
                    mWrittenPowerStatsDescriptors.add(cur.powerStats.descriptor);
                }
                if (!mMeasuredEnergyHeaderWritten) {
                    EnergyConsumerDetails.EnergyConsumer[] consumers =
                            cur.energyConsumerDetails.consumers;
                    dest.writeInt(consumers.length);
                    for (EnergyConsumerDetails.EnergyConsumer consumer : consumers) {
                        dest.writeInt(consumer.type);
                        dest.writeInt(consumer.ordinal);
                        dest.writeString(consumer.name);
                    }
                    mMeasuredEnergyHeaderWritten = true;
                }
                mVarintParceler.writeLongArray(dest, cur.energyConsumerDetails.chargeUC);
            }

            if (cur.cpuUsageDetails != null) {
                if (DEBUG) {
                    Slog.i(TAG, "WRITE DELTA: cpuUsageDetails=" + cur.cpuUsageDetails);
                }
                if (!mCpuUsageHeaderWritten) {
                    dest.writeInt(cur.cpuUsageDetails.cpuBracketDescriptions.length);
                    for (String desc: cur.cpuUsageDetails.cpuBracketDescriptions) {
                        dest.writeString(desc);
                    }
                    mCpuUsageHeaderWritten = true;
                }
                dest.writeInt(cur.cpuUsageDetails.uid);
                mVarintParceler.writeLongArray(dest, cur.cpuUsageDetails.cpuUsageMs);
                cur.powerStats.writeToParcel(dest);
            }
        }
    }
@@ -2054,13 +2002,15 @@ public class BatteryStatsHistory {
     * fewer bytes.  It is a bit more expensive than just writing the long into the parcel,
     * but at scale saves a lot of storage and allows recording of longer battery history.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public static final class VarintParceler {
        /**
         * Writes an array of longs into Parcel using the varint format, see
         * https://developers.google.com/protocol-buffers/docs/encoding#varints
         */
        public void writeLongArray(Parcel parcel, long[] values) {
            if (values.length == 0) {
                return;
            }
            int out = 0;
            int shift = 0;
            for (long value : values) {
@@ -2092,6 +2042,9 @@ public class BatteryStatsHistory {
         * Reads a long written with {@link #writeLongArray}
         */
        public void readLongArray(Parcel parcel, long[] values) {
            if (values.length == 0) {
                return;
            }
            int in = parcel.readInt();
            int available = 4;
            for (int i = 0; i < values.length; i++) {
+9 −72
Original line number Diff line number Diff line
@@ -36,16 +36,10 @@ public class BatteryStatsHistoryIterator implements Iterator<BatteryStats.Histor
    private final BatteryStats.HistoryStepDetails mReadHistoryStepDetails =
            new BatteryStats.HistoryStepDetails();
    private final SparseArray<BatteryStats.HistoryTag> mHistoryTags = new SparseArray<>();
    private BatteryStats.EnergyConsumerDetails mEnergyConsumerDetails;
    private BatteryStats.CpuUsageDetails mCpuUsageDetails;
    private final BatteryStatsHistory.VarintParceler mVarintParceler =
            new BatteryStatsHistory.VarintParceler();

    private final PowerStats.DescriptorRegistry mDescriptorRegistry =
            new PowerStats.DescriptorRegistry();
    private final BatteryStats.HistoryItem mHistoryItem = new BatteryStats.HistoryItem();

    private static final int MAX_ENERGY_CONSUMER_COUNT = 100;
    private static final int MAX_CPU_BRACKET_COUNT = 100;

    public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history) {
        mBatteryStatsHistory = history;
        mHistoryItem.clear();
@@ -229,74 +223,17 @@ public class BatteryStatsHistoryIterator implements Iterator<BatteryStats.Histor
        cur.wifiRailChargeMah = src.readDouble();
        if ((cur.states2 & BatteryStats.HistoryItem.STATE2_EXTENSIONS_FLAG) != 0) {
            final int extensionFlags = src.readInt();
            if ((extensionFlags & BatteryStatsHistory.EXTENSION_MEASURED_ENERGY_HEADER_FLAG) != 0) {
                if (mEnergyConsumerDetails == null) {
                    mEnergyConsumerDetails = new BatteryStats.EnergyConsumerDetails();
                }

                final int consumerCount = src.readInt();
                if (consumerCount > MAX_ENERGY_CONSUMER_COUNT) {
                    // Check to avoid a heap explosion in case the parcel is corrupted
                    throw new IllegalStateException(
                            "EnergyConsumer count too high: " + consumerCount
                                    + ". Max = " + MAX_ENERGY_CONSUMER_COUNT);
                }
                mEnergyConsumerDetails.consumers =
                        new BatteryStats.EnergyConsumerDetails.EnergyConsumer[consumerCount];
                mEnergyConsumerDetails.chargeUC = new long[consumerCount];
                for (int i = 0; i < consumerCount; i++) {
                    BatteryStats.EnergyConsumerDetails.EnergyConsumer consumer =
                            new BatteryStats.EnergyConsumerDetails.EnergyConsumer();
                    consumer.type = src.readInt();
                    consumer.ordinal = src.readInt();
                    consumer.name = src.readString();
                    mEnergyConsumerDetails.consumers[i] = consumer;
            if ((extensionFlags & BatteryStatsHistory.EXTENSION_POWER_STATS_DESCRIPTOR_FLAG) != 0) {
                PowerStats.Descriptor descriptor = PowerStats.Descriptor.readSummaryFromParcel(src);
                mDescriptorRegistry.register(descriptor);
            }
            }

            if ((extensionFlags & BatteryStatsHistory.EXTENSION_MEASURED_ENERGY_FLAG) != 0) {
                if (mEnergyConsumerDetails == null) {
                    throw new IllegalStateException("MeasuredEnergyDetails without a header");
                }

                mVarintParceler.readLongArray(src, mEnergyConsumerDetails.chargeUC);
                cur.energyConsumerDetails = mEnergyConsumerDetails;
            } else {
                cur.energyConsumerDetails = null;
            }

            if ((extensionFlags & BatteryStatsHistory.EXTENSION_CPU_USAGE_HEADER_FLAG) != 0) {
                mCpuUsageDetails = new BatteryStats.CpuUsageDetails();
                final int cpuBracketCount = src.readInt();
                if (cpuBracketCount > MAX_CPU_BRACKET_COUNT) {
                    // Check to avoid a heap explosion in case the parcel is corrupted
                    throw new IllegalStateException("Too many CPU brackets: " + cpuBracketCount
                            + ". Max = " + MAX_CPU_BRACKET_COUNT);
                }
                mCpuUsageDetails.cpuBracketDescriptions = new String[cpuBracketCount];
                for (int i = 0; i < cpuBracketCount; i++) {
                    mCpuUsageDetails.cpuBracketDescriptions[i] = src.readString();
                }
                mCpuUsageDetails.cpuUsageMs =
                        new long[mCpuUsageDetails.cpuBracketDescriptions.length];
            } else if (mCpuUsageDetails != null) {
                mCpuUsageDetails.cpuBracketDescriptions = null;
            }

            if ((extensionFlags & BatteryStatsHistory.EXTENSION_CPU_USAGE_FLAG) != 0) {
                if (mCpuUsageDetails == null) {
                    throw new IllegalStateException("CpuUsageDetails without a header");
                }

                mCpuUsageDetails.uid = src.readInt();
                mVarintParceler.readLongArray(src, mCpuUsageDetails.cpuUsageMs);
                cur.cpuUsageDetails = mCpuUsageDetails;
            if ((extensionFlags & BatteryStatsHistory.EXTENSION_POWER_STATS_FLAG) != 0) {
                cur.powerStats = PowerStats.readFromParcel(src, mDescriptorRegistry);
            } else {
                cur.cpuUsageDetails = null;
                cur.powerStats = null;
            }
        } else {
            cur.energyConsumerDetails = null;
            cur.cpuUsageDetails = null;
            cur.powerStats = null;
        }
    }

+37 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.os.BatteryConsumer;
import android.os.Bundle;
import android.os.Parcel;
import android.os.UserHandle;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.SparseArray;
@@ -137,6 +138,20 @@ public final class PowerStats {
            return new Descriptor(powerComponentId, name, statsArrayLength, uidStatsArrayLength,
                    extras);
        }

        @Override
        public String toString() {
            if (extras != null) {
                extras.size();  // Unparcel
            }
            return "PowerStats.Descriptor{"
                    + "powerComponentId=" + powerComponentId
                    + ", name='" + name + '\''
                    + ", statsArrayLength=" + statsArrayLength
                    + ", uidStatsArrayLength=" + uidStatsArrayLength
                    + ", extras=" + extras
                    + '}';
        }
    }

    /**
@@ -250,6 +265,23 @@ public final class PowerStats {
        }
    }

    /**
     * Formats the stats as a string suitable to be included in the Battery History dump.
     */
    public String formatForBatteryHistory(String uidPrefix) {
        StringBuilder sb = new StringBuilder();
        sb.append("duration=").append(durationMs).append(" ").append(descriptor.name);
        if (stats.length > 0) {
            sb.append("=").append(Arrays.toString(stats));
        }
        for (int i = 0; i < uidStats.size(); i++) {
            sb.append(uidPrefix)
                    .append(UserHandle.formatUid(uidStats.keyAt(i)))
                    .append(": ").append(Arrays.toString(uidStats.valueAt(i)));
        }
        return sb.toString();
    }

    /**
     * Prints the contents of the stats snapshot.
     */
@@ -266,4 +298,9 @@ public final class PowerStats {
        }
        pw.decreaseIndent();
    }

    @Override
    public String toString() {
        return "PowerStats: " + formatForBatteryHistory(" UID ");
    }
}
+0 −6

File changed.

Preview size limit exceeded, changes collapsed.

Loading