From 21f76aa77075be5e057c36040d7d6e695c669b72 Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Mon, 25 Jan 2016 12:27:06 -0800 Subject: [PATCH] Record ModemActivityInfo and distribute power blame to apps Telephony expsoses a getModemActivity() method, which BatteryStats will poll when a change in network activity occurs (on the modem). The time spent in various states (tx, idle, rx) are distributed amongst the apps that did rx/tx traffic during that window. Bug:23147562 Change-Id: I480a85df95786f87c382b96816fe2ed4bb2d5a42 --- core/java/android/os/BatteryStats.java | 450 +++++++------ .../android/internal/os/BatteryStatsImpl.java | 629 ++++++++++++------ .../internal/os/BluetoothPowerCalculator.java | 16 +- .../com/android/internal/os/PowerProfile.java | 12 + .../internal/os/WifiPowerCalculator.java | 27 +- core/res/res/xml/power_profile.xml | 14 +- .../server/am/BatteryStatsService.java | 27 +- .../android/telephony/ModemActivityInfo.java | 5 +- 8 files changed, 770 insertions(+), 410 deletions(-) diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 918050644ce41..52fa2ed162f18 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -201,9 +201,14 @@ public abstract class BatteryStats implements Parcelable { private static final String BATTERY_LEVEL_DATA = "lv"; private static final String GLOBAL_WIFI_DATA = "gwfl"; private static final String WIFI_DATA = "wfl"; - private static final String GLOBAL_BLUETOOTH_DATA = "gble"; + private static final String GLOBAL_WIFI_CONTROLLER_DATA = "gwfcd"; + private static final String WIFI_CONTROLLER_DATA = "wfcd"; + private static final String GLOBAL_BLUETOOTH_CONTROLLER_DATA = "gble"; + private static final String BLUETOOTH_CONTROLLER_DATA = "ble"; private static final String MISC_DATA = "m"; private static final String GLOBAL_NETWORK_DATA = "gn"; + private static final String GLOBAL_MODEM_CONTROLLER_DATA = "gmcd"; + private static final String MODEM_CONTROLLER_DATA = "mcd"; private static final String HISTORY_STRING_POOL = "hsp"; private static final String HISTORY_DATA = "h"; private static final String SCREEN_BRIGHTNESS_DATA = "br"; @@ -270,6 +275,39 @@ public abstract class BatteryStats implements Parcelable { public abstract void logState(Printer pw, String prefix); } + /** + * Container class that aggregates counters for transmit, receive, and idle state of a + * radio controller. + */ + public static abstract class ControllerActivityCounter { + /** + * @return a non-null {@link LongCounter} representing time spent (milliseconds) in the + * idle state. + */ + public abstract LongCounter getIdleTimeCounter(); + + /** + * @return a non-null {@link LongCounter} representing time spent (milliseconds) in the + * receive state. + */ + public abstract LongCounter getRxTimeCounter(); + + /** + * An array of {@link LongCounter}, representing various transmit levels, where each level + * may draw a different amount of power. The levels themselves are controller-specific. + * @return non-null array of {@link LongCounter}s representing time spent (milliseconds) in + * various transmit level states. + */ + public abstract LongCounter[] getTxTimeCounters(); + + /** + * @return a non-null {@link LongCounter} representing the power consumed by the controller + * in all states, measured in milli-ampere-milliseconds (mAms). The counter may always + * yield a value of 0 if the device doesn't support power calculations. + */ + public abstract LongCounter getPowerCounter(); + } + /** * State for keeping track of timing information. */ @@ -367,25 +405,9 @@ public abstract class BatteryStats implements Parcelable { */ public abstract ArrayMap getPackageStats(); - /** - * Returns the time in milliseconds that this app kept the WiFi controller in the - * specified state type. - * @param type one of {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, or - * {@link #CONTROLLER_TX_TIME}. - * @param which one of {@link #STATS_CURRENT}, {@link #STATS_SINCE_CHARGED}, or - * {@link #STATS_SINCE_UNPLUGGED}. - */ - public abstract long getWifiControllerActivity(int type, int which); - - /** - * Returns the time in milliseconds that this app kept the Bluetooth controller in the - * specified state type. - * @param type one of {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, or - * {@link #CONTROLLER_TX_TIME}. - * @param which one of {@link #STATS_CURRENT}, {@link #STATS_SINCE_CHARGED}, or - * {@link #STATS_SINCE_UNPLUGGED}. - */ - public abstract long getBluetoothControllerActivity(int type, int which); + public abstract ControllerActivityCounter getWifiControllerActivity(); + public abstract ControllerActivityCounter getBluetoothControllerActivity(); + public abstract ControllerActivityCounter getModemControllerActivity(); /** * {@hide} @@ -2031,43 +2053,47 @@ 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_POWER_DRAIN = 3; - public static final int NUM_CONTROLLER_ACTIVITY_TYPES = CONTROLLER_POWER_DRAIN + 1; - - /** - * Returns true if the BatteryStats object has detailed bluetooth power reports. - * When true, calling {@link #getBluetoothControllerActivity(int, int)} will yield the - * actual power data. - */ - public abstract boolean hasBluetoothActivityReporting(); - - /** - * For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and - * {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the - * respective state. - * For {@link #CONTROLLER_POWER_DRAIN}, returns the power used by the controller in - * milli-ampere-milliseconds (mAms). - */ - public abstract long getBluetoothControllerActivity(int type, int which); - /** * Returns true if the BatteryStats object has detailed WiFi power reports. - * When true, calling {@link #getWifiControllerActivity(int, int)} will yield the + * When true, calling {@link #getWifiControllerActivity()} will yield the * actual power data. */ public abstract boolean hasWifiActivityReporting(); /** - * For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and - * {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the - * respective state. - * For {@link #CONTROLLER_POWER_DRAIN}, returns the power used by the controller in - * milli-ampere-milliseconds (mAms). + * Returns a {@link ControllerActivityCounter} which is an aggregate of the times spent + * in various radio controller states, such as transmit, receive, and idle. + * @return non-null {@link ControllerActivityCounter} */ - public abstract long getWifiControllerActivity(int type, int which); + public abstract ControllerActivityCounter getWifiControllerActivity(); + + /** + * Returns true if the BatteryStats object has detailed bluetooth power reports. + * When true, calling {@link #getBluetoothControllerActivity()} will yield the + * actual power data. + */ + public abstract boolean hasBluetoothActivityReporting(); + + /** + * Returns a {@link ControllerActivityCounter} which is an aggregate of the times spent + * in various radio controller states, such as transmit, receive, and idle. + * @return non-null {@link ControllerActivityCounter} + */ + public abstract ControllerActivityCounter getBluetoothControllerActivity(); + + /** + * Returns true if the BatteryStats object has detailed modem power reports. + * When true, calling {@link #getModemControllerActivity()} will yield the + * actual power data. + */ + public abstract boolean hasModemActivityReporting(); + + /** + * Returns a {@link ControllerActivityCounter} which is an aggregate of the times spent + * in various radio controller states, such as transmit, receive, and idle. + * @return non-null {@link ControllerActivityCounter} + */ + public abstract ControllerActivityCounter getModemControllerActivity(); /** * Return the wall clock time when battery stats data collection started. @@ -2496,6 +2522,17 @@ public abstract class BatteryStats implements Parcelable { return ","; } + private static final void dumpLineHeader(PrintWriter pw, int uid, String category, + String type) { + pw.print(BATTERY_STATS_CHECKIN_VERSION); + pw.print(','); + pw.print(uid); + pw.print(','); + pw.print(category); + pw.print(','); + pw.print(type); + } + /** * Dump a comma-separated line of values for terse checkin mode. * @@ -2506,14 +2543,7 @@ public abstract class BatteryStats implements Parcelable { */ private static final void dumpLine(PrintWriter pw, int uid, String category, String type, Object... args ) { - pw.print(BATTERY_STATS_CHECKIN_VERSION); - pw.print(','); - pw.print(uid); - pw.print(','); - pw.print(category); - pw.print(','); - pw.print(type); - + dumpLineHeader(pw, uid, category, type); for (Object arg : args) { pw.print(','); pw.print(arg); @@ -2545,6 +2575,140 @@ public abstract class BatteryStats implements Parcelable { } } + /** + * Checks if the ControllerActivityCounter has any data worth dumping. + */ + private static boolean controllerActivityHasData(ControllerActivityCounter counter, int which) { + if (counter == null) { + return false; + } + + if (counter.getIdleTimeCounter().getCountLocked(which) != 0 + || counter.getRxTimeCounter().getCountLocked(which) != 0 + || counter.getPowerCounter().getCountLocked(which) != 0) { + return true; + } + + for (LongCounter c : counter.getTxTimeCounters()) { + if (c.getCountLocked(which) != 0) { + return true; + } + } + return false; + } + + /** + * Dumps the ControllerActivityCounter if it has any data worth dumping. + * The order of the arguments in the final check in line is: + * + * idle, rx, power, tx... + * + * where tx... is one or more transmit level times. + */ + private static final void dumpControllerActivityLine(PrintWriter pw, int uid, String category, + String type, + ControllerActivityCounter counter, + int which) { + if (!controllerActivityHasData(counter, which)) { + return; + } + + dumpLineHeader(pw, uid, category, type); + pw.print(","); + pw.print(counter.getIdleTimeCounter().getCountLocked(which)); + pw.print(","); + pw.print(counter.getRxTimeCounter().getCountLocked(which)); + pw.print(","); + pw.print(counter.getPowerCounter().getCountLocked(which) / (1000 * 60 * 60)); + for (LongCounter c : counter.getTxTimeCounters()) { + pw.print(","); + pw.print(c.getCountLocked(which)); + } + pw.println(); + } + + private final void printControllerActivityIfInteresting(PrintWriter pw, StringBuilder sb, + String prefix, String controllerName, + ControllerActivityCounter counter, + int which) { + if (controllerActivityHasData(counter, which)) { + printControllerActivity(pw, sb, prefix, controllerName, counter, which); + } + } + + private final void printControllerActivity(PrintWriter pw, StringBuilder sb, String prefix, + String controllerName, + ControllerActivityCounter counter, int which) { + final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which); + final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which); + final long powerDrainMaMs = counter.getPowerCounter().getCountLocked(which); + long totalTxTimeMs = 0; + for (LongCounter txState : counter.getTxTimeCounters()) { + totalTxTimeMs += txState.getCountLocked(which); + } + + final long totalTimeMs = idleTimeMs + rxTimeMs + totalTxTimeMs; + + sb.setLength(0); + sb.append(prefix); + sb.append(" "); + sb.append(controllerName); + sb.append(" Idle time: "); + formatTimeMs(sb, idleTimeMs); + sb.append("("); + sb.append(formatRatioLocked(idleTimeMs, totalTimeMs)); + sb.append(")"); + pw.println(sb.toString()); + + sb.setLength(0); + sb.append(prefix); + sb.append(" "); + sb.append(controllerName); + sb.append(" Rx time: "); + formatTimeMs(sb, rxTimeMs); + sb.append("("); + sb.append(formatRatioLocked(rxTimeMs, totalTimeMs)); + sb.append(")"); + pw.println(sb.toString()); + + sb.setLength(0); + sb.append(prefix); + sb.append(" "); + sb.append(controllerName); + sb.append(" Tx time: "); + formatTimeMs(sb, totalTxTimeMs); + sb.append("("); + sb.append(formatRatioLocked(totalTxTimeMs, totalTimeMs)); + sb.append(")"); + pw.println(sb.toString()); + + final int numTxLvls = counter.getTxTimeCounters().length; + if (numTxLvls > 1) { + for (int lvl = 0; lvl < numTxLvls; lvl++) { + final long txLvlTimeMs = counter.getTxTimeCounters()[lvl].getCountLocked(which); + sb.setLength(0); + sb.append(prefix); + sb.append(" ["); + sb.append(lvl); + sb.append("] "); + formatTimeMs(sb, txLvlTimeMs); + sb.append("("); + sb.append(formatRatioLocked(txLvlTimeMs, totalTxTimeMs)); + sb.append(")"); + pw.println(sb.toString()); + } + } + + sb.setLength(0); + sb.append(prefix); + sb.append(" "); + sb.append(controllerName); + sb.append(" Power drain: ").append( + BatteryStatsHelper.makemAh(powerDrainMaMs / (double) (1000*60*60))); + sb.append("mAh"); + pw.println(sb.toString()); + } + /** * Temporary for settings. */ @@ -2637,24 +2801,22 @@ public abstract class BatteryStats implements Parcelable { mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes, mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets); + // Dump Modem controller stats + dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_MODEM_CONTROLLER_DATA, + getModemControllerActivity(), which); + // Dump Wifi controller stats final long wifiOnTime = getWifiOnTime(rawRealtime, which); final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which); - final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which); - final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which); - final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which); - final long wifiPowerMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which); - dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA, - wifiOnTime / 1000, wifiRunningTime / 1000, - wifiIdleTimeMs, wifiRxTimeMs, wifiTxTimeMs, wifiPowerMaMs / (1000*60*60)); + dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA, wifiOnTime / 1000, + wifiRunningTime / 1000, /* legacy fields follow, keep at 0 */ 0, 0, 0, 0); + + dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_WIFI_CONTROLLER_DATA, + getWifiControllerActivity(), which); // Dump Bluetooth controller stats - final long btIdleTimeMs = getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which); - final long btRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which); - final long btTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which); - final long btPowerMaMs = getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which); - dumpLine(pw, 0 /* uid */, category, GLOBAL_BLUETOOTH_DATA, - btIdleTimeMs, btRxTimeMs, btTxTimeMs, btPowerMaMs / (1000*60*60)); + dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_BLUETOOTH_CONTROLLER_DATA, + getBluetoothControllerActivity(), which); // Dump misc stats dumpLine(pw, 0 /* uid */, category, MISC_DATA, @@ -2865,21 +3027,25 @@ public abstract class BatteryStats implements Parcelable { mobileActiveTime, mobileActiveCount); } + // Dump modem controller data, per UID. + dumpControllerActivityLine(pw, uid, category, MODEM_CONTROLLER_DATA, + u.getModemControllerActivity(), which); + + // Dump Wifi controller data, per UID. final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which); final long wifiScanTime = u.getWifiScanTime(rawRealtime, which); final int wifiScanCount = u.getWifiScanCount(which); final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which); - final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which); - final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which); - final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which); if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0 - || uidWifiRunningTime != 0 || uidWifiIdleTimeMs != 0 || uidWifiRxTimeMs != 0 - || uidWifiTxTimeMs != 0) { - dumpLine(pw, uid, category, WIFI_DATA, - fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime, wifiScanCount, - uidWifiIdleTimeMs, uidWifiRxTimeMs, uidWifiTxTimeMs); + || uidWifiRunningTime != 0) { + dumpLine(pw, uid, category, WIFI_DATA, fullWifiLockOnTime, wifiScanTime, + uidWifiRunningTime, wifiScanCount, + /* legacy fields follow, keep at 0 */ 0, 0, 0, 0); } + dumpControllerActivityLine(pw, uid, category, WIFI_CONTROLLER_DATA, + u.getWifiControllerActivity(), which); + if (u.hasUserActivity()) { args = new Object[Uid.NUM_USER_ACTIVITY_TYPES]; boolean hasData = false; @@ -3409,6 +3575,8 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); } + printControllerActivity(pw, sb, prefix, "Radio", getModemControllerActivity(), which); + pw.print(prefix); pw.print(" Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes)); pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes)); @@ -3494,85 +3662,14 @@ public abstract class BatteryStats implements Parcelable { if (!didOne) sb.append(" (no activity)"); pw.println(sb.toString()); - final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which); - final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which); - final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which); - final long wifiPowerDrainMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, 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(" WiFi Power drain: ").append( - BatteryStatsHelper.makemAh(wifiPowerDrainMaMs / (double) (1000*60*60))); - sb.append("mAh"); - pw.println(sb.toString()); + printControllerActivity(pw, sb, prefix, "WiFi", getWifiControllerActivity(), which); pw.print(prefix); pw.print(" Bluetooth total received: "); pw.print(formatBytesLocked(btRxTotalBytes)); pw.print(", sent: "); pw.println(formatBytesLocked(btTxTotalBytes)); - 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()); - - sb.setLength(0); - sb.append(prefix); - sb.append(" Bluetooth Power drain: ").append(BatteryStatsHelper.makemAh( - getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which) / - (double)(1000*60*60))); - sb.append("mAh"); - pw.println(sb.toString()); + printControllerActivity(pw, sb, prefix, "Bluetooth", getBluetoothControllerActivity(), + which); pw.println(); @@ -3897,6 +3994,9 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); } + printControllerActivityIfInteresting(pw, sb, prefix + " ", "Modem", + u.getModemControllerActivity(), which); + if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) { pw.print(prefix); pw.print(" Wi-Fi network: "); pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, "); @@ -3925,26 +4025,8 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); } - final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which); - final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which); - final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which); - final long uidWifiTotalTimeMs = uidWifiIdleTimeMs + uidWifiRxTimeMs + uidWifiTxTimeMs; - if (uidWifiTotalTimeMs > 0) { - sb.setLength(0); - sb.append(prefix).append(" WiFi Idle time: "); - formatTimeMs(sb, uidWifiIdleTimeMs); - sb.append("(").append(formatRatioLocked(uidWifiIdleTimeMs, uidWifiTotalTimeMs)) - .append(")\n"); - - sb.append(prefix).append(" WiFi Rx time: "); formatTimeMs(sb, uidWifiRxTimeMs); - sb.append("(").append(formatRatioLocked(uidWifiRxTimeMs, uidWifiTotalTimeMs)) - .append(")\n"); - - sb.append(prefix).append(" WiFi Tx time: "); formatTimeMs(sb, uidWifiTxTimeMs); - sb.append("(").append(formatRatioLocked(uidWifiTxTimeMs, uidWifiTotalTimeMs)) - .append(")"); - pw.println(sb.toString()); - } + printControllerActivityIfInteresting(pw, sb, prefix + " ", "WiFi", + u.getWifiControllerActivity(), which); if (btRxBytes > 0 || btTxBytes > 0) { pw.print(prefix); pw.print(" Bluetooth network: "); @@ -3953,30 +4035,6 @@ public abstract class BatteryStats implements Parcelable { pw.println(" sent"); } - final long uidBtIdleTimeMs = u.getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, - which); - final long uidBtRxTimeMs = u.getBluetoothControllerActivity(CONTROLLER_RX_TIME, which); - final long uidBtTxTimeMs = u.getBluetoothControllerActivity(CONTROLLER_TX_TIME, which); - final long uidBtTotalTimeMs = uidBtIdleTimeMs + uidBtRxTimeMs + uidBtTxTimeMs; - if (uidBtTotalTimeMs > 0) { - sb.setLength(0); - sb.append(prefix).append(" Bluetooth Idle time: "); - formatTimeMs(sb, uidBtIdleTimeMs); - sb.append("(").append(formatRatioLocked(uidBtIdleTimeMs, uidBtTotalTimeMs)) - .append(")\n"); - - sb.append(prefix).append(" Bluetooth Rx time: "); - formatTimeMs(sb, uidBtRxTimeMs); - sb.append("(").append(formatRatioLocked(uidBtRxTimeMs, uidBtTotalTimeMs)) - .append(")\n"); - - sb.append(prefix).append(" Bluetooth Tx time: "); - formatTimeMs(sb, uidBtTxTimeMs); - sb.append("(").append(formatRatioLocked(uidBtTxTimeMs, uidBtTotalTimeMs)) - .append(")"); - pw.println(sb.toString()); - } - if (u.hasUserActivity()) { boolean hasData = false; for (int i=0; i= 0 && type < mBluetoothActivityCounters.length) { - return mBluetoothActivityCounters[type].getCountLocked(which); - } - return 0; + @Override + public ControllerActivityCounter getWifiControllerActivity() { + return mWifiActivity; } - @Override public boolean hasWifiActivityReporting() { - return mHasWifiEnergyReporting; + @Override + public ControllerActivityCounter getModemControllerActivity() { + return mModemActivity; } - @Override public long getWifiControllerActivity(int type, int which) { - if (type >= 0 && type < mWifiActivityCounters.length) { - return mWifiActivityCounters[type].getCountLocked(which); - } - return 0; + @Override + public boolean hasBluetoothActivityReporting() { + return mHasBluetoothReporting; + } + + @Override + public boolean hasWifiActivityReporting() { + return mHasWifiReporting; + } + + @Override + public boolean hasModemActivityReporting() { + return mHasModemReporting; } @Override @@ -4457,15 +4621,21 @@ public final class BatteryStatsImpl extends BatteryStats { /** * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode. + * Can be null if the UID has had no such activity. */ - LongSamplingCounter[] mWifiControllerTime = - new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES]; + private ControllerActivityCounterImpl mWifiControllerActivity; /** * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode. + * Can be null if the UID has had no such activity. */ - LongSamplingCounter[] mBluetoothControllerTime = - new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES]; + private ControllerActivityCounterImpl mBluetoothControllerActivity; + + /** + * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode. + * Can be null if the UID has had no such activity. + */ + private ControllerActivityCounterImpl mModemControllerActivity; /** * The CPU times we had at the last history details update. @@ -4684,18 +4854,43 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public void noteWifiControllerActivityLocked(int type, long timeMs) { - if (mWifiControllerTime[type] == null) { - mWifiControllerTime[type] = new LongSamplingCounter(mOnBatteryTimeBase); - } - mWifiControllerTime[type].addCountLocked(timeMs); + @Override + public ControllerActivityCounter getWifiControllerActivity() { + return mWifiControllerActivity; } - public void noteBluetoothControllerActivityLocked(int type, long timeMs) { - if (mBluetoothControllerTime[type] == null) { - mBluetoothControllerTime[type] = new LongSamplingCounter(mOnBatteryTimeBase); + @Override + public ControllerActivityCounter getBluetoothControllerActivity() { + return mBluetoothControllerActivity; + } + + @Override + public ControllerActivityCounter getModemControllerActivity() { + return mModemControllerActivity; + } + + public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() { + if (mWifiControllerActivity == null) { + mWifiControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + NUM_BT_TX_LEVELS); } - mBluetoothControllerTime[type].addCountLocked(timeMs); + return mWifiControllerActivity; + } + + public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() { + if (mBluetoothControllerActivity == null) { + mBluetoothControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + NUM_BT_TX_LEVELS); + } + return mBluetoothControllerActivity; + } + + public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() { + if (mModemControllerActivity == null) { + mModemControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + ModemActivityInfo.TX_POWER_LEVELS); + } + return mModemControllerActivity; } public StopwatchTimer createAudioTurnedOnTimerLocked() { @@ -5083,24 +5278,6 @@ public final class BatteryStatsImpl extends BatteryStats { return 0; } - @Override - public long getWifiControllerActivity(int type, int which) { - if (type >= 0 && type < NUM_CONTROLLER_ACTIVITY_TYPES && - mWifiControllerTime[type] != null) { - return mWifiControllerTime[type].getCountLocked(which); - } - return 0; - } - - @Override - public long getBluetoothControllerActivity(int type, int which) { - if (type >= 0 && type < NUM_CONTROLLER_ACTIVITY_TYPES && - mBluetoothControllerTime[type] != null) { - return mBluetoothControllerTime[type].getCountLocked(which); - } - return 0; - } - void initNetworkActivityLocked() { mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; @@ -5190,14 +5367,16 @@ public final class BatteryStatsImpl extends BatteryStats { mMobileRadioActiveCount.reset(false); } - for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) { - if (mWifiControllerTime[i] != null) { - mWifiControllerTime[i].reset(false); - } + if (mWifiControllerActivity != null) { + mWifiControllerActivity.reset(false); + } - if (mBluetoothControllerTime[i] != null) { - mBluetoothControllerTime[i].reset(false); - } + if (mBluetoothActivity != null) { + mBluetoothActivity.reset(false); + } + + if (mModemActivity != null) { + mModemActivity.reset(false); } mUserCpuTime.reset(false); @@ -5342,15 +5521,18 @@ public final class BatteryStatsImpl extends BatteryStats { } } - for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) { - if (mWifiControllerTime[i] != null) { - mWifiControllerTime[i].detach(); - } - - if (mBluetoothControllerTime[i] != null) { - mBluetoothControllerTime[i].detach(); - } + if (mWifiControllerActivity != null) { + mWifiControllerActivity.detach(); } + + if (mBluetoothControllerActivity != null) { + mBluetoothControllerActivity.detach(); + } + + if (mModemControllerActivity != null) { + mModemControllerActivity.detach(); + } + mPids.clear(); mUserCpuTime.detach(); @@ -5521,22 +5703,25 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(0); } - for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) { - if (mWifiControllerTime[i] != null) { - out.writeInt(1); - mWifiControllerTime[i].writeToParcel(out); - } else { - out.writeInt(0); - } + if (mWifiControllerActivity != null) { + out.writeInt(1); + mWifiControllerActivity.writeToParcel(out, 0); + } else { + out.writeInt(0); } - for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) { - if (mBluetoothControllerTime[i] != null) { - out.writeInt(1); - mBluetoothControllerTime[i].writeToParcel(out); - } else { - out.writeInt(0); - } + if (mBluetoothControllerActivity != null) { + out.writeInt(1); + mBluetoothControllerActivity.writeToParcel(out, 0); + } else { + out.writeInt(0); + } + + if (mModemControllerActivity != null) { + out.writeInt(1); + mModemControllerActivity.writeToParcel(out, 0); + } else { + out.writeInt(0); } mUserCpuTime.writeToParcel(out); @@ -5727,20 +5912,25 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkPacketActivityCounters = null; } - for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) { - if (in.readInt() != 0) { - mWifiControllerTime[i] = new LongSamplingCounter(mOnBatteryTimeBase, in); - } else { - mWifiControllerTime[i] = null; - } + if (in.readInt() != 0) { + mWifiControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + NUM_WIFI_TX_LEVELS, in); + } else { + mWifiControllerActivity = null; } - for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) { - if (in.readInt() != 0) { - mBluetoothControllerTime[i] = new LongSamplingCounter(mOnBatteryTimeBase, in); - } else { - mBluetoothControllerTime[i] = null; - } + if (in.readInt() != 0) { + mBluetoothControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + NUM_BT_TX_LEVELS, in); + } else { + mBluetoothControllerActivity = null; + } + + if (in.readInt() != 0) { + mModemControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + ModemActivityInfo.TX_POWER_LEVELS, in); + } else { + mModemControllerActivity = null; } mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in); @@ -6916,10 +7106,12 @@ 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); - } + mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS); + mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + NUM_BT_TX_LEVELS); + mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + ModemActivityInfo.TX_POWER_LEVELS); + mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase); mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase); mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase); @@ -7567,10 +7759,9 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i=0; i0.1 0.1 0.1 + 0.1 + + 0.1 0.1 - 0.1 0.2 0.1 + + + 0 + 0 + 0 + 0 +