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

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

Merge "Convert CpuPowerCalculator from using BatterySipper to UidBatteryConsumer"

parents b241fd12 e786140e
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