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

Commit 33dac559 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

BatteryStats: Record energy info stats from WiFi and Bluetooth controllers

Surface some of this information in BatteryStatsHelper. If we are given a
total energy from the WiFi controller, we normalize the computed
energy of each app and blame them for a fraction of the real energy.

Change-Id: I64051b600f5d9f6ac4580d56ef0977971eb4be2d
parent 488caeb7
Loading
Loading
Loading
Loading
+74 −4
Original line number Diff line number Diff line
@@ -441,14 +441,14 @@ public abstract class BatteryStats implements Parcelable {
            public abstract boolean isActive();

            /**
             * Returns the total time (in 1/100 sec) spent executing in user code.
             * Returns the total time (in milliseconds) spent executing in user code.
             *
             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
             */
            public abstract long getUserTime(int which);

            /**
             * Returns the total time (in 1/100 sec) spent executing in system code.
             * Returns the total time (in milliseconds) spent executing in system code.
             *
             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
             */
@@ -476,14 +476,14 @@ public abstract class BatteryStats implements Parcelable {
            public abstract int getNumAnrs(int which);

            /**
             * Returns the cpu time spent in microseconds while the process was in the foreground.
             * Returns the cpu time (milliseconds) spent while the process was in the foreground.
             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
             * @return foreground cpu time in microseconds
             */
            public abstract long getForegroundTime(int which);

            /**
             * Returns the approximate cpu time spent in microseconds, at a certain CPU speed.
             * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed.
             * @param speedStep the index of the CPU speed. This is not the actual speed of the
             * CPU.
             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
@@ -1858,6 +1858,15 @@ public abstract class BatteryStats implements Parcelable {
    public abstract long getNetworkActivityBytes(int type, int which);
    public abstract long getNetworkActivityPackets(int type, int which);

    public static final int CONTROLLER_IDLE_TIME = 0;
    public static final int CONTROLLER_RX_TIME = 1;
    public static final int CONTROLLER_TX_TIME = 2;
    public static final int CONTROLLER_ENERGY = 3;
    public static final int NUM_CONTROLLER_ACTIVITY_TYPES = CONTROLLER_ENERGY + 1;

    public abstract long getBluetoothControllerActivity(int type, int which);
    public abstract long getWifiControllerActivity(int type, int which);

    /**
     * Return the wall clock time when battery stats data collection started.
     */
@@ -3142,6 +3151,35 @@ public abstract class BatteryStats implements Parcelable {
        if (!didOne) sb.append(" (no activity)");
        pw.println(sb.toString());

        final long wifiIdleTimeMs = getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
        final long wifiRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
        final long wifiTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
        final long wifiTotalTimeMs = wifiIdleTimeMs + wifiRxTimeMs + wifiTxTimeMs;

        sb.setLength(0);
        sb.append(prefix);
        sb.append("  WiFi Idle time: "); formatTimeMs(sb, wifiIdleTimeMs);
        sb.append(" (");
        sb.append(formatRatioLocked(wifiIdleTimeMs, wifiTotalTimeMs));
        sb.append(")");
        pw.println(sb.toString());

        sb.setLength(0);
        sb.append(prefix);
        sb.append("  WiFi Rx time:   "); formatTimeMs(sb, wifiRxTimeMs);
        sb.append(" (");
        sb.append(formatRatioLocked(wifiRxTimeMs, wifiTotalTimeMs));
        sb.append(")");
        pw.println(sb.toString());

        sb.setLength(0);
        sb.append(prefix);
        sb.append("  WiFi Tx time:   "); formatTimeMs(sb, wifiTxTimeMs);
        sb.append(" (");
        sb.append(formatRatioLocked(wifiTxTimeMs, wifiTotalTimeMs));
        sb.append(")");
        pw.println(sb.toString());

        sb.setLength(0);
        sb.append(prefix);
                sb.append("  Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
@@ -3169,9 +3207,41 @@ public abstract class BatteryStats implements Parcelable {
            sb.append(getPhoneDataConnectionCount(i, which));
            sb.append("x");
        }

        if (!didOne) sb.append(" (no activity)");
        pw.println(sb.toString());

        final long bluetoothIdleTimeMs =
                getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
        final long bluetoothRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
        final long bluetoothTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
        final long bluetoothTotalTimeMs = bluetoothIdleTimeMs + bluetoothRxTimeMs +
                bluetoothTxTimeMs;

        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Bluetooth Idle time: "); formatTimeMs(sb, bluetoothIdleTimeMs);
        sb.append(" (");
        sb.append(formatRatioLocked(bluetoothIdleTimeMs, bluetoothTotalTimeMs));
        sb.append(")");
        pw.println(sb.toString());

        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Bluetooth Rx time:   "); formatTimeMs(sb, bluetoothRxTimeMs);
        sb.append(" (");
        sb.append(formatRatioLocked(bluetoothRxTimeMs, bluetoothTotalTimeMs));
        sb.append(")");
        pw.println(sb.toString());

        sb.setLength(0);
        sb.append(prefix);
        sb.append("  Bluetooth Tx time:   "); formatTimeMs(sb, bluetoothTxTimeMs);
        sb.append(" (");
        sb.append(formatRatioLocked(bluetoothTxTimeMs, bluetoothTotalTimeMs));
        sb.append(")");
        pw.println(sb.toString());

        pw.println();

        if (which == STATS_SINCE_UNPLUGGED) {
+38 −0
Original line number Diff line number Diff line
@@ -26,12 +26,15 @@ public class BatterySipper implements Comparable<BatterySipper> {
    public double value;
    public double[] values;
    public DrainType drainType;

    // Measured in milliseconds.
    public long usageTime;
    public long cpuTime;
    public long gpsTime;
    public long wifiRunningTime;
    public long cpuFgTime;
    public long wakeLockTime;

    public long mobileRxPackets;
    public long mobileTxPackets;
    public long mobileActive;
@@ -48,6 +51,14 @@ public class BatterySipper implements Comparable<BatterySipper> {
    public String[] mPackages;
    public String packageWithHighestDrain;

    // Measured in mAh (milli-ampere per hour).
    public double wifiPower;
    public double cpuPower;
    public double wakeLockPower;
    public double mobileRadioPower;
    public double gpsPower;
    public double sensorPower;

    public enum DrainType {
        IDLE,
        CELL,
@@ -107,4 +118,31 @@ public class BatterySipper implements Comparable<BatterySipper> {
        }
        return uidObj.getUid();
    }

    /**
     * Add stats from other to this BatterySipper.
     */
    public void add(BatterySipper other) {
        cpuTime += other.cpuTime;
        gpsTime += other.gpsTime;
        wifiRunningTime += other.wifiRunningTime;
        cpuFgTime += other.cpuFgTime;
        wakeLockTime += other.wakeLockTime;
        mobileRxPackets += other.mobileRxPackets;
        mobileTxPackets += other.mobileTxPackets;
        mobileActive += other.mobileActive;
        mobileActiveCount += other.mobileActiveCount;
        wifiRxPackets += other.wifiRxPackets;
        wifiTxPackets += other.wifiTxPackets;
        mobileRxBytes += other.mobileRxBytes;
        mobileTxBytes += other.mobileTxBytes;
        wifiRxBytes += other.wifiRxBytes;
        wifiTxBytes += other.wifiTxBytes;
        wifiPower += other.wifiPower;
        gpsPower += other.gpsPower;
        cpuPower += other.cpuPower;
        sensorPower += other.sensorPower;
        mobileRadioPower += other.mobileRadioPower;
        wakeLockPower += other.wakeLockPower;
    }
}
+320 −218

File changed.

Preview size limit exceeded, changes collapsed.

+126 −0
Original line number Diff line number Diff line
@@ -20,11 +20,15 @@ import static android.net.NetworkStats.UID_ALL;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;

import android.app.ActivityManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkStats;
import android.net.wifi.IWifiManager;
import android.net.wifi.WifiActivityEnergyInfo;
import android.net.wifi.WifiManager;
import android.os.BadParcelableException;
import android.os.BatteryManager;
@@ -38,6 +42,8 @@ import android.os.Parcel;
import android.os.ParcelFormatException;
import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.WorkSource;
@@ -332,6 +338,12 @@ public final class BatteryStatsImpl extends BatteryStats {
    final LongSamplingCounter[] mNetworkPacketActivityCounters =
            new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];

    final LongSamplingCounter[] mBluetoothActivityCounters =
            new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];

    final LongSamplingCounter[] mWifiActivityCounters =
            new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];

    boolean mWifiOn;
    StopwatchTimer mWifiOnTimer;

@@ -4307,6 +4319,20 @@ public final class BatteryStatsImpl extends BatteryStats {
        return mBluetoothStateTimer[bluetoothState].getCountLocked(which);
    }

    @Override public long getBluetoothControllerActivity(int type, int which) {
        if (type >= 0 && type < mBluetoothActivityCounters.length) {
            return mBluetoothActivityCounters[type].getCountLocked(which);
        }
        return 0;
    }

    @Override public long getWifiControllerActivity(int type, int which) {
        if (type >= 0 && type < mWifiActivityCounters.length) {
            return mWifiActivityCounters[type].getCountLocked(which);
        }
        return 0;
    }

    @Override public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
        return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
    }
@@ -6652,6 +6678,10 @@ public final class BatteryStatsImpl extends BatteryStats {
            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
        }
        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
            mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
            mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
        }
        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase);
        mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase);
        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
@@ -7239,6 +7269,10 @@ public final class BatteryStatsImpl extends BatteryStats {
        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
            mBluetoothStateTimer[i].reset(false);
        }
        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
            mBluetoothActivityCounters[i].reset(false);
            mWifiActivityCounters[i].reset(false);
        }
        mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;

        for (int i=0; i<mUidStats.size(); i++) {
@@ -7325,6 +7359,9 @@ public final class BatteryStatsImpl extends BatteryStats {
    public void pullPendingStateUpdatesLocked() {
        updateKernelWakelocksLocked();
        updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
        // TODO(adamlesinski): enable when bluedroid stops deadlocking. b/19248786
        // updateBluetoothControllerActivityLocked();
        updateWifiControllerActivityLocked();
        if (mOnBatteryInternal) {
            final boolean screenOn = mScreenState == Display.STATE_ON;
            updateDischargeScreenLevelsLocked(screenOn, screenOn);
@@ -7761,6 +7798,65 @@ public final class BatteryStatsImpl extends BatteryStats {
        }
    }

    private void updateBluetoothControllerActivityLocked() {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter == null) {
            return;
        }

        // We read the data even if we are not on battery. Each read clears
        // the previous data, so we must always read to make sure the
        // data is for the current interval.
        BluetoothActivityEnergyInfo info = adapter.getControllerActivityEnergyInfo(
                BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED);
        if (info == null || !info.isValid() || !mOnBatteryInternal) {
            // Bad info or we are not on battery.
            return;
        }

        mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
                info.getControllerRxTimeMillis());
        mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
                info.getControllerTxTimeMillis());
        mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
                info.getControllerIdleTimeMillis());
        mBluetoothActivityCounters[CONTROLLER_ENERGY].addCountLocked(
                info.getControllerEnergyUsed());
    }

    private void updateWifiControllerActivityLocked() {
        IWifiManager wifiManager = IWifiManager.Stub.asInterface(
                ServiceManager.getService(Context.WIFI_SERVICE));
        if (wifiManager == null) {
            return;
        }

        WifiActivityEnergyInfo info;
        try {
            // We read the data even if we are not on battery. Each read clears
            // the previous data, so we must always read to make sure the
            // data is for the current interval.
            info = wifiManager.reportActivityInfo();
        } catch (RemoteException e) {
            // Nothing to report, WiFi is dead.
            return;
        }

        if (info == null || !info.isValid() || !mOnBatteryInternal) {
            // Bad info or we are not on battery.
            return;
        }

        mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
                info.getControllerRxTimeMillis());
        mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
                info.getControllerTxTimeMillis());
        mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
                info.getControllerIdleTimeMillis());
        mWifiActivityCounters[CONTROLLER_ENERGY].addCountLocked(
                info.getControllerEnergyUsed());
    }

    public long getAwakeTimeBattery() {
        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
    }
@@ -8475,6 +8571,15 @@ public final class BatteryStatsImpl extends BatteryStats {
        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
            mBluetoothStateTimer[i].readSummaryFromParcelLocked(in);
        }

        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
            mBluetoothActivityCounters[i].readSummaryFromParcelLocked(in);
        }

        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
            mWifiActivityCounters[i].readSummaryFromParcelLocked(in);
        }

        mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
        mFlashlightOn = false;
        mFlashlightOnTimer.readSummaryFromParcelLocked(in);
@@ -8763,6 +8868,12 @@ public final class BatteryStatsImpl extends BatteryStats {
        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
            mBluetoothStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
        }
        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
            mBluetoothActivityCounters[i].writeSummaryFromParcelLocked(out);
        }
        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
            mWifiActivityCounters[i].writeSummaryFromParcelLocked(out);
        }
        out.writeInt(mNumConnectivityChange);
        mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);

@@ -9067,6 +9178,15 @@ public final class BatteryStatsImpl extends BatteryStats {
            mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i,
                    null, mOnBatteryTimeBase, in);
        }

        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
            mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
        }

        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
            mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
        }

        mNumConnectivityChange = in.readInt();
        mLoadedNumConnectivityChange = in.readInt();
        mUnpluggedNumConnectivityChange = in.readInt();
@@ -9212,6 +9332,12 @@ public final class BatteryStatsImpl extends BatteryStats {
        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
            mBluetoothStateTimer[i].writeToParcel(out, uSecRealtime);
        }
        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
            mBluetoothActivityCounters[i].writeToParcel(out);
        }
        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
            mWifiActivityCounters[i].writeToParcel(out);
        }
        out.writeInt(mNumConnectivityChange);
        out.writeInt(mLoadedNumConnectivityChange);
        out.writeInt(mUnpluggedNumConnectivityChange);
+24 −3
Original line number Diff line number Diff line
@@ -75,6 +75,11 @@ public class PowerProfile {
     */
    public static final String POWER_WIFI_ACTIVE = "wifi.active";

    /**
     * Operating voltage of the WiFi controller.
     */
    public static final String OPERATING_VOLTAGE_WIFI = "wifi.voltage";

    /**
     * Power consumption when GPS is on.
     */
@@ -95,6 +100,11 @@ public class PowerProfile {
     */
    public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at";

    /**
     * Operating voltage of the Bluetooth controller.
     */
    public static final String OPERATING_VOLTAGE_BLUETOOTH = "bluetooth.voltage";

    /**
     * Power consumption when screen is on, not including the backlight power.
     */
@@ -224,11 +234,13 @@ public class PowerProfile {
    }

    /**
     * Returns the average current in mA consumed by the subsystem 
     * Returns the average current in mA consumed by the subsystem, or the given
     * default value if the subsystem has no recorded value.
     * @param type the subsystem type
     * @param defaultValue the value to return if the subsystem has no recorded value.
     * @return the average current in milliAmps.
     */
    public double getAveragePower(String type) {
    public double getAveragePowerOrDefault(String type, double defaultValue) {
        if (sPowerMap.containsKey(type)) {
            Object data = sPowerMap.get(type);
            if (data instanceof Double[]) {
@@ -237,10 +249,19 @@ public class PowerProfile {
                return (Double) sPowerMap.get(type);
            }
        } else {
            return 0;
            return defaultValue;
        }
    }

    /**
     * Returns the average current in mA consumed by the subsystem
     * @param type the subsystem type
     * @return the average current in milliAmps.
     */
    public double getAveragePower(String type) {
        return getAveragePowerOrDefault(type, 0);
    }
    
    /**
     * Returns the average current in mA consumed by the subsystem for the given level.
     * @param type the subsystem type