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

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

Merge changes from topic "incipient_sobs" into main

* changes:
  Add PowerStatsAggregator to aggregate power stats
  Add date range to battery history iterator
  Add multi-state stats container
  Include proc state change in battery history
  Include PowerStats snapshots in battery history
  Make PowerStats parcelable
parents 82831b69 afb6880a
Loading
Loading
Loading
Loading
+67 −135
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.os;
import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;

import android.annotation.CurrentTimeMillisLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -55,6 +56,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;

@@ -1793,75 +1795,55 @@ public abstract class BatteryStats {
    }

    /**
     * Measured energy delta from the previous reading.
     * An extension to the history item describing a proc state change for a UID.
     */
    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;
    public static final class ProcessStateChange {
        public int uid;
        public @BatteryConsumer.ProcessState int processState;

        private static final int LARGE_UID_FLAG = 0x80000000;
        private static final int SMALL_UID_MASK = 0x00FFFFFF;
        private static final int PROC_STATE_MASK = 0x7F000000;
        private static final int PROC_STATE_SHIFT = Integer.numberOfTrailingZeros(PROC_STATE_MASK);

        /**
             * Human-readable name of the energy consumer, e.g. "CPU"
         * Writes this object to the supplied parcel.
         */
            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();
        public void writeToParcel(Parcel out) {
            int bits = processState << PROC_STATE_SHIFT;
            if ((uid & ~SMALL_UID_MASK) == 0) {
                bits |= uid;
                out.writeInt(bits);
            } else {
                bits |= LARGE_UID_FLAG;
                out.writeInt(bits);
                out.writeInt(uid);
            }
        }

        /**
     * CPU usage for a given UID.
     */
    public static final class CpuUsageDetails {
        /**
         * Descriptions of CPU power brackets, see PowerProfile.getCpuPowerBracketDescription
         * Reads this object from the supplied parcel.
         */
        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(", ");
        public void readFromParcel(Parcel in) {
            int bits = in.readInt();
            processState = (bits & PROC_STATE_MASK) >>> PROC_STATE_SHIFT;
            if (processState >= BatteryConsumer.PROCESS_STATE_COUNT) {
                Slog.e(TAG, "Unrecognized proc state in battery history: " + processState);
                processState = BatteryConsumer.PROCESS_STATE_UNSPECIFIED;
            }
            if ((bits & LARGE_UID_FLAG) == 0) {
                uid = bits & ~PROC_STATE_MASK;
            } else {
                uid = in.readInt();
            }
                sb.append(cpuUsageMs[bracket]);
        }
            return sb.toString();

        /**
         * String representation for inclusion in the battery history dump.
         */
        public String formatForBatteryHistory() {
            return UserHandle.formatUid(uid) + ": "
                    + BatteryConsumer.processStateToString(processState);
        }
    }

@@ -2008,11 +1990,11 @@ 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 are power stats to be written to history
        public PowerStats powerStats;

        // Non-null when there is CPU usage information
        public CpuUsageDetails cpuUsageDetails;
        // Non-null when there is procstate change to be written to history
        public ProcessStateChange processStateChange;

        public static final int EVENT_FLAG_START = 0x8000;
        public static final int EVENT_FLAG_FINISH = 0x4000;
@@ -2110,6 +2092,7 @@ public abstract class BatteryStats {
        public final HistoryTag localWakelockTag = new HistoryTag();
        public final HistoryTag localWakeReasonTag = new HistoryTag();
        public final HistoryTag localEventTag = new HistoryTag();
        public final ProcessStateChange localProcessStateChange = new ProcessStateChange();

        // 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.
@@ -2222,8 +2205,8 @@ public abstract class BatteryStats {
            eventCode = EVENT_NONE;
            eventTag = null;
            tagsFirstOccurrence = false;
            energyConsumerDetails = null;
            cpuUsageDetails = null;
            powerStats = null;
            processStateChange = null;
        }

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

        public boolean sameNonEvent(HistoryItem o) {
@@ -2434,8 +2417,14 @@ public abstract class BatteryStats {
     * Returns a BatteryStatsHistoryIterator. Battery history will continue being writable,
     * but the iterator will continue iterating over the snapshot taken at the time this method
     * is called.
     *
     * @param startTimeMs wall-clock time to start iterating from, inclusive
     * @param endTimeMs wall-clock time to stop iterating, exclusive.
     *                  Pass 0 to indicate current time.
     */
    public abstract BatteryStatsHistoryIterator iterateBatteryStatsHistory();
    public abstract BatteryStatsHistoryIterator iterateBatteryStatsHistory(
            @CurrentTimeMillisLong long startTimeMs,
            @CurrentTimeMillisLong long endTimeMs);

    /**
     * Returns the number of times the device has been started.
@@ -6911,25 +6900,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 +7135,19 @@ 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]);
                            }
                        item.append(
                                "\n                 Stats: ");
                        item.append(rec.powerStats.formatForBatteryHistory(
                                "\n                    "));
                    }
                }
                }
                if (rec.cpuUsageDetails != null) {
                if (rec.processStateChange != null && verbose) {
                    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(" procstate: ");
                        item.append(rec.processStateChange.formatForBatteryHistory());
                    }
                    firstExtension = false;
                }
                item.append("\n");
                if (rec.stepDetails != null) {
@@ -7537,7 +7469,7 @@ public abstract class BatteryStats {
        long baseTime = -1;
        boolean printed = false;
        HistoryEventTracker tracker = null;
        try (BatteryStatsHistoryIterator iterator = iterateBatteryStatsHistory()) {
        try (BatteryStatsHistoryIterator iterator = iterateBatteryStatsHistory(0, 0)) {
            HistoryItem rec;
            while ((rec = iterator.next()) != null) {
                try {
@@ -8460,7 +8392,7 @@ public abstract class BatteryStats {
        long baseTime = -1;
        boolean printed = false;
        HistoryEventTracker tracker = null;
        try (BatteryStatsHistoryIterator iterator = iterateBatteryStatsHistory()) {
        try (BatteryStatsHistoryIterator iterator = iterateBatteryStatsHistory(0, 0)) {
            HistoryItem rec;
            while ((rec = iterator.next()) != null) {
                lastTime = rec.time;
+1 −1
Original line number Diff line number Diff line
@@ -315,7 +315,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
            throw new IllegalStateException(
                    "Battery history was not requested in the BatteryUsageStatsQuery");
        }
        return new BatteryStatsHistoryIterator(mBatteryStatsHistory);
        return new BatteryStatsHistoryIterator(mBatteryStatsHistory, 0, 0);
    }

    @Override
+196 −159

File changed.

Preview size limit exceeded, changes collapsed.

+64 −93
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.internal.os;

import android.annotation.CurrentTimeMillisLong;
import android.annotation.NonNull;
import android.os.BatteryManager;
import android.os.BatteryStats;
@@ -33,32 +34,32 @@ public class BatteryStatsHistoryIterator implements Iterator<BatteryStats.Histor
    private static final boolean DEBUG = false;
    private static final String TAG = "BatteryStatsHistoryItr";
    private final BatteryStatsHistory mBatteryStatsHistory;
    private final @CurrentTimeMillisLong long mStartTimeMs;
    private final @CurrentTimeMillisLong long mEndTimeMs;
    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 BatteryStats.HistoryItem mHistoryItem = new BatteryStats.HistoryItem();
    private boolean mNextItemReady;

    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) {
    public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history,
            @CurrentTimeMillisLong long startTimeMs,
            @CurrentTimeMillisLong long endTimeMs) {
        mBatteryStatsHistory = history;
        mStartTimeMs = startTimeMs;
        mEndTimeMs = (endTimeMs != 0) ? endTimeMs : Long.MAX_VALUE;
        mHistoryItem.clear();
    }

    @Override
    public boolean hasNext() {
        Parcel p = mBatteryStatsHistory.getNextParcel();
        if (p == null) {
            close();
            return false;
        if (!mNextItemReady) {
            advance();
        }
        return true;

        return mHistoryItem != null;
    }

    /**
@@ -67,10 +68,18 @@ public class BatteryStatsHistoryIterator implements Iterator<BatteryStats.Histor
     */
    @Override
    public BatteryStats.HistoryItem next() {
        Parcel p = mBatteryStatsHistory.getNextParcel();
        if (!mNextItemReady) {
            advance();
        }
        mNextItemReady = false;
        return mHistoryItem;
    }

    private void advance() {
        while (true) {
            Parcel p = mBatteryStatsHistory.getNextParcel(mStartTimeMs, mEndTimeMs);
            if (p == null) {
            close();
            return null;
                break;
            }

            final long lastRealtimeMs = mHistoryItem.time;
@@ -79,13 +88,25 @@ public class BatteryStatsHistoryIterator implements Iterator<BatteryStats.Histor
                readHistoryDelta(p, mHistoryItem);
            } catch (Throwable t) {
                Slog.wtf(TAG, "Corrupted battery history", t);
            return null;
                break;
            }
            if (mHistoryItem.cmd != BatteryStats.HistoryItem.CMD_CURRENT_TIME
                && mHistoryItem.cmd != BatteryStats.HistoryItem.CMD_RESET && lastWalltimeMs != 0) {
                    && mHistoryItem.cmd != BatteryStats.HistoryItem.CMD_RESET
                    && lastWalltimeMs != 0) {
                mHistoryItem.currentTime = lastWalltimeMs + (mHistoryItem.time - lastRealtimeMs);
            }
        return mHistoryItem;
            if (mEndTimeMs != 0 && mHistoryItem.currentTime >= mEndTimeMs) {
                break;
            }
            if (mHistoryItem.currentTime >= mStartTimeMs) {
                mNextItemReady = true;
                return;
            }
        }

        mHistoryItem = null;
        mNextItemReady = true;
        close();
    }

    private void readHistoryDelta(Parcel src, BatteryStats.HistoryItem cur) {
@@ -229,74 +250,24 @@ 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;
            if ((extensionFlags & BatteryStatsHistory.EXTENSION_POWER_STATS_FLAG) != 0) {
                cur.powerStats = PowerStats.readFromParcel(src, mDescriptorRegistry);
            } 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");
                cur.powerStats = null;
            }

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

+32 −0
Original line number Diff line number Diff line
@@ -190,6 +190,34 @@ public final class LongArrayMultiStateCounter implements Parcelable {
        native_setState(mNativeObject, state, timestampMs);
    }

    /**
     * Sets the new values.  The delta between the previously set values and these values
     * is distributed among the state according to the time the object spent in those states
     * since the previous call to updateValues.
     */
    public void updateValues(long[] values, long timestampMs) {
        LongArrayContainer container = sTmpArrayContainer.getAndSet(null);
        if (container == null || container.mLength != values.length) {
            container = new LongArrayContainer(values.length);
        }
        container.setValues(values);
        updateValues(container, timestampMs);
        sTmpArrayContainer.set(container);
    }

    /**
     * Adds the supplied values to the current accumulated values in the counter.
     */
    public void incrementValues(long[] values, long timestampMs) {
        LongArrayContainer container = sTmpArrayContainer.getAndSet(null);
        if (container == null || container.mLength != values.length) {
            container = new LongArrayContainer(values.length);
        }
        container.setValues(values);
        native_incrementValues(mNativeObject, container.mNativeObject, timestampMs);
        sTmpArrayContainer.set(container);
    }

    /**
     * Sets the new values.  The delta between the previously set values and these values
     * is distributed among the state according to the time the object spent in those states
@@ -292,6 +320,10 @@ public final class LongArrayMultiStateCounter implements Parcelable {
    private static native void native_updateValues(long nativeObject,
            long longArrayContainerNativeObject, long timestampMs);

    @CriticalNative
    private static native void native_incrementValues(long nativeObject,
            long longArrayContainerNativeObject, long timestampMs);

    @CriticalNative
    private static native void native_addCounts(long nativeObject,
            long longArrayContainerNativeObject);
Loading