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

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

Convert BatteryStats.dumpLocked from BatteryStatsHelper to BatteryUsageStats

Bug: 162380414
Test: atest FrameworksCoreTests:BatteryUsageStatsTest

Change-Id: Icb508c60e037ee983c0ebde5905ec0a08fe648c3
parent 1ebf0cf0
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package android.os;

import android.annotation.NonNull;

import java.io.PrintWriter;

/**
 * Contains power consumption data across the entire device.
 *
@@ -37,6 +39,11 @@ public final class AggregateBatteryConsumer extends BatteryConsumer implements P
        mConsumedPowerMah = source.readDouble();
    }

    @Override
    public void dump(PrintWriter pw, boolean skipEmptyComponents) {
        mPowerComponents.dump(pw, skipEmptyComponents);
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
+69 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.os;
import android.annotation.IntDef;
import android.annotation.NonNull;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@@ -27,7 +28,7 @@ import java.lang.annotation.RetentionPolicy;
 *
 * @hide
 */
public class BatteryConsumer {
public abstract class BatteryConsumer {

    /**
     * Power usage component, describing the particular part of the system
@@ -85,12 +86,37 @@ public class BatteryConsumer {
    public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
    public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;

    private static final String[] sPowerComponentNames = new String[POWER_COMPONENT_COUNT];

    static {
        // Assign individually to avoid future mismatch
        sPowerComponentNames[POWER_COMPONENT_SCREEN] = "screen";
        sPowerComponentNames[POWER_COMPONENT_CPU] = "cpu";
        sPowerComponentNames[POWER_COMPONENT_BLUETOOTH] = "bluetooth";
        sPowerComponentNames[POWER_COMPONENT_CAMERA] = "camera";
        sPowerComponentNames[POWER_COMPONENT_AUDIO] = "audio";
        sPowerComponentNames[POWER_COMPONENT_VIDEO] = "video";
        sPowerComponentNames[POWER_COMPONENT_FLASHLIGHT] = "flashlight";
        sPowerComponentNames[POWER_COMPONENT_SYSTEM_SERVICES] = "system_services";
        sPowerComponentNames[POWER_COMPONENT_MOBILE_RADIO] = "mobile_radio";
        sPowerComponentNames[POWER_COMPONENT_SENSORS] = "sensors";
        sPowerComponentNames[POWER_COMPONENT_GNSS] = "gnss";
        sPowerComponentNames[POWER_COMPONENT_WIFI] = "wifi";
        sPowerComponentNames[POWER_COMPONENT_WAKELOCK] = "wakelock";
        sPowerComponentNames[POWER_COMPONENT_MEMORY] = "memory";
        sPowerComponentNames[POWER_COMPONENT_PHONE] = "phone";
        sPowerComponentNames[POWER_COMPONENT_AMBIENT_DISPLAY] = "ambient_display";
        sPowerComponentNames[POWER_COMPONENT_IDLE] = "idle";
        sPowerComponentNames[POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS] = "reattributed";
    }

    /**
     * Identifiers of models used for power estimation.
     *
     * @hide
     */
    @IntDef(prefix = {"POWER_MODEL_"}, value = {
            POWER_MODEL_UNDEFINED,
            POWER_MODEL_POWER_PROFILE,
            POWER_MODEL_MEASURED_ENERGY,
    })
@@ -98,16 +124,21 @@ public class BatteryConsumer {
    public @interface PowerModel {
    }

    /**
     * Unspecified power model.
     */
    public static final int POWER_MODEL_UNDEFINED = 0;

    /**
     * Power model that is based on average consumption rates that hardware components
     * consume in various states.
     */
    public static final int POWER_MODEL_POWER_PROFILE = 0;
    public static final int POWER_MODEL_POWER_PROFILE = 1;

    /**
     * Power model that is based on energy consumption measured by on-device power monitors.
     */
    public static final int POWER_MODEL_MEASURED_ENERGY = 1;
    public static final int POWER_MODEL_MEASURED_ENERGY = 2;

    protected final PowerComponents mPowerComponents;

@@ -197,6 +228,41 @@ public class BatteryConsumer {
        mPowerComponents.writeToParcel(dest, flags);
    }

    /**
     * Returns the name of the specified component.  Intended for logging and debugging.
     */
    public static String powerComponentIdToString(@BatteryConsumer.PowerComponent int componentId) {
        return sPowerComponentNames[componentId];
    }

    /**
     * Returns the name of the specified power model.  Intended for logging and debugging.
     */
    public static String powerModelToString(@BatteryConsumer.PowerModel int powerModel) {
        switch (powerModel) {
            case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
                return "measured energy";
            case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
                return "power profile";
            default:
                return "";
        }
    }

    /**
     * Prints the stats in a human-readable format.
     */
    public void dump(PrintWriter pw) {
        dump(pw, true);
    }

    /**
     * Prints the stats in a human-readable format.
     *
     * @param skipEmptyComponents if true, omit any power components with a zero amount.
     */
    public abstract void dump(PrintWriter pw, boolean skipEmptyComponents);

    protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
        final PowerComponents.Builder mPowerComponentsBuilder;

+10 −144
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BatteryUsageStatsProvider;

import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -5299,154 +5300,19 @@ public abstract class BatteryStats implements Parcelable {
        pw.println(getDischargeAmountScreenDozeSinceCharge());
        pw.println();

        final BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, this);
        final BatteryUsageStats stats = provider.getBatteryUsageStats(
                new BatteryUsageStatsQuery.Builder()
                        .setMaxStatsAgeMs(0)
                        .includePowerModels()
                        .build());
        stats.dump(pw, prefix);

        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
        helper.create(this);
        helper.refreshStats(which, UserHandle.USER_ALL);
        List<BatterySipper> sippers = helper.getUsageList();
        if (sippers != null && sippers.size() > 0) {
            pw.print(prefix); pw.println("  Estimated power use (mAh):");
            pw.print(prefix); pw.print("    Capacity: ");
                    printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
                    pw.print(", Computed drain: "); printmAh(pw, helper.getComputedPower());
                    pw.print(", actual drain: "); printmAh(pw, helper.getMinDrainedPower());
                    if (helper.getMinDrainedPower() != helper.getMaxDrainedPower()) {
                        pw.print("-"); printmAh(pw, helper.getMaxDrainedPower());
                    }
                    pw.println();
            for (int i=0; i<sippers.size(); i++) {
                final BatterySipper bs = sippers.get(i);
                pw.print(prefix);
                switch (bs.drainType) {
                    case AMBIENT_DISPLAY:
                        pw.print("    Ambient display: ");
                        break;
                    case IDLE:
                        pw.print("    Idle: ");
                        break;
                    case CELL:
                        pw.print("    Cell standby: ");
                        break;
                    case PHONE:
                        pw.print("    Phone calls: ");
                        break;
                    case WIFI:
                        pw.print("    Wifi: ");
                        break;
                    case BLUETOOTH:
                        pw.print("    Bluetooth: ");
                        break;
                    case SCREEN:
                        pw.print("    Screen: ");
                        break;
                    case FLASHLIGHT:
                        pw.print("    Flashlight: ");
                        break;
                    case APP:
                        pw.print("    Uid ");
                        UserHandle.formatUid(pw, bs.uidObj.getUid());
                        pw.print(": ");
                        break;
                    case USER:
                        pw.print("    User "); pw.print(bs.userId);
                        pw.print(": ");
                        break;
                    case UNACCOUNTED:
                        pw.print("    Unaccounted: ");
                        break;
                    case OVERCOUNTED:
                        pw.print("    Over-counted: ");
                        break;
                    case CAMERA:
                        pw.print("    Camera: ");
                        break;
                    default:
                        pw.print("    ???: ");
                        break;
                }
                printmAh(pw, bs.totalPowerMah);

                if (bs.usagePowerMah != bs.totalPowerMah) {
                    // If the usage (generic power) isn't the whole amount, we list out
                    // what components are involved in the calculation.

                    pw.print(" (");
                    if (bs.usagePowerMah != 0) {
                        pw.print(" usage=");
                        printmAh(pw, bs.usagePowerMah);
                    }
                    if (bs.cpuPowerMah != 0) {
                        pw.print(" cpu=");
                        printmAh(pw, bs.cpuPowerMah);
                    }
                    if (bs.wakeLockPowerMah != 0) {
                        pw.print(" wake=");
                        printmAh(pw, bs.wakeLockPowerMah);
                    }
                    if (bs.mobileRadioPowerMah != 0) {
                        pw.print(" radio=");
                        printmAh(pw, bs.mobileRadioPowerMah);
                    }
                    if (bs.wifiPowerMah != 0) {
                        pw.print(" wifi=");
                        printmAh(pw, bs.wifiPowerMah);
                    }
                    if (bs.bluetoothPowerMah != 0) {
                        pw.print(" bt=");
                        printmAh(pw, bs.bluetoothPowerMah);
                    }
                    if (bs.gpsPowerMah != 0) {
                        pw.print(" gps=");
                        printmAh(pw, bs.gpsPowerMah);
                    }
                    if (bs.sensorPowerMah != 0) {
                        pw.print(" sensor=");
                        printmAh(pw, bs.sensorPowerMah);
                    }
                    if (bs.cameraPowerMah != 0) {
                        pw.print(" camera=");
                        printmAh(pw, bs.cameraPowerMah);
                    }
                    if (bs.flashlightPowerMah != 0) {
                        pw.print(" flash=");
                        printmAh(pw, bs.flashlightPowerMah);
                    }
                    if (bs.customMeasuredPowerMah != null) {
                        for (int idx = 0; idx < bs.customMeasuredPowerMah.length; idx++) {
                            final double customPowerMah = bs.customMeasuredPowerMah[idx];
                            if (customPowerMah != 0) {
                                pw.print(" custom[" + idx + "]=");
                                printmAh(pw, customPowerMah);
                            }
                        }
                    }
                    pw.print(" )");
                }

                // If there is additional smearing information, include it.
                if (bs.totalSmearedPowerMah != bs.totalPowerMah) {
                    pw.print(" Including smearing: ");
                    printmAh(pw, bs.totalSmearedPowerMah);
                    pw.print(" (");
                    if (bs.screenPowerMah != 0) {
                        pw.print(" screen=");
                        printmAh(pw, bs.screenPowerMah);
                    }
                    if (bs.proportionalSmearMah != 0) {
                        pw.print(" proportional=");
                        printmAh(pw, bs.proportionalSmearMah);
                    }
                    pw.print(" )");
                }
                if (bs.shouldHide) {
                    pw.print(" Excluded from smearing");
                }

                pw.println();
            }
            pw.println();
        }

        sippers = helper.getMobilemsppList();
        final List<BatterySipper> sippers = helper.getMobilemsppList();
        if (sippers != null && sippers.size() > 0) {
            pw.print(prefix); pw.println("  Per-app mobile ms per packet:");
            long totalTime = 0;
+121 −0
Original line number Diff line number Diff line
@@ -23,10 +23,13 @@ import android.util.SparseArray;

import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.internal.os.PowerCalculator;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
@@ -73,6 +76,7 @@ public final class BatteryUsageStats implements Parcelable {

    private final int mDischargePercentage;
    private final long mStatsStartTimestampMs;
    private final double mBatteryCapacityMah;
    private final double mDischargedPowerLowerBound;
    private final double mDischargedPowerUpperBound;
    private final long mBatteryTimeRemainingMs;
@@ -86,6 +90,7 @@ public final class BatteryUsageStats implements Parcelable {

    private BatteryUsageStats(@NonNull Builder builder) {
        mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
        mBatteryCapacityMah = builder.mBatteryCapacityMah;
        mDischargePercentage = builder.mDischargePercentage;
        mDischargedPowerLowerBound = builder.mDischargedPowerLowerBoundMah;
        mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah;
@@ -144,6 +149,13 @@ public final class BatteryUsageStats implements Parcelable {
                .getConsumedPower();
    }

    /**
     * Returns battery capacity in milli-amp-hours.
     */
    public double getBatteryCapacity() {
        return mBatteryCapacityMah;
    }

    /**
     * Portion of battery charge drained since BatteryStats reset (e.g. due to being fully
     * charged), as percentage of the full charge in the range [0:100]
@@ -217,6 +229,7 @@ public final class BatteryUsageStats implements Parcelable {

    private BatteryUsageStats(@NonNull Parcel source) {
        mStatsStartTimestampMs = source.readLong();
        mBatteryCapacityMah = source.readDouble();
        mDischargePercentage = source.readInt();
        mDischargedPowerLowerBound = source.readDouble();
        mDischargedPowerUpperBound = source.readDouble();
@@ -274,6 +287,7 @@ public final class BatteryUsageStats implements Parcelable {
    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeLong(mStatsStartTimestampMs);
        dest.writeDouble(mBatteryCapacityMah);
        dest.writeInt(mDischargePercentage);
        dest.writeDouble(mDischargedPowerLowerBound);
        dest.writeDouble(mDischargedPowerUpperBound);
@@ -321,6 +335,104 @@ public final class BatteryUsageStats implements Parcelable {
        }
    };

    /**
     * Prints the stats in a human-readable format.
     */
    public void dump(PrintWriter pw, String prefix) {
        pw.print(prefix);
        pw.println("  Estimated power use (mAh):");
        pw.print(prefix);
        pw.print("    Capacity: ");
        PowerCalculator.printPowerMah(pw, getBatteryCapacity());
        pw.print(", Computed drain: ");
        PowerCalculator.printPowerMah(pw, getConsumedPower());
        final Range<Double> dischargedPowerRange = getDischargedPowerRange();
        pw.print(", actual drain: ");
        PowerCalculator.printPowerMah(pw, dischargedPowerRange.getLower());
        if (!dischargedPowerRange.getLower().equals(dischargedPowerRange.getUpper())) {
            pw.print("-");
            PowerCalculator.printPowerMah(pw, dischargedPowerRange.getUpper());
        }
        pw.println();

        pw.println("    Global");
        final BatteryConsumer deviceConsumer = getAggregateBatteryConsumer(
                AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE);
        final BatteryConsumer appsConsumer = getAggregateBatteryConsumer(
                AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS);

        for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
                componentId++) {
            final double devicePowerMah = deviceConsumer.getConsumedPower(componentId);
            final double appsPowerMah = appsConsumer.getConsumedPower(componentId);
            if (devicePowerMah == 0 && appsPowerMah == 0) {
                continue;
            }

            final String componentName = BatteryConsumer.powerComponentIdToString(componentId);
            printPowerComponent(pw, prefix, componentName, devicePowerMah, appsPowerMah,
                    deviceConsumer.getPowerModel(componentId),
                    deviceConsumer.getUsageDurationMillis(componentId));
        }

        for (int componentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
                componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
                        + mCustomPowerComponentNames.length;
                componentId++) {
            final double devicePowerMah =
                    deviceConsumer.getConsumedPowerForCustomComponent(componentId);
            final double appsPowerMah =
                    appsConsumer.getConsumedPowerForCustomComponent(componentId);
            if (devicePowerMah == 0 && appsPowerMah == 0) {
                continue;
            }

            printPowerComponent(pw, prefix, deviceConsumer.getCustomPowerComponentName(componentId),
                    devicePowerMah, appsPowerMah,
                    BatteryConsumer.POWER_MODEL_UNDEFINED,
                    deviceConsumer.getUsageDurationForCustomComponentMillis(componentId));
        }

        dumpSortedBatteryConsumers(pw, prefix, getUidBatteryConsumers());
        dumpSortedBatteryConsumers(pw, prefix, getUserBatteryConsumers());
    }

    private void printPowerComponent(PrintWriter pw, String prefix, String componentName,
            double devicePowerMah, double appsPowerMah, int powerModel, long durationMs) {
        StringBuilder sb = new StringBuilder();
        sb.append(prefix).append("      ").append(componentName).append(": ")
                .append(PowerCalculator.formatCharge(devicePowerMah));
        if (powerModel != BatteryConsumer.POWER_MODEL_UNDEFINED
                && powerModel != BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
            sb.append(" [");
            sb.append(BatteryConsumer.powerModelToString(powerModel));
            sb.append("]");
        }
        sb.append(" apps: ").append(PowerCalculator.formatCharge(appsPowerMah));
        if (durationMs != 0) {
            sb.append(" duration: ");
            BatteryStats.formatTimeMs(sb, durationMs);
        }

        pw.println(sb.toString());
    }

    private void dumpSortedBatteryConsumers(PrintWriter pw, String prefix,
            List<? extends BatteryConsumer> batteryConsumers) {
        batteryConsumers.sort(
                Comparator.<BatteryConsumer>comparingDouble(BatteryConsumer::getConsumedPower)
                        .reversed());
        for (BatteryConsumer consumer : batteryConsumers) {
            if (consumer.getConsumedPower() == 0) {
                continue;
            }
            pw.print(prefix);
            pw.print("    ");
            consumer.dump(pw);
            pw.println();
        }
    }

    /**
     * Builder for BatteryUsageStats.
     */
@@ -329,6 +441,7 @@ public final class BatteryUsageStats implements Parcelable {
        private final String[] mCustomPowerComponentNames;
        private final boolean mIncludePowerModels;
        private long mStatsStartTimestampMs;
        private double mBatteryCapacityMah;
        private int mDischargePercentage;
        private double mDischargedPowerLowerBoundMah;
        private double mDischargedPowerUpperBoundMah;
@@ -364,6 +477,14 @@ public final class BatteryUsageStats implements Parcelable {
            return new BatteryUsageStats(this);
        }

        /**
         * Sets the battery capacity in milli-amp-hours.
         */
        public Builder setBatteryCapacity(double batteryCapacityMah) {
            mBatteryCapacityMah = batteryCapacityMah;
            return this;
        }

        /**
         * Sets the timestamp of the latest battery stats reset, in milliseconds.
         */
+35 −0
Original line number Diff line number Diff line
@@ -17,6 +17,10 @@ package android.os;

import android.annotation.NonNull;

import com.android.internal.os.PowerCalculator;

import java.io.PrintWriter;

/**
 * Contains details of battery attribution data broken down to individual power drain types
 * such as CPU, RAM, GPU etc.
@@ -202,6 +206,37 @@ class PowerComponents {
        return max;
    }

    public void dump(PrintWriter pw, boolean skipEmptyComponents) {
        String separator = "";
        for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
                componentId++) {
            final double componentPower = getConsumedPower(componentId);
            if (skipEmptyComponents && componentPower == 0) {
                continue;
            }
            pw.print(separator); separator = " ";
            pw.print(BatteryConsumer.powerComponentIdToString(componentId));
            pw.print("=");
            PowerCalculator.printPowerMah(pw, componentPower);
        }

        final int customComponentCount = getCustomPowerComponentCount();
        for (int customComponentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
                customComponentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
                        + customComponentCount;
                customComponentId++) {
            final double customComponentPower =
                    getConsumedPowerForCustomComponent(customComponentId);
            if (skipEmptyComponents && customComponentPower == 0) {
                continue;
            }
            pw.print(separator); separator = " ";
            pw.print(getCustomPowerComponentName(customComponentId));
            pw.print("=");
            PowerCalculator.printPowerMah(pw, customComponentPower);
        }
    }

    /**
     * Builder for PowerComponents.
     */
Loading