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

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

Convert CpuPowerCalculator from using BatterySipper to UidBatteryConsumer

Bug: 158137862
Test: Start Settings app, navigate to Apps, pick an app, navigate to Battery

Change-Id: I1ce3d1a0ece5419384c366e908523312651877ee
parent 2cefd2df
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -49,6 +49,28 @@ public abstract class BatteryConsumer {
    public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
    public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;

    /**
     * Time usage component, describing the particular part of the system
     * that was used for the corresponding amount of time.
     *
     * @hide
     */
    @IntDef(prefix = {"TIME_COMPONENT_"}, value = {
            TIME_COMPONENT_CPU,
            TIME_COMPONENT_CPU_FOREGROUND,
    })
    @Retention(RetentionPolicy.SOURCE)
    public static @interface TimeComponent {
    }

    public static final int TIME_COMPONENT_CPU = 0;
    public static final int TIME_COMPONENT_CPU_FOREGROUND = 1;

    public static final int TIME_COMPONENT_COUNT = 2;

    public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000;
    public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999;

    private final PowerComponents mPowerComponents;

    protected BatteryConsumer(@NonNull PowerComponents powerComponents) {
@@ -83,6 +105,29 @@ public abstract class BatteryConsumer {
        return mPowerComponents.getConsumedPowerForCustomComponent(componentId);
    }

    /**
     * Returns the amount of time since BatteryStats reset used by the specified component, e.g.
     * CPU, WiFi etc.
     *
     * @param componentId The ID of the time component, e.g.
     *                    {@link UidBatteryConsumer#TIME_COMPONENT_CPU}.
     * @return Amount of time in milliseconds.
     */
    public long getUsageDurationMillis(@TimeComponent int componentId) {
        return mPowerComponents.getUsageDurationMillis(componentId);
    }

    /**
     * Returns the amount of usage time attributed to the specified custom component
     * since BatteryStats reset.
     *
     * @param componentId The ID of the custom power component.
     * @return Amount of time in milliseconds.
     */
    public long getUsageDurationForCustomComponentMillis(int componentId) {
        return mPowerComponents.getUsageDurationForCustomComponentMillis(componentId);
    }

    protected void writeToParcel(Parcel dest, int flags) {
        mPowerComponents.writeToParcel(dest, flags);
    }
+15 −4
Original line number Diff line number Diff line
@@ -35,7 +35,11 @@ public final class BatteryUsageStats implements Parcelable {
    private BatteryUsageStats(@NonNull Builder builder) {
        mConsumedPower = builder.mConsumedPower;
        mDischargePercentage = builder.mDischargePercentage;
        mUidBatteryConsumers = builder.mUidBatteryConsumers;
        final int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
        mUidBatteryConsumers = new ArrayList<>(uidBatteryConsumerCount);
        for (int i = 0; i < uidBatteryConsumerCount; i++) {
            mUidBatteryConsumers.add(builder.mUidBatteryConsumerBuilders.get(i).build());
        }
    }

    /**
@@ -95,7 +99,8 @@ public final class BatteryUsageStats implements Parcelable {
    public static final class Builder {
        private double mConsumedPower;
        private int mDischargePercentage;
        private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers = new ArrayList<>();
        private final ArrayList<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders =
                new ArrayList<>();

        /**
         * Constructs a read-only object using the Builder values.
@@ -130,9 +135,15 @@ public final class BatteryUsageStats implements Parcelable {
         * individual UID.
         */
        @NonNull
        public Builder addUidBatteryConsumer(@NonNull UidBatteryConsumer uidBatteryConsumer) {
            mUidBatteryConsumers.add(uidBatteryConsumer);
        public Builder addUidBatteryConsumerBuilder(
                @NonNull UidBatteryConsumer.Builder uidBatteryConsumer) {
            mUidBatteryConsumerBuilders.add(uidBatteryConsumer);
            return this;
        }

        @NonNull
        public List<UidBatteryConsumer.Builder> getUidBatteryConsumerBuilders() {
            return mUidBatteryConsumerBuilders;
        }
    }
}
+96 −2
Original line number Diff line number Diff line
@@ -29,21 +29,25 @@ class PowerComponents {

    private final double mTotalPowerConsumed;
    private final double[] mPowerComponents;
    private final long[] mTimeComponents;

    PowerComponents(@NonNull Builder builder) {
        mTotalPowerConsumed = builder.mTotalPowerConsumed;
        mPowerComponents = builder.mPowerComponents;
        mTimeComponents = builder.mTimeComponents;
    }

    PowerComponents(@NonNull Parcel source) {
        mTotalPowerConsumed = source.readDouble();
        mPowerComponents = source.createDoubleArray();
        mTimeComponents = source.createLongArray();
    }

    /** Writes contents to Parcel */
    void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeDouble(mTotalPowerConsumed);
        dest.writeDoubleArray(mPowerComponents);
        dest.writeLongArray(mTimeComponents);
    }

    /**
@@ -93,16 +97,59 @@ class PowerComponents {
        }
    }

    /**
     * Returns the amount of time used by the specified component, e.g. CPU, WiFi etc.
     *
     * @param componentId The ID of the time component, e.g.
     *                    {@link UidBatteryConsumer#TIME_COMPONENT_CPU}.
     * @return Amount of time in milliseconds.
     */
    public long getUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId) {
        if (componentId >= UidBatteryConsumer.TIME_COMPONENT_COUNT) {
            throw new IllegalArgumentException(
                    "Unsupported time component ID: " + componentId);
        }
        try {
            return mTimeComponents[componentId];
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
        }
    }

    /**
     * Returns the amount of usage time attributed to the specified custom component.
     *
     * @param componentId The ID of the custom power component.
     * @return Amount of time in milliseconds.
     */
    public long getUsageDurationForCustomComponentMillis(int componentId) {
        if (componentId < UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID) {
            throw new IllegalArgumentException(
                    "Unsupported custom time component ID: " + componentId);
        }
        try {
            return mTimeComponents[
                    UidBatteryConsumer.TIME_COMPONENT_COUNT + componentId
                            - UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID];
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new IllegalArgumentException(
                    "Unsupported custom time component ID: " + componentId);
        }
    }

    /**
     * Builder for PowerComponents.
     */
    static final class Builder {
        private double mTotalPowerConsumed;
        private final double[] mPowerComponents;
        private final long[] mTimeComponents;

        Builder(int customPowerComponentCount) {
            mPowerComponents = new double[BatteryConsumer.POWER_COMPONENT_COUNT
        Builder(int customPowerComponentCount, int customTimeComponentCount) {
            mPowerComponents = new double[UidBatteryConsumer.POWER_COMPONENT_COUNT
                    + customPowerComponentCount];
            mTimeComponents = new long[UidBatteryConsumer.TIME_COMPONENT_COUNT
                    + customTimeComponentCount];
        }

        /**
@@ -159,6 +206,53 @@ class PowerComponents {
            return this;
        }

        /**
         * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc.
         *
         * @param componentId                  The ID of the time component, e.g.
         *                                     {@link UidBatteryConsumer#TIME_COMPONENT_CPU}.
         * @param componentUsageDurationMillis Amount of time in milliseconds.
         */
        @NonNull
        public Builder setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId,
                long componentUsageDurationMillis) {
            if (componentId >= UidBatteryConsumer.TIME_COMPONENT_COUNT) {
                throw new IllegalArgumentException(
                        "Unsupported time component ID: " + componentId);
            }
            try {
                mTimeComponents[componentId] = componentUsageDurationMillis;
            } catch (ArrayIndexOutOfBoundsException e) {
                throw new IllegalArgumentException(
                        "Unsupported time component ID: " + componentId);
            }
            return this;
        }

        /**
         * Sets the amount of time used by the specified custom component.
         *
         * @param componentId                  The ID of the custom power component.
         * @param componentUsageDurationMillis Amount of time in milliseconds.
         */
        @NonNull
        public Builder setUsageDurationForCustomComponentMillis(int componentId,
                long componentUsageDurationMillis) {
            if (componentId < UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID) {
                throw new IllegalArgumentException(
                        "Unsupported custom time component ID: " + componentId);
            }
            try {
                mTimeComponents[UidBatteryConsumer.TIME_COMPONENT_COUNT + componentId
                        - UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID] =
                        componentUsageDurationMillis;
            } catch (ArrayIndexOutOfBoundsException e) {
                throw new IllegalArgumentException(
                        "Unsupported custom time component ID: " + componentId);
            }
            return this;
        }

        /**
         * Creates a read-only object out of the Builder values.
         */
+45 −4
Original line number Diff line number Diff line
@@ -82,12 +82,24 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
     */
    public static final class Builder {
        private final PowerComponents.Builder mPowerComponentsBuilder;
        private final BatteryStats.Uid mBatteryStatsUid;
        private final int mUid;
        private String mPackageWithHighestDrain;

        public Builder(int customPowerComponentCount, int uid) {
            mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount);
            mUid = uid;
        public Builder(int customPowerComponentCount, int customTimeComponentCount,
                BatteryStats.Uid batteryStatsUid) {
            mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount,
                    customTimeComponentCount);
            mBatteryStatsUid = batteryStatsUid;
            mUid = batteryStatsUid.getUid();
        }

        public BatteryStats.Uid getBatteryStatsUid() {
            return mBatteryStatsUid;
        }

        public int getUid() {
            return mUid;
        }

        /**
@@ -132,6 +144,35 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
            return this;
        }

        /**
         * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc.
         *
         * @param componentId                  The ID of the time component, e.g.
         *                                     {@link UidBatteryConsumer#TIME_COMPONENT_CPU}.
         * @param componentUsageDurationMillis Amount of time in milliseconds.
         */
        @NonNull
        public Builder setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId,
                long componentUsageDurationMillis) {
            mPowerComponentsBuilder.setUsageDurationMillis(componentId,
                    componentUsageDurationMillis);
            return this;
        }

        /**
         * Sets the amount of time used by the specified custom component.
         *
         * @param componentId                  The ID of the custom power component.
         * @param componentUsageDurationMillis Amount of time in milliseconds.
         */
        @NonNull
        public Builder setUsageDurationForCustomComponentMillis(int componentId,
                long componentUsageDurationMillis) {
            mPowerComponentsBuilder.setUsageDurationForCustomComponentMillis(componentId,
                    componentUsageDurationMillis);
            return this;
        }

        /**
         * Sets the name of the package owned by this UID that consumed the highest amount
         * of power since BatteryStats reset.
+73 −9
Original line number Diff line number Diff line
@@ -17,13 +17,18 @@
package com.android.internal.os;

import android.content.Context;
import android.os.BatteryConsumer;
import android.hardware.SensorManager;
import android.net.ConnectivityManager;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.SparseArray;

import java.util.ArrayList;
import java.util.List;

/**
@@ -33,10 +38,53 @@ import java.util.List;
public class BatteryUsageStatsProvider {
    private final Context mContext;
    private final BatteryStatsImpl mStats;
    private final PowerProfile mPowerProfile;
    private final Object mLock = new Object();
    private List<PowerCalculator> mPowerCalculators;

    public BatteryUsageStatsProvider(Context context, BatteryStatsImpl stats) {
        mContext = context;
        mStats = stats;
        mPowerProfile = new PowerProfile(mContext);
    }

    private List<PowerCalculator> getPowerCalculators() {
        synchronized (mLock) {
            if (mPowerCalculators == null) {
                mPowerCalculators = new ArrayList<>();

                // Power calculators are applied in the order of registration
                mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile));
                if (!isWifiOnlyDevice(mContext)) {
                    mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile));
                }
                mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new SensorPowerCalculator(mPowerProfile,
                        mContext.getSystemService(SensorManager.class)));
                mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new MediaPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile));
                mPowerCalculators.add(new ScreenPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new AmbientDisplayPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new SystemServicePowerCalculator(mPowerProfile));
                mPowerCalculators.add(new IdlePowerCalculator(mPowerProfile));

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

    private static boolean isWifiOnlyDevice(Context context) {
        ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
        if (cm == null) {
            return false;
        }
        return !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
    }

    /**
@@ -49,11 +97,19 @@ public class BatteryUsageStatsProvider {
                false /* collectBatteryBroadcast */);
        batteryStatsHelper.create((Bundle) null);
        final UserManager userManager = mContext.getSystemService(UserManager.class);
        batteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
                userManager.getUserProfiles());
        final List<UserHandle> asUsers = userManager.getUserProfiles();
        final int n = asUsers.size();
        SparseArray<UserHandle> users = new SparseArray<>(n);
        for (int i = 0; i < n; ++i) {
            UserHandle userHandle = asUsers.get(i);
            users.put(userHandle.getIdentifier(), userHandle);
        }

        batteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, users);

        // TODO(b/174186358): read extra power component number from configuration
        final int customPowerComponentCount = 0;
        final int customTimeComponentCount = 0;
        final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder()
                .setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0))
                .setConsumedPower(batteryStatsHelper.getTotalPower());
@@ -62,15 +118,23 @@ public class BatteryUsageStatsProvider {
        for (int i = 0; i < usageList.size(); i++) {
            final BatterySipper sipper = usageList.get(i);
            if (sipper.drainType == BatterySipper.DrainType.APP) {
                batteryUsageStatsBuilder.addUidBatteryConsumer(
                        new UidBatteryConsumer.Builder(customPowerComponentCount, sipper.getUid())
                batteryUsageStatsBuilder.addUidBatteryConsumerBuilder(
                        new UidBatteryConsumer.Builder(customPowerComponentCount,
                                customTimeComponentCount, sipper.uidObj)
                                .setPackageWithHighestDrain(sipper.packageWithHighestDrain)
                                .setConsumedPower(sipper.sumPower())
                                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU,
                                        sipper.cpuPowerMah)
                                .build());
                                .setConsumedPower(sipper.sumPower()));
            }
        }

        final long realtimeUs = SystemClock.elapsedRealtime() * 1000;
        final long uptimeUs = SystemClock.uptimeMillis() * 1000;

        final List<PowerCalculator> powerCalculators = getPowerCalculators();
        for (PowerCalculator powerCalculator : powerCalculators) {
            powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs,
                    BatteryStats.STATS_SINCE_CHARGED, users);
        }

        return batteryUsageStatsBuilder.build();
    }
}
Loading