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

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

Merge changes I99c836be,I1532ee40,Ic7f9107b into main

* changes:
  Convert BatteryChargeCalculator to a PowerStatsProcessor
  Add PowerStats collector and processor for Wakelocks
  Use procState change events to compute time-in-state duration
parents c9d7ca62 65f84edd
Loading
Loading
Loading
Loading
+18 −4
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ public abstract class BatteryConsumer {
            POWER_COMPONENT_AMBIENT_DISPLAY,
            POWER_COMPONENT_IDLE,
            POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS,
            POWER_COMPONENT_BASE,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface PowerComponent {
@@ -101,8 +102,10 @@ public abstract class BatteryConsumer {
    // The value should be negative or zero.
    public static final int POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS =
            OsProtoEnums.POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS; // 17

    public static final int POWER_COMPONENT_COUNT = 18;
    // Power component ID that is used for technical purposes of attribution of time-in-state
    // for UIDs and other general computations not associated with specific hardware.
    public static final int POWER_COMPONENT_BASE = 18;
    public static final int POWER_COMPONENT_COUNT = 19;

    public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
    public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
@@ -129,6 +132,7 @@ public abstract class BatteryConsumer {
        sPowerComponentNames[POWER_COMPONENT_AMBIENT_DISPLAY] = "ambient_display";
        sPowerComponentNames[POWER_COMPONENT_IDLE] = "idle";
        sPowerComponentNames[POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS] = "reattributed";
        sPowerComponentNames[POWER_COMPONENT_BASE] = "";        // Top-level, no need for a name
    }

    /**
@@ -211,6 +215,7 @@ public abstract class BatteryConsumer {
    private static final IntArray SUPPORTED_POWER_COMPONENTS_PER_PROCESS_STATE;
    static {
        int[] supportedPowerComponents = {
                POWER_COMPONENT_BASE,
                POWER_COMPONENT_CPU,
                POWER_COMPONENT_MOBILE_RADIO,
                POWER_COMPONENT_WIFI,
@@ -220,7 +225,9 @@ public abstract class BatteryConsumer {
                POWER_COMPONENT_FLASHLIGHT,
                POWER_COMPONENT_CAMERA,
                POWER_COMPONENT_GNSS,
                POWER_COMPONENT_SENSORS};
                POWER_COMPONENT_SENSORS,
                POWER_COMPONENT_WAKELOCK,
        };
        Arrays.sort(supportedPowerComponents);
        SUPPORTED_POWER_COMPONENTS_PER_PROCESS_STATE = IntArray.wrap(supportedPowerComponents);
    };
@@ -939,7 +946,7 @@ public abstract class BatteryConsumer {
            ));

            // Declare Keys for all process states, if needed
            if (includeProcessStateData) {
            if (includeProcessStateData || componentId == POWER_COMPONENT_BASE) {
                boolean isSupported = SUPPORTED_POWER_COMPONENTS_PER_PROCESS_STATE
                        .binarySearch(componentId) >= 0
                        || componentId >= FIRST_CUSTOM_POWER_COMPONENT_ID;
@@ -1126,6 +1133,13 @@ public abstract class BatteryConsumer {
            return (T) this;
        }

        @SuppressWarnings("unchecked")
        @NonNull
        public T addUsageDurationMillis(Key key, long componentUsageTimeMillis) {
            mPowerComponentsBuilder.addUsageDurationMillis(key, componentUsageTimeMillis);
            return (T) this;
        }

        /**
         * Returns the total power accumulated by this builder so far. It may change
         * by the time the {@code build()} method is called.
+17 −1
Original line number Diff line number Diff line
@@ -1950,7 +1950,8 @@ public abstract class BatteryStats {

        // STATES bits that are used for Power Stats tracking
        public static final int IMPORTANT_FOR_POWER_STATS_STATES =
                STATE_GPS_ON_FLAG | STATE_SENSOR_ON_FLAG | STATE_AUDIO_ON_FLAG;
                STATE_GPS_ON_FLAG | STATE_SENSOR_ON_FLAG | STATE_AUDIO_ON_FLAG
                        | STATE_WAKE_LOCK_FLAG;

        @UnsupportedAppUsage
        public int states;
@@ -3624,6 +3625,21 @@ public abstract class BatteryStats {
     */
    public abstract int getLearnedBatteryCapacity();

    /**
     * Returns best known estimate of the battery capacity in milli-amp-hours.
     */
    public int getBatteryCapacity() {
        int batteryCapacityUah = getLearnedBatteryCapacity();
        if (batteryCapacityUah > 0) {
            return batteryCapacityUah / 1000;
        }
        batteryCapacityUah = getMinLearnedBatteryCapacity();
        if (batteryCapacityUah > 0) {
            return batteryCapacityUah / 1000;
        }
        return getEstimatedBatteryCapacity();
    }

    /**
     * Return the array of discharge step durations.
     */
+13 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package android.os;

import static android.os.BatteryConsumer.BatteryConsumerDataLayout.POWER_MODEL_NOT_INCLUDED;
import static android.os.BatteryConsumer.POWER_COMPONENT_ANY;
import static android.os.BatteryConsumer.POWER_COMPONENT_BASE;
import static android.os.BatteryConsumer.POWER_STATE_ANY;
import static android.os.BatteryConsumer.POWER_STATE_UNSPECIFIED;
import static android.os.BatteryConsumer.PROCESS_STATE_ANY;
@@ -184,6 +185,10 @@ class PowerComponents {
            @BatteryConsumer.PowerState int powerState, boolean skipEmptyComponents) {
        StringBuilder sb = new StringBuilder();
        for (@BatteryConsumer.PowerComponentId int id : mData.layout.powerComponentIds) {
            if (id == POWER_COMPONENT_BASE) {
                continue;
            }

            dump(sb, id, PROCESS_STATE_ANY, screenState, powerState, skipEmptyComponents);
            if (mData.layout.processStateDataIncluded) {
                for (int processState = 0; processState < BatteryConsumer.PROCESS_STATE_COUNT;
@@ -491,6 +496,14 @@ class PowerComponents {
            return this;
        }

        @NonNull
        public Builder addUsageDurationMillis(BatteryConsumer.Key key,
                long componentUsageDurationMillis) {
            mData.putLong(key.mDurationColumnIndex,
                    mData.getLong(key.mDurationColumnIndex) + componentUsageDurationMillis);
            return this;
        }

        public void addPowerAndDuration(PowerComponents.Builder other) {
            addPowerAndDuration(other.mData);
        }
+31 −54
Original line number Diff line number Diff line
@@ -70,10 +70,7 @@ public final class UidBatteryConsumer extends BatteryConsumer {

    static final int COLUMN_INDEX_UID = BatteryConsumer.COLUMN_COUNT;
    static final int COLUMN_INDEX_PACKAGE_WITH_HIGHEST_DRAIN = COLUMN_INDEX_UID + 1;
    static final int COLUMN_INDEX_TIME_IN_FOREGROUND = COLUMN_INDEX_UID + 2;
    static final int COLUMN_INDEX_TIME_IN_BACKGROUND = COLUMN_INDEX_UID + 3;
    static final int COLUMN_INDEX_TIME_IN_FOREGROUND_SERVICE = COLUMN_INDEX_UID + 4;
    static final int COLUMN_COUNT = BatteryConsumer.COLUMN_COUNT + 5;
    static final int COLUMN_COUNT = BatteryConsumer.COLUMN_COUNT + 2;

    UidBatteryConsumer(BatteryConsumerData data) {
        super(data);
@@ -100,10 +97,10 @@ public final class UidBatteryConsumer extends BatteryConsumer {
    public long getTimeInStateMs(@State int state) {
        switch (state) {
            case STATE_BACKGROUND:
                return mData.getInt(COLUMN_INDEX_TIME_IN_BACKGROUND)
                        + mData.getInt(COLUMN_INDEX_TIME_IN_FOREGROUND_SERVICE);
                return getTimeInProcessStateMs(PROCESS_STATE_BACKGROUND)
                        + getTimeInProcessStateMs(PROCESS_STATE_FOREGROUND_SERVICE);
            case STATE_FOREGROUND:
                return mData.getInt(COLUMN_INDEX_TIME_IN_FOREGROUND);
                return getTimeInProcessStateMs(PROCESS_STATE_FOREGROUND);
        }
        return 0;
    }
@@ -112,13 +109,9 @@ public final class UidBatteryConsumer extends BatteryConsumer {
     * Returns the amount of time in milliseconds this UID spent in the specified process state.
     */
    public long getTimeInProcessStateMs(@ProcessState int state) {
        switch (state) {
            case PROCESS_STATE_BACKGROUND:
                return mData.getInt(COLUMN_INDEX_TIME_IN_BACKGROUND);
            case PROCESS_STATE_FOREGROUND:
                return mData.getInt(COLUMN_INDEX_TIME_IN_FOREGROUND);
            case PROCESS_STATE_FOREGROUND_SERVICE:
                return mData.getInt(COLUMN_INDEX_TIME_IN_FOREGROUND_SERVICE);
        Key key = getKey(POWER_COMPONENT_BASE, state);
        if (key != null) {
            return getUsageDurationMillis(key);
        }
        return 0;
    }
@@ -130,7 +123,6 @@ public final class UidBatteryConsumer extends BatteryConsumer {
        pw.print(": ");
        pw.print(BatteryStats.formatCharge(getConsumedPower()));

        if (mData.layout.processStateDataIncluded) {
        StringBuilder sb = new StringBuilder();
        appendProcessStateData(sb, BatteryConsumer.PROCESS_STATE_FOREGROUND,
                skipEmptyComponents);
@@ -141,9 +133,6 @@ public final class UidBatteryConsumer extends BatteryConsumer {
        appendProcessStateData(sb, BatteryConsumer.PROCESS_STATE_CACHED,
                skipEmptyComponents);
        pw.println(sb);
        } else {
            pw.println();
        }

        pw.print("      ");
        mPowerComponents.dump(pw, SCREEN_STATE_ANY, POWER_STATE_ANY, skipEmptyComponents);
@@ -190,12 +179,20 @@ public final class UidBatteryConsumer extends BatteryConsumer {
            boolean skipEmptyComponents) {
        Dimensions dimensions = new Dimensions(POWER_COMPONENT_ANY, processState);
        final double power = mPowerComponents.getConsumedPower(dimensions);
        if (power == 0 && skipEmptyComponents) {

        Key key = getKey(POWER_COMPONENT_BASE, processState);
        long durationMs = key != null ? mPowerComponents.getUsageDurationMillis(key) : 0;
        if (power == 0 && durationMs == 0 && skipEmptyComponents) {
            return;
        }

        sb.append(" ").append(processStateToString(processState)).append(": ")
                .append(BatteryStats.formatCharge(power));
        if (durationMs != 0) {
            sb.append(" (");
            BatteryStats.formatTimeMsNoSpace(sb, durationMs);
            sb.append(")");
        }
    }

    /** Serializes this object to XML */
@@ -322,10 +319,10 @@ public final class UidBatteryConsumer extends BatteryConsumer {
        public Builder setTimeInStateMs(@State int state, long timeInStateMs) {
            switch (state) {
                case STATE_FOREGROUND:
                    mData.putLong(COLUMN_INDEX_TIME_IN_FOREGROUND, timeInStateMs);
                    setTimeInProcessStateMs(PROCESS_STATE_FOREGROUND, timeInStateMs);
                    break;
                case STATE_BACKGROUND:
                    mData.putLong(COLUMN_INDEX_TIME_IN_BACKGROUND, timeInStateMs);
                    setTimeInProcessStateMs(PROCESS_STATE_BACKGROUND, timeInStateMs);
                    break;
                default:
                    throw new IllegalArgumentException("Unsupported state: " + state);
@@ -339,18 +336,9 @@ public final class UidBatteryConsumer extends BatteryConsumer {
         */
        @NonNull
        public Builder setTimeInProcessStateMs(@ProcessState int state, long timeInProcessStateMs) {
            switch (state) {
                case PROCESS_STATE_FOREGROUND:
                    mData.putLong(COLUMN_INDEX_TIME_IN_FOREGROUND, timeInProcessStateMs);
                    break;
                case PROCESS_STATE_BACKGROUND:
                    mData.putLong(COLUMN_INDEX_TIME_IN_BACKGROUND, timeInProcessStateMs);
                    break;
                case PROCESS_STATE_FOREGROUND_SERVICE:
                    mData.putLong(COLUMN_INDEX_TIME_IN_FOREGROUND_SERVICE, timeInProcessStateMs);
                    break;
                default:
                    throw new IllegalArgumentException("Unsupported process state: " + state);
            Key key = getKey(POWER_COMPONENT_BASE, state);
            if (key != null) {
                mData.putLong(key.mDurationColumnIndex, timeInProcessStateMs);
            }
            return this;
        }
@@ -368,17 +356,6 @@ public final class UidBatteryConsumer extends BatteryConsumer {
         */
        public Builder add(UidBatteryConsumer consumer) {
            mPowerComponentsBuilder.addPowerAndDuration(consumer.mPowerComponents);

            setTimeInProcessStateMs(PROCESS_STATE_FOREGROUND,
                    mData.getLong(COLUMN_INDEX_TIME_IN_FOREGROUND)
                            + consumer.getTimeInProcessStateMs(PROCESS_STATE_FOREGROUND));
            setTimeInProcessStateMs(PROCESS_STATE_BACKGROUND,
                    mData.getLong(COLUMN_INDEX_TIME_IN_BACKGROUND)
                            + consumer.getTimeInProcessStateMs(PROCESS_STATE_BACKGROUND));
            setTimeInProcessStateMs(PROCESS_STATE_FOREGROUND_SERVICE,
                    mData.getLong(COLUMN_INDEX_TIME_IN_FOREGROUND_SERVICE)
                            + consumer.getTimeInProcessStateMs(PROCESS_STATE_FOREGROUND_SERVICE));

            if (mPackageWithHighestDrain == PACKAGE_NAME_UNINITIALIZED) {
                mPackageWithHighestDrain = consumer.getPackageWithHighestDrain();
            } else if (!TextUtils.equals(mPackageWithHighestDrain,
+18 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
@@ -1745,9 +1746,12 @@ public class BatteryStatsHistory {
                    mHistoryAddTmp.setTo(mHistoryLastWritten);
                    mHistoryAddTmp.wakelockTag = null;
                    mHistoryAddTmp.wakeReasonTag = null;
                    mHistoryAddTmp.powerStats = null;
                    mHistoryAddTmp.processStateChange = null;
                    mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
                    mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
                    writeHistoryItem(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp);

                }
            }
            mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
@@ -2452,6 +2456,20 @@ public class BatteryStatsHistory {
        }
    }

    /**
     * Prints battery stats history for debugging.
     */
    public void dump(PrintWriter pw, long startTimeMs, long endTimeMs) {
        BatteryStats.HistoryPrinter printer = new BatteryStats.HistoryPrinter();
        try (BatteryStatsHistoryIterator iterate = iterate(startTimeMs, endTimeMs)) {
            while (iterate.hasNext()) {
                HistoryItem next = iterate.next();
                printer.printNextItem(pw, next, 0, false, true);
            }
        }
        pw.flush();
    }

    /**
     * Writes/reads an array of longs into Parcel using a compact format, where small integers use
     * fewer bytes.  It is a bit more expensive than just writing the long into the parcel,
Loading