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

Commit 6581acd7 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Use procState change events to compute time-in-state duration

Bug: 345022340
Test: atest PowerStatsTests; atest PowerStatsTestsRavenwood
Flag: com.android.server.power.optimization.accumulate_battery_usage_stats
Change-Id: Ic7f9107b3b6d262089c81e521862300b08cb1c40
parent 183cfc93
Loading
Loading
Loading
Loading
+15 −3
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,
@@ -939,7 +944,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 +1131,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.
+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,
+11 −4
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.BatteryConsumer.POWER_COMPONENT_BASE;
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;

import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
@@ -1224,8 +1225,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub

            final float totalDeviceConsumedPowerMah = (float) deviceConsumer.getConsumedPower();

            for (@BatteryConsumer.PowerComponentId int componentIndex :
            for (@BatteryConsumer.PowerComponentId int powerComponentId :
                    deviceConsumer.getPowerComponentIds()) {
                if (powerComponentId == POWER_COMPONENT_BASE) {
                    continue;
                }

                for (@BatteryConsumer.ProcessState int processState : UID_PROCESS_STATES) {

@@ -1237,7 +1241,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                            totalDeviceConsumedPowerMah,
                            0,
                            deviceConsumer,
                            componentIndex)) {
                            powerComponentId)) {
                        return StatsManager.PULL_SUCCESS;
                    }
                }
@@ -1253,8 +1257,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                final int uid = uidConsumer.getUid();
                final float totalConsumedPowerMah = (float) uidConsumer.getConsumedPower();

                for (@BatteryConsumer.PowerComponentId int componentIndex :
                for (@BatteryConsumer.PowerComponentId int powerComponentId :
                        uidConsumer.getPowerComponentIds()) {
                    if (powerComponentId == POWER_COMPONENT_BASE) {
                        continue;
                    }

                    for (@BatteryConsumer.ProcessState int processState : UID_PROCESS_STATES) {

@@ -1268,7 +1275,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                                totalConsumedPowerMah,
                                timeInProcessStateMs,
                                uidConsumer,
                                componentIndex)) {
                                powerComponentId)) {
                            return StatsManager.PULL_SUCCESS;
                        }
                    }
+1 −3
Original line number Diff line number Diff line
@@ -10910,7 +10910,6 @@ public class BatteryStatsImpl extends BatteryStats {
            // Make special note of Foreground Services
            final boolean userAwareService = ActivityManager.isForegroundService(procState);
            uidRunningState = BatteryStats.mapToInternalProcessState(procState);
            if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
                return;
            }
@@ -10949,8 +10948,7 @@ public class BatteryStatsImpl extends BatteryStats {
                final int batteryConsumerProcessState =
                        mapUidProcessStateToBatteryConsumerProcessState(uidRunningState);
                if (mBsi.mSystemReady && mBsi.mPowerStatsCollectorEnabled.get(
                        BatteryConsumer.POWER_COMPONENT_CPU)) {
                if (mBsi.mSystemReady) {
                    mBsi.mHistory.recordProcessStateChange(elapsedRealtimeMs, uptimeMs, mUid,
                            batteryConsumerProcessState);
                }
Loading