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

Commit d1635747 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Simplify SystemServicePowerCalculator

Fix SystemServicePowerCalculatorTest

Test: atest FrameworksCoreTests:com.android.internal.os.SystemServicePowerCalculatorTest
Bug: 158137862

Change-Id: Ia3218b5c91eacfc0122a35d0898bddd8394f8c4e
parent 4c4fc216
Loading
Loading
Loading
Loading
+14 −1
Original line number Original line Diff line number Diff line
@@ -48,6 +48,7 @@ public abstract class BatteryConsumer {
            POWER_COMPONENT_SENSORS,
            POWER_COMPONENT_SENSORS,
            POWER_COMPONENT_GNSS,
            POWER_COMPONENT_GNSS,
            POWER_COMPONENT_SCREEN,
            POWER_COMPONENT_SCREEN,
            POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS,
    })
    })
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    public static @interface PowerComponent {
    public static @interface PowerComponent {
@@ -65,8 +66,12 @@ public abstract class BatteryConsumer {
    public static final int POWER_COMPONENT_SENSORS = 9;
    public static final int POWER_COMPONENT_SENSORS = 9;
    public static final int POWER_COMPONENT_GNSS = 10;
    public static final int POWER_COMPONENT_GNSS = 10;
    public static final int POWER_COMPONENT_SCREEN = 13;
    public static final int POWER_COMPONENT_SCREEN = 13;
    // Power that is re-attributed to other battery consumers. For example, for System Server
    // this represents the power attributed to apps requesting system services.
    // The value should be negative or zero.
    public static final int POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS = 14;


    public static final int POWER_COMPONENT_COUNT = 14;
    public static final int POWER_COMPONENT_COUNT = 15;


    public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
    public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
    public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
    public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
@@ -236,5 +241,13 @@ public abstract class BatteryConsumer {
                    componentUsageTimeMillis);
                    componentUsageTimeMillis);
            return (T) this;
            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.
         */
        public double getTotalPower() {
            return mPowerComponentsBuilder.getTotalPower();
        }
    }
    }
}
}
+13 −5
Original line number Original line Diff line number Diff line
@@ -38,11 +38,7 @@ class PowerComponents {
        mCustomPowerComponentCount = builder.mCustomPowerComponentCount;
        mCustomPowerComponentCount = builder.mCustomPowerComponentCount;
        mPowerComponents = builder.mPowerComponents;
        mPowerComponents = builder.mPowerComponents;
        mTimeComponents = builder.mTimeComponents;
        mTimeComponents = builder.mTimeComponents;
        double totalPower = 0;
        mTotalPowerConsumed = builder.getTotalPower();
        for (int i = mPowerComponents.length - 1; i >= 0; i--) {
            totalPower += mPowerComponents[i];
        }
        mTotalPowerConsumed = totalPower;
    }
    }


    PowerComponents(@NonNull Parcel source) {
    PowerComponents(@NonNull Parcel source) {
@@ -263,6 +259,18 @@ class PowerComponents {
            }
            }
        }
        }


        /**
         * Returns the total power accumulated by this builder so far. It may change
         * by the time the {@code build()} method is called.
         */
        public double getTotalPower() {
            double totalPower = 0;
            for (int i = mPowerComponents.length - 1; i >= 0; i--) {
                totalPower += mPowerComponents[i];
            }
            return totalPower;
        }

        /**
        /**
         * Creates a read-only object out of the Builder values.
         * Creates a read-only object out of the Builder values.
         */
         */
+10 −0
Original line number Original line Diff line number Diff line
@@ -135,6 +135,11 @@ public class BatterySipper implements Comparable<BatterySipper> {
    public double systemServiceCpuPowerMah;
    public double systemServiceCpuPowerMah;
    public double[] customMeasuredPowerMah;
    public double[] customMeasuredPowerMah;


    // Power that is re-attributed to other sippers. For example, for System Server
    // this represents the power attributed to apps requesting system services.
    // The value should be negative or zero.
    public double powerReattributedToOtherSippersMah;

    // Do not include this sipper in results because it is included
    // Do not include this sipper in results because it is included
    // in an aggregate sipper.
    // in an aggregate sipper.
    public boolean isAggregated;
    public boolean isAggregated;
@@ -263,6 +268,7 @@ public class BatterySipper implements Comparable<BatterySipper> {
                }
                }
            }
            }
        }
        }
        powerReattributedToOtherSippersMah += other.powerReattributedToOtherSippersMah;
    }
    }


    /**
    /**
@@ -281,6 +287,10 @@ public class BatterySipper implements Comparable<BatterySipper> {
                totalPowerMah += customMeasuredPowerMah[idx];
                totalPowerMah += customMeasuredPowerMah[idx];
            }
            }
        }
        }

        // powerAttributedToOtherSippersMah is negative or zero
        totalPowerMah = totalPowerMah + powerReattributedToOtherSippersMah;

        totalSmearedPowerMah = totalPowerMah + screenPowerMah + proportionalSmearMah;
        totalSmearedPowerMah = totalPowerMah + screenPowerMah + proportionalSmearMah;


        return totalPowerMah;
        return totalPowerMah;
+7 −3
Original line number Original line Diff line number Diff line
@@ -70,11 +70,14 @@ public class BatteryUsageStatsProvider {
                mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile));
                mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile));
                mPowerCalculators.add(new ScreenPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new ScreenPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new AmbientDisplayPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new AmbientDisplayPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new SystemServicePowerCalculator(mPowerProfile));
                mPowerCalculators.add(new IdlePowerCalculator(mPowerProfile));
                mPowerCalculators.add(new IdlePowerCalculator(mPowerProfile));
                mPowerCalculators.add(new CustomMeasuredPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new CustomMeasuredPowerCalculator(mPowerProfile));

                mPowerCalculators.add(new UserPowerCalculator());
                mPowerCalculators.add(new UserPowerCalculator());

                // It is important that SystemServicePowerCalculator be applied last,
                // because it re-attributes some of the power estimated by the other
                // calculators.
                mPowerCalculators.add(new SystemServicePowerCalculator(mPowerProfile));
            }
            }
        }
        }
        return mPowerCalculators;
        return mPowerCalculators;
@@ -128,7 +131,8 @@ public class BatteryUsageStatsProvider {
        final long uptimeUs = SystemClock.uptimeMillis() * 1000;
        final long uptimeUs = SystemClock.uptimeMillis() * 1000;


        final List<PowerCalculator> powerCalculators = getPowerCalculators();
        final List<PowerCalculator> powerCalculators = getPowerCalculators();
        for (PowerCalculator powerCalculator : powerCalculators) {
        for (int i = 0, count = powerCalculators.size(); i < count; i++) {
            PowerCalculator powerCalculator = powerCalculators.get(i);
            powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs,
            powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs,
                    query);
                    query);
        }
        }
+81 −56
Original line number Original line Diff line number Diff line
@@ -20,12 +20,12 @@ import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.UidBatteryConsumer;
import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.os.UserHandle;
import android.util.Log;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseArray;


import java.util.Arrays;
import java.util.List;
import java.util.List;


/**
/**
@@ -36,87 +36,112 @@ public class SystemServicePowerCalculator extends PowerCalculator {
    private static final boolean DEBUG = false;
    private static final boolean DEBUG = false;
    private static final String TAG = "SystemServicePowerCalc";
    private static final String TAG = "SystemServicePowerCalc";


    private static final long MICROSEC_IN_HR = (long) 60 * 60 * 1000 * 1000;
    // Power estimators per CPU cluster, per CPU frequency. The array is flattened according

    // to this layout:
    private final PowerProfile mPowerProfile;

    // Tracks system server CPU [cluster][speed] power in milliAmp-microseconds
    // Data organized like this:
    // {cluster1-speed1, cluster1-speed2, ..., cluster2-speed1, cluster2-speed2, ...}
    // {cluster1-speed1, cluster1-speed2, ..., cluster2-speed1, cluster2-speed2, ...}
    private double[] mSystemServicePowerMaUs;
    private final UsageBasedPowerEstimator[] mPowerEstimators;


    public SystemServicePowerCalculator(PowerProfile powerProfile) {
    public SystemServicePowerCalculator(PowerProfile powerProfile) {
        mPowerProfile = powerProfile;
        int numFreqs = 0;
        final int numCpuClusters = powerProfile.getNumCpuClusters();
        for (int cluster = 0; cluster < numCpuClusters; cluster++) {
            numFreqs += powerProfile.getNumSpeedStepsInCpuCluster(cluster);
        }
        }


    @Override
        mPowerEstimators = new UsageBasedPowerEstimator[numFreqs];
    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
        int index = 0;
            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
        for (int cluster = 0; cluster < numCpuClusters; cluster++) {
        calculateSystemServicePower(batteryStats);
            final int numSpeeds = powerProfile.getNumSpeedStepsInCpuCluster(cluster);
        super.calculate(builder, batteryStats, rawRealtimeUs, rawUptimeUs, query);
            for (int speed = 0; speed < numSpeeds; speed++) {
                mPowerEstimators[index++] = new UsageBasedPowerEstimator(
                        powerProfile.getAveragePowerForCpuCore(cluster, speed));
            }
        }
    }
    }


    @Override
    @Override
    protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
        double systemServicePowerMah = calculateSystemServicePower(batteryStats);
        final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
                builder.getUidBatteryConsumerBuilders();
        final UidBatteryConsumer.Builder systemServerConsumer = uidBatteryConsumerBuilders.get(
                Process.SYSTEM_UID);

        if (systemServerConsumer != null) {
            systemServicePowerMah = Math.min(systemServicePowerMah,
                    systemServerConsumer.getTotalPower());

            // The system server power needs to be adjusted because part of it got
            // distributed to applications
            systemServerConsumer.setConsumedPower(
                    BatteryConsumer.POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS,
                    -systemServicePowerMah);
        }

        for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
            final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
            if (app != systemServerConsumer) {
                final BatteryStats.Uid uid = app.getBatteryStatsUid();
                app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES,
                app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES,
                calculateSystemServerCpuPowerMah(u));
                        systemServicePowerMah * uid.getProportionalSystemServiceUsage());
            }
        }
    }
    }


    @Override
    @Override
    public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
    public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
            long rawRealtimeUs, long rawUptimeUs, int statsType,
            long rawRealtimeUs, long rawUptimeUs, int statsType,
            SparseArray<UserHandle> asUsers) {
            SparseArray<UserHandle> asUsers) {
        calculateSystemServicePower(batteryStats);
        double systemServicePowerMah = calculateSystemServicePower(batteryStats);
        super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers);
        BatterySipper systemServerSipper = null;
        for (int i = sippers.size() - 1; i >= 0; i--) {
            final BatterySipper app = sippers.get(i);
            if (app.drainType == BatterySipper.DrainType.APP) {
                if (app.getUid() == Process.SYSTEM_UID) {
                    systemServerSipper = app;
                    break;
                }
                }

    @Override
    protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
            long rawUptimeUs, int statsType) {
        app.systemServiceCpuPowerMah = calculateSystemServerCpuPowerMah(u);
            }
            }

    private void calculateSystemServicePower(BatteryStats batteryStats) {
        final long[] systemServiceTimeAtCpuSpeeds = batteryStats.getSystemServiceTimeAtCpuSpeeds();
        if (systemServiceTimeAtCpuSpeeds == null) {
            return;
        }
        }


        if (mSystemServicePowerMaUs == null) {
        if (systemServerSipper != null) {
            mSystemServicePowerMaUs = new double[systemServiceTimeAtCpuSpeeds.length];
            systemServicePowerMah = Math.min(systemServicePowerMah, systemServerSipper.sumPower());

            // The system server power needs to be adjusted because part of it got
            // distributed to applications
            systemServerSipper.powerReattributedToOtherSippersMah = -systemServicePowerMah;
        }
        }
        int index = 0;

        final int numCpuClusters = mPowerProfile.getNumCpuClusters();
        for (int i = sippers.size() - 1; i >= 0; i--) {
        for (int cluster = 0; cluster < numCpuClusters; cluster++) {
            final BatterySipper app = sippers.get(i);
            final int numSpeeds = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
            if (app.drainType == BatterySipper.DrainType.APP) {
            for (int speed = 0; speed < numSpeeds; speed++) {
                if (app != systemServerSipper) {
                mSystemServicePowerMaUs[index] =
                    final BatteryStats.Uid uid = app.uidObj;
                        systemServiceTimeAtCpuSpeeds[index]
                    app.systemServiceCpuPowerMah =
                                * mPowerProfile.getAveragePowerForCpuCore(cluster, speed);
                            systemServicePowerMah * uid.getProportionalSystemServiceUsage();
                index++;
                }
                }
            }
            }

        if (DEBUG) {
            Log.d(TAG, "System service power per CPU cluster and frequency:"
                    + Arrays.toString(mSystemServicePowerMaUs));
        }
        }
    }
    }


    private double calculateSystemServerCpuPowerMah(BatteryStats.Uid u) {
    private double calculateSystemServicePower(BatteryStats batteryStats) {
        double cpuPowerMaUs = 0;
        final long[] systemServiceTimeAtCpuSpeeds = batteryStats.getSystemServiceTimeAtCpuSpeeds();
        final double proportionalUsage = u.getProportionalSystemServiceUsage();
        if (systemServiceTimeAtCpuSpeeds == null) {
        if (proportionalUsage > 0 && mSystemServicePowerMaUs != null) {
            return 0;
            for (int i = 0; i < mSystemServicePowerMaUs.length; i++) {
                cpuPowerMaUs += mSystemServicePowerMaUs[i] * proportionalUsage;
        }
        }

        // TODO(179210707): additionally account for CPU active and per cluster battery use

        double powerMah = 0;
        for (int i = 0; i < mPowerEstimators.length; i++) {
            powerMah += mPowerEstimators[i].calculatePower(systemServiceTimeAtCpuSpeeds[i]);
        }
        }
        return cpuPowerMaUs / MICROSEC_IN_HR;

        if (DEBUG) {
            Log.d(TAG, "System service power:" + powerMah);
        }
        }


    @Override
        return powerMah;
    public void reset() {
        mSystemServicePowerMaUs = null;
    }
    }
}
}
Loading