diff options
8 files changed, 761 insertions, 401 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 918050644ce4..52fa2ed162f1 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"; @@ -271,6 +276,39 @@ public abstract class BatteryStats implements Parcelable { } /** + * 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. */ public static abstract class Timer { @@ -367,25 +405,9 @@ public abstract class BatteryStats implements Parcelable { */ public abstract ArrayMap<String, ? extends Pkg> getPackageStats(); - /** - * Returns the time in milliseconds that this app kept the WiFi controller in the - * specified state <code>type</code>. - * @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 <code>type</code>. - * @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 WiFi power reports. + * When true, calling {@link #getWifiControllerActivity()} will yield the + * actual power data. + */ + public abstract boolean hasWifiActivityReporting(); + + /** + * 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 getWifiControllerActivity(); /** * Returns true if the BatteryStats object has detailed bluetooth power reports. - * When true, calling {@link #getBluetoothControllerActivity(int, int)} will yield the + * When true, calling {@link #getBluetoothControllerActivity()} 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). + * 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 getBluetoothControllerActivity(int type, int which); + public abstract ControllerActivityCounter getBluetoothControllerActivity(); /** - * Returns true if the BatteryStats object has detailed WiFi power reports. - * When true, calling {@link #getWifiControllerActivity(int, int)} will yield the + * 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 hasWifiActivityReporting(); + public abstract boolean hasModemActivityReporting(); /** - * 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 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); @@ -2546,6 +2576,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. */ public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) { @@ -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<Uid.NUM_USER_ACTIVITY_TYPES; i++) { diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 57220b1e1968..c71c131146a1 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -41,6 +41,7 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.WorkSource; import android.telephony.DataConnectionRealTimeInfo; +import android.telephony.ModemActivityInfo; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; @@ -106,7 +107,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 139 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 140 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -119,6 +120,12 @@ public final class BatteryStatsImpl extends BatteryStats { // in to one common name. private static final int MAX_WAKELOCKS_PER_UID = 100; + // Number of transmit power states the Wifi controller can be in. + private static final int NUM_WIFI_TX_LEVELS = 1; + + // Number of transmit power states the Bluetooth controller can be in. + private static final int NUM_BT_TX_LEVELS = 1; + private final JournaledFile mFile; public final AtomicFile mCheckinFile; public final AtomicFile mDailyFile; @@ -379,11 +386,38 @@ public final class BatteryStatsImpl extends BatteryStats { final LongSamplingCounter[] mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; - final LongSamplingCounter[] mBluetoothActivityCounters = - new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES]; + /** + * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device. + */ + ControllerActivityCounterImpl mWifiActivity; + + /** + * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device. + */ + ControllerActivityCounterImpl mBluetoothActivity; + + /** + * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device. + */ + ControllerActivityCounterImpl mModemActivity; + + /** + * Whether the device supports WiFi controller energy reporting. This is set to true on + * the first WiFi energy report. See {@link #mWifiActivity}. + */ + boolean mHasWifiReporting = false; + + /** + * Whether the device supports Bluetooth controller energy reporting. This is set to true on + * the first Bluetooth energy report. See {@link #mBluetoothActivity}. + */ + boolean mHasBluetoothReporting = false; - final LongSamplingCounter[] mWifiActivityCounters = - new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES]; + /** + * Whether the device supports Modem controller energy reporting. This is set to true on + * the first Modem energy report. See {@link #mModemActivity}. + */ + boolean mHasModemReporting = false; boolean mWifiOn; StopwatchTimer mWifiOnTimer; @@ -479,8 +513,6 @@ public final class BatteryStatsImpl extends BatteryStats { private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry(); private PowerProfile mPowerProfile; - private boolean mHasWifiEnergyReporting = false; - private boolean mHasBluetoothEnergyReporting = false; /* * Holds a SamplingTimer associated with each kernel wakelock name being tracked. @@ -1770,6 +1802,131 @@ public final class BatteryStatsImpl extends BatteryStats { public abstract T instantiateObject(); } + public static class ControllerActivityCounterImpl extends ControllerActivityCounter + implements Parcelable { + private final LongSamplingCounter mIdleTimeMillis; + private final LongSamplingCounter mRxTimeMillis; + private final LongSamplingCounter[] mTxTimeMillis; + private final LongSamplingCounter mPowerDrainMaMs; + + public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) { + mIdleTimeMillis = new LongSamplingCounter(timeBase); + mRxTimeMillis = new LongSamplingCounter(timeBase); + mTxTimeMillis = new LongSamplingCounter[numTxStates]; + for (int i = 0; i < numTxStates; i++) { + mTxTimeMillis[i] = new LongSamplingCounter(timeBase); + } + mPowerDrainMaMs = new LongSamplingCounter(timeBase); + } + + public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) { + mIdleTimeMillis = new LongSamplingCounter(timeBase, in); + mRxTimeMillis = new LongSamplingCounter(timeBase, in); + final int recordedTxStates = in.readInt(); + if (recordedTxStates != numTxStates) { + throw new ParcelFormatException("inconsistent tx state lengths"); + } + + mTxTimeMillis = new LongSamplingCounter[numTxStates]; + for (int i = 0; i < numTxStates; i++) { + mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in); + } + mPowerDrainMaMs = new LongSamplingCounter(timeBase, in); + } + + public void readSummaryFromParcel(Parcel in) { + mIdleTimeMillis.readSummaryFromParcelLocked(in); + mRxTimeMillis.readSummaryFromParcelLocked(in); + final int recordedTxStates = in.readInt(); + if (recordedTxStates != mTxTimeMillis.length) { + throw new ParcelFormatException("inconsistent tx state lengths"); + } + for (LongSamplingCounter counter : mTxTimeMillis) { + counter.readSummaryFromParcelLocked(in); + } + mPowerDrainMaMs.readSummaryFromParcelLocked(in); + } + + @Override + public int describeContents() { + return 0; + } + + public void writeSummaryToParcel(Parcel dest) { + mIdleTimeMillis.writeSummaryFromParcelLocked(dest); + mRxTimeMillis.writeSummaryFromParcelLocked(dest); + dest.writeInt(mTxTimeMillis.length); + for (LongSamplingCounter counter : mTxTimeMillis) { + counter.writeSummaryFromParcelLocked(dest); + } + mPowerDrainMaMs.writeSummaryFromParcelLocked(dest); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + mIdleTimeMillis.writeToParcel(dest); + mRxTimeMillis.writeToParcel(dest); + dest.writeInt(mTxTimeMillis.length); + for (LongSamplingCounter counter : mTxTimeMillis) { + counter.writeToParcel(dest); + } + mPowerDrainMaMs.writeToParcel(dest); + } + + public void reset(boolean detachIfReset) { + mIdleTimeMillis.reset(detachIfReset); + mRxTimeMillis.reset(detachIfReset); + for (LongSamplingCounter counter : mTxTimeMillis) { + counter.reset(detachIfReset); + } + mPowerDrainMaMs.reset(detachIfReset); + } + + public void detach() { + mIdleTimeMillis.detach(); + mRxTimeMillis.detach(); + for (LongSamplingCounter counter : mTxTimeMillis) { + counter.detach(); + } + mPowerDrainMaMs.detach(); + } + + /** + * @return a LongSamplingCounter, measuring time spent in the idle state in + * milliseconds. + */ + @Override + public LongSamplingCounter getIdleTimeCounter() { + return mRxTimeMillis; + } + + /** + * @return a LongSamplingCounter, measuring time spent in the receive state in + * milliseconds. + */ + @Override + public LongSamplingCounter getRxTimeCounter() { + return mRxTimeMillis; + } + + /** + * @return a LongSamplingCounter[], measuring time spent in various transmit states in + * milliseconds. + */ + @Override + public LongSamplingCounter[] getTxTimeCounters() { + return mTxTimeMillis; + } + + /** + * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS). + */ + @Override + public LongSamplingCounter getPowerCounter() { + return mPowerDrainMaMs; + } + } + /* * Get the wakeup reason counter, and create a new one if one * doesn't already exist. @@ -3198,7 +3355,7 @@ public final class BatteryStatsImpl extends BatteryStats { mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime); } else { mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs); - updateMobileRadioStateLocked(realElapsedRealtimeMs); + updateMobileRadioStateLocked(realElapsedRealtimeMs, null); mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs); } } @@ -4144,8 +4301,7 @@ public final class BatteryStatsImpl extends BatteryStats { // During device boot, qtaguid isn't enabled until after the inital // loading of battery stats. Now that they're enabled, take our initial // snapshot for future delta calculation. - final long elapsedRealtimeMs = SystemClock.elapsedRealtime(); - updateMobileRadioStateLocked(elapsedRealtimeMs); + updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), null); updateWifiStateLocked(null); } @@ -4328,26 +4484,34 @@ public final class BatteryStatsImpl extends BatteryStats { return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which); } - @Override public boolean hasBluetoothActivityReporting() { - return mHasBluetoothEnergyReporting; + @Override + public ControllerActivityCounter getBluetoothControllerActivity() { + return mBluetoothActivity; } - @Override public long getBluetoothControllerActivity(int type, int which) { - if (type >= 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); + @Override + public ControllerActivityCounter getWifiControllerActivity() { + return mWifiControllerActivity; + } + + @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); } - mWifiControllerTime[type].addCountLocked(timeMs); + return mWifiControllerActivity; } - public void noteBluetoothControllerActivityLocked(int type, long timeMs) { - if (mBluetoothControllerTime[type] == null) { - mBluetoothControllerTime[type] = new LongSamplingCounter(mOnBatteryTimeBase); + public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() { + if (mBluetoothControllerActivity == null) { + mBluetoothControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + NUM_BT_TX_LEVELS); } - mBluetoothControllerTime[type].addCountLocked(timeMs); + 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 (mWifiControllerActivity != null) { + mWifiControllerActivity.detach(); + } - if (mBluetoothControllerTime[i] != null) { - mBluetoothControllerTime[i].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; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) { mWifiSignalStrengthsTimer[i].reset(false); } - for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) { - mBluetoothActivityCounters[i].reset(false); - mWifiActivityCounters[i].reset(false); - } + mWifiActivity.reset(false); + mBluetoothActivity.reset(false); + mModemActivity.reset(false); mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0; for (int i=0; i<mUidStats.size(); i++) { @@ -7781,7 +7972,7 @@ public final class BatteryStatsImpl extends BatteryStats { } if (info != null) { - mHasWifiEnergyReporting = true; + mHasWifiReporting = true; // Measured in mAms final long txTimeMs = info.getControllerTxTimeMillis(); @@ -7861,8 +8052,11 @@ public final class BatteryStatsImpl extends BatteryStats { + scanRxTimeSinceMarkMs + " ms Tx:" + scanTxTimeSinceMarkMs + " ms)"); } - uid.noteWifiControllerActivityLocked(CONTROLLER_RX_TIME, scanRxTimeSinceMarkMs); - uid.noteWifiControllerActivityLocked(CONTROLLER_TX_TIME, scanTxTimeSinceMarkMs); + + ControllerActivityCounterImpl activityCounter = + uid.getOrCreateWifiControllerActivityLocked(); + activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs); + activityCounter.getTxTimeCounters()[0].addCountLocked(scanTxTimeSinceMarkMs); leftOverRxTimeMs -= scanRxTimeSinceMarkMs; leftOverTxTimeMs -= scanTxTimeSinceMarkMs; } @@ -7881,7 +8075,8 @@ public final class BatteryStatsImpl extends BatteryStats { Slog.d(TAG, " IdleTime for UID " + uid.getUid() + ": " + myIdleTimeMs + " ms"); } - uid.noteWifiControllerActivityLocked(CONTROLLER_IDLE_TIME, myIdleTimeMs); + uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter() + .addCountLocked(myIdleTimeMs); } } @@ -7898,7 +8093,8 @@ public final class BatteryStatsImpl extends BatteryStats { if (DEBUG_ENERGY) { Slog.d(TAG, " TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms"); } - uid.noteWifiControllerActivityLocked(CONTROLLER_TX_TIME, myTxTimeMs); + uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0] + .addCountLocked(myTxTimeMs); } // Distribute the remaining Rx power appropriately between all apps that received @@ -7909,25 +8105,23 @@ public final class BatteryStatsImpl extends BatteryStats { if (DEBUG_ENERGY) { Slog.d(TAG, " RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms"); } - uid.noteWifiControllerActivityLocked(CONTROLLER_RX_TIME, myRxTimeMs); + uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter() + .addCountLocked(myRxTimeMs); } // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper. // Update WiFi controller stats. - mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked( - info.getControllerRxTimeMillis()); - mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked( - info.getControllerTxTimeMillis()); - mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked( - info.getControllerIdleTimeMillis()); + mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis()); + mWifiActivity.getTxTimeCounters()[0].addCountLocked(info.getControllerTxTimeMillis()); + mWifiActivity.getIdleTimeCounter().addCountLocked(info.getControllerIdleTimeMillis()); // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V. final double opVolt = mPowerProfile.getAveragePower( PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0; if (opVolt != 0) { // We store the power drain as mAms. - mWifiActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked( + mWifiActivity.getPowerCounter().addCountLocked( (long)(info.getControllerEnergyUsed() / opVolt)); } } @@ -7936,9 +8130,10 @@ public final class BatteryStatsImpl extends BatteryStats { /** * Distribute Cell radio energy info and network traffic to apps. */ - public void updateMobileRadioStateLocked(final long elapsedRealtimeMs) { + public void updateMobileRadioStateLocked(final long elapsedRealtimeMs, + final ModemActivityInfo activityInfo) { if (DEBUG_ENERGY) { - Slog.d(TAG, "Updating mobile radio stats"); + Slog.d(TAG, "Updating mobile radio stats with " + activityInfo); } NetworkStats delta = null; @@ -7951,60 +8146,112 @@ public final class BatteryStatsImpl extends BatteryStats { return; } - if (delta == null || !mOnBatteryInternal) { + if (!mOnBatteryInternal) { return; } long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked( elapsedRealtimeMs * 1000); mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs); - long totalPackets = delta.getTotalPackets(); - final int size = delta.size(); - for (int i = 0; i < size; i++) { - final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); + long totalRxPackets = 0; + long totalTxPackets = 0; + if (delta != null) { + final int size = delta.size(); + for (int i = 0; i < size; i++) { + final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); + if (entry.rxPackets == 0 || entry.txPackets == 0) { + continue; + } - if (entry.rxBytes == 0 || entry.txBytes == 0) { - continue; - } + if (DEBUG_ENERGY) { + Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes + + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets + + " txPackets=" + entry.txPackets); + } - if (DEBUG_ENERGY) { - Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes - + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets - + " txPackets=" + entry.txPackets); - } + totalRxPackets += entry.rxPackets; + totalTxPackets += entry.txPackets; - final Uid u = getUidStatsLocked(mapUid(entry.uid)); - u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, - entry.rxPackets); - u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, - entry.txPackets); + final Uid u = getUidStatsLocked(mapUid(entry.uid)); + u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets); + u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets); + + mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( + entry.rxBytes); + mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( + entry.txBytes); + mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( + entry.rxPackets); + mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( + entry.txPackets); + } + + // Now distribute proportional blame to the apps that did networking. + long totalPackets = totalRxPackets + totalTxPackets; + if (totalPackets > 0) { + for (int i = 0; i < size; i++) { + final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); + if (entry.rxPackets == 0 && entry.txPackets == 0) { + continue; + } - if (radioTime > 0) { - // Distribute total radio active time in to this app. - long appPackets = entry.rxPackets + entry.txPackets; - long appRadioTime = (radioTime*appPackets)/totalPackets; - u.noteMobileRadioActiveTimeLocked(appRadioTime); - // Remove this app from the totals, so that we don't lose any time - // due to rounding. - radioTime -= appRadioTime; - totalPackets -= appPackets; + final Uid u = getUidStatsLocked(mapUid(entry.uid)); + + // Distribute total radio active time in to this app. + final long appPackets = entry.rxPackets + entry.txPackets; + final long appRadioTime = (radioTime * appPackets) / totalPackets; + u.noteMobileRadioActiveTimeLocked(appRadioTime); + + // Remove this app from the totals, so that we don't lose any time + // due to rounding. + radioTime -= appRadioTime; + totalPackets -= appPackets; + + if (activityInfo != null) { + ControllerActivityCounterImpl activityCounter = + u.getOrCreateModemControllerActivityLocked(); + if (entry.rxPackets != 0) { + final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis()) + / totalRxPackets; + activityCounter.getRxTimeCounter().addCountLocked(rxMs); + } + + if (entry.txPackets != 0) { + for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { + long txMs = entry.txPackets * activityInfo.getTxTimeMillis()[lvl]; + txMs /= totalTxPackets; + activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs); + } + } + } + } } - mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( - entry.rxBytes); - mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( - entry.txBytes); - mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( - entry.rxPackets); - mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( - entry.txPackets); + if (radioTime > 0) { + // Whoops, there is some radio time we can't blame on an app! + mMobileRadioActiveUnknownTime.addCountLocked(radioTime); + mMobileRadioActiveUnknownCount.addCountLocked(1); + } } - if (radioTime > 0) { - // Whoops, there is some radio time we can't blame on an app! - mMobileRadioActiveUnknownTime.addCountLocked(radioTime); - mMobileRadioActiveUnknownCount.addCountLocked(1); + if (activityInfo != null) { + mHasModemReporting = true; + mModemActivity.getIdleTimeCounter().addCountLocked(activityInfo.getIdleTimeMillis()); + mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis()); + for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { + mModemActivity.getTxTimeCounters()[lvl] + .addCountLocked(activityInfo.getTxTimeMillis()[lvl]); + } + + // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V. + final double opVolt = mPowerProfile.getAveragePower( + PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0; + if (opVolt != 0) { + // We store the power drain as mAms. + mModemActivity.getPowerCounter().addCountLocked( + (long) (activityInfo.getEnergyUsed() / opVolt)); + } } } @@ -8018,12 +8265,12 @@ public final class BatteryStatsImpl extends BatteryStats { } if (info != null && mOnBatteryInternal) { - mHasBluetoothEnergyReporting = true; - mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked( + mHasBluetoothReporting = true; + mBluetoothActivity.getRxTimeCounter().addCountLocked( info.getControllerRxTimeMillis()); - mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked( + mBluetoothActivity.getTxTimeCounters()[0].addCountLocked( info.getControllerTxTimeMillis()); - mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked( + mBluetoothActivity.getIdleTimeCounter().addCountLocked( info.getControllerIdleTimeMillis()); // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V. @@ -8031,7 +8278,7 @@ public final class BatteryStatsImpl extends BatteryStats { PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0; if (opVolt != 0) { // We store the power drain as mAms. - mBluetoothActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked( + mBluetoothActivity.getPowerCounter().addCountLocked( (long) (info.getControllerEnergyUsed() / opVolt)); } @@ -9337,12 +9584,12 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) { mWifiSignalStrengthsTimer[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); - } + mWifiActivity.readSummaryFromParcel(in); + mBluetoothActivity.readSummaryFromParcel(in); + mModemActivity.readSummaryFromParcel(in); + mHasWifiReporting = in.readInt() != 0; + mHasBluetoothReporting = in.readInt() != 0; + mHasModemReporting = in.readInt() != 0; mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt(); mFlashlightOnNesting = 0; @@ -9671,12 +9918,13 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) { mWifiSignalStrengthsTimer[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); - } + mWifiActivity.writeSummaryToParcel(out); + mBluetoothActivity.writeSummaryToParcel(out); + mModemActivity.writeSummaryToParcel(out); + out.writeInt(mHasWifiReporting ? 1 : 0); + out.writeInt(mHasBluetoothReporting ? 1 : 0); + out.writeInt(mHasModemReporting ? 1 : 0); + out.writeInt(mNumConnectivityChange); mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); @@ -10019,15 +10267,17 @@ public final class BatteryStatsImpl extends BatteryStats { mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-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); - } - mHasWifiEnergyReporting = in.readInt() != 0; - mHasBluetoothEnergyReporting = in.readInt() != 0; + mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + NUM_WIFI_TX_LEVELS, in); + mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + NUM_BT_TX_LEVELS, in); + mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, + ModemActivityInfo.TX_POWER_LEVELS, in); + mHasWifiReporting = in.readInt() != 0; + mHasBluetoothReporting = in.readInt() != 0; + mHasModemReporting = in.readInt() != 0; + mNumConnectivityChange = in.readInt(); mLoadedNumConnectivityChange = in.readInt(); mUnpluggedNumConnectivityChange = in.readInt(); @@ -10174,14 +10424,13 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) { mWifiSignalStrengthsTimer[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(mHasWifiEnergyReporting ? 1 : 0); - out.writeInt(mHasBluetoothEnergyReporting ? 1 : 0); + mWifiActivity.writeToParcel(out, 0); + mBluetoothActivity.writeToParcel(out, 0); + mModemActivity.writeToParcel(out, 0); + out.writeInt(mHasWifiReporting ? 1 : 0); + out.writeInt(mHasBluetoothReporting ? 1 : 0); + out.writeInt(mHasModemReporting ? 1 : 0); + out.writeInt(mNumConnectivityChange); out.writeInt(mLoadedNumConnectivityChange); out.writeInt(mUnpluggedNumConnectivityChange); diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java index 1f5967283219..531d1fac9991 100644 --- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java +++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java @@ -40,15 +40,15 @@ public class BluetoothPowerCalculator extends PowerCalculator { @Override public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs, long rawUptimeUs, int statsType) { - final long idleTimeMs = stats.getBluetoothControllerActivity( - BatteryStats.CONTROLLER_IDLE_TIME, statsType); - final long txTimeMs = stats.getBluetoothControllerActivity( - BatteryStats.CONTROLLER_TX_TIME, statsType); - final long rxTimeMs = stats.getBluetoothControllerActivity( - BatteryStats.CONTROLLER_RX_TIME, statsType); + final BatteryStats.ControllerActivityCounter counter = + stats.getBluetoothControllerActivity(); + + final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType); + final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType); + final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType); final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs; - double powerMah = stats.getBluetoothControllerActivity( - BatteryStats.CONTROLLER_POWER_DRAIN, statsType) / (double)(1000*60*60); + double powerMah = counter.getPowerCounter().getCountLocked(statsType) + / (double)(1000*60*60); if (powerMah == 0) { // Some devices do not report the power, so calculate it. diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java index aaa9f734aba8..14ebe227f3b4 100644 --- a/core/java/com/android/internal/os/PowerProfile.java +++ b/core/java/com/android/internal/os/PowerProfile.java @@ -93,6 +93,12 @@ public class PowerProfile { public static final String POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE = "bluetooth.controller.voltage"; + public static final String POWER_MODEM_CONTROLLER_IDLE = "modem.controller.idle"; + public static final String POWER_MODEM_CONTROLLER_RX = "modem.controller.rx"; + public static final String POWER_MODEM_CONTROLLER_TX = "modem.controller.tx"; + public static final String POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE = + "modem.controller.voltage"; + /** * Power consumption when GPS is on. */ @@ -100,17 +106,23 @@ public class PowerProfile { /** * Power consumption when Bluetooth driver is on. + * @deprecated */ + @Deprecated public static final String POWER_BLUETOOTH_ON = "bluetooth.on"; /** * Power consumption when Bluetooth driver is transmitting/receiving. + * @deprecated */ + @Deprecated public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active"; /** * Power consumption when Bluetooth driver gets an AT command. + * @deprecated */ + @Deprecated public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at"; diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java index 146c0f87ad5b..2a27f70ff05d 100644 --- a/core/java/com/android/internal/os/WifiPowerCalculator.java +++ b/core/java/com/android/internal/os/WifiPowerCalculator.java @@ -39,10 +39,14 @@ public class WifiPowerCalculator extends PowerCalculator { @Override public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, int statsType) { - final long idleTime = u.getWifiControllerActivity(BatteryStats.CONTROLLER_IDLE_TIME, - statsType); - final long txTime = u.getWifiControllerActivity(BatteryStats.CONTROLLER_TX_TIME, statsType); - final long rxTime = u.getWifiControllerActivity(BatteryStats.CONTROLLER_RX_TIME, statsType); + final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity(); + if (counter == null) { + return; + } + + final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType); + final long txTime = counter.getTxTimeCounters()[0].getCountLocked(statsType); + final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType); app.wifiRunningTimeMs = idleTime + rxTime + txTime; app.wifiPowerMah = ((idleTime * mIdleCurrentMa) + (txTime * mTxCurrentMa) + (rxTime * mRxCurrentMa)) @@ -67,16 +71,15 @@ public class WifiPowerCalculator extends PowerCalculator { @Override public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs, long rawUptimeUs, int statsType) { - final long idleTimeMs = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_IDLE_TIME, - statsType); - final long rxTimeMs = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_RX_TIME, - statsType); - final long txTimeMs = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_TX_TIME, - statsType); + final BatteryStats.ControllerActivityCounter counter = stats.getWifiControllerActivity(); + + final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType); + final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType); + final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType); app.wifiRunningTimeMs = idleTimeMs + rxTimeMs + txTimeMs; - double powerDrainMah = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_POWER_DRAIN, - statsType) / (double)(1000*60*60); + double powerDrainMah = counter.getPowerCounter().getCountLocked(statsType) + / (double)(1000*60*60); if (powerDrainMah == 0) { // Some controllers do not report power drain, so we can calculate it here. powerDrainMah = ((idleTimeMs * mIdleCurrentMa) + (txTimeMs * mTxCurrentMa) diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml index ddd0ca2a4bb2..76b5fe1e1b55 100644 --- a/core/res/res/xml/power_profile.xml +++ b/core/res/res/xml/power_profile.xml @@ -39,15 +39,27 @@ <item name="dsp.video">0.1</item> <!-- ~50mA --> <item name="camera.flashlight">0.1</item> <!-- Avg. power for camera flash, ~160mA --> <item name="camera.avg">0.1</item> <!-- Avg. power use of camera in standard usecases, ~550mA --> + <item name="gps.on">0.1</item> <!-- ~50mA --> + + <!-- Radio related values. For modems without energy reporting support in firmware, use + radio.active, radio.scanning, and radio.on. --> <item name="radio.active">0.1</item> <!-- ~200mA --> <item name="radio.scanning">0.1</item> <!-- cellular radio scanning for signal, ~10mA --> - <item name="gps.on">0.1</item> <!-- ~50mA --> <!-- Current consumed by the radio at different signal strengths, when paging --> <array name="radio.on"> <!-- Strength 0 to BINS-1 --> <value>0.2</value> <!-- ~2mA --> <value>0.1</value> <!-- ~1mA --> </array> + + <!-- Radio related values. For modems WITH energy reporting support in firmware, use + modem.controller.idle, modem.controller.tx, modem.controller.rx, modem.controller.voltage. + --> + <item name="modem.controller.idle">0</item> + <item name="modem.controller.rx">0</item> + <item name="modem.controller.tx">0</item> + <item name="modem.controller.voltage">0</item> + <!-- A list of heterogeneous CPU clusters, where the value for each cluster represents the number of CPU cores for that cluster. diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 0f7dff27b4fc..97ef10b10ab2 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -40,6 +40,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.WorkSource; import android.telephony.DataConnectionRealTimeInfo; +import android.telephony.ModemActivityInfo; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.util.IntArray; @@ -51,6 +52,7 @@ import com.android.internal.app.IBatteryStats; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.PowerProfile; +import com.android.internal.telephony.ITelephony; import com.android.server.FgThread; import com.android.server.LocalServices; @@ -1329,6 +1331,24 @@ public final class BatteryStatsService extends IBatteryStats.Stub return null; } + @GuardedBy("mExternalStatsLock") + private ModemActivityInfo pullModemActivityInfoLocked() { + ITelephony tm = ITelephony.Stub.asInterface(ServiceManager.getService( + Context.TELEPHONY_SERVICE)); + try { + if (tm != null) { + ModemActivityInfo info = tm.getModemActivityInfo(); + if (info == null || info.isValid()) { + return info; + } + Slog.wtf(TAG, "Modem activity info is invalid: " + info); + } + } catch (RemoteException e) { + // Nothing to do. + } + return null; + } + /** * Fetches data from external sources (WiFi controller, bluetooth chipset) and updates * batterystats with that information. @@ -1358,6 +1378,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub wifiEnergyInfo = pullWifiEnergyInfoLocked(); } + ModemActivityInfo modemActivityInfo = null; + if ((updateFlags & UPDATE_RADIO) != 0) { + modemActivityInfo = pullModemActivityInfoLocked(); + } + BluetoothActivityEnergyInfo bluetoothEnergyInfo = null; if ((updateFlags & UPDATE_BT) != 0) { // We only pull bluetooth stats when we have to, as we are not distributing its @@ -1379,7 +1404,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } if ((updateFlags & UPDATE_RADIO) != 0) { - mStats.updateMobileRadioStateLocked(elapsedRealtime); + mStats.updateMobileRadioStateLocked(elapsedRealtime, modemActivityInfo); } if ((updateFlags & UPDATE_WIFI) != 0) { diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java index ea96e7cbaadf..c65e8bac42af 100644 --- a/telephony/java/android/telephony/ModemActivityInfo.java +++ b/telephony/java/android/telephony/ModemActivityInfo.java @@ -58,6 +58,7 @@ public class ModemActivityInfo implements Parcelable { return "ModemActivityInfo{" + " mTimestamp=" + mTimestamp + " mSleepTimeMs=" + mSleepTimeMs + + " mIdleTimeMs=" + mIdleTimeMs + " mTxTimeMs[]=" + Arrays.toString(mTxTimeMs) + " mRxTimeMs=" + mRxTimeMs + " mEnergyUsed=" + mEnergyUsed @@ -153,7 +154,7 @@ public class ModemActivityInfo implements Parcelable { for (int i = 0; i < TX_POWER_LEVELS; i++) { totalTxTimeMs += txTime[i]; } - return ((getIdleTimeMillis() != 0) || (totalTxTimeMs != 0) - || (getSleepTimeMillis() != 0) || (getIdleTimeMillis() != 0)); + return ((getIdleTimeMillis() >= 0) && (totalTxTimeMs >= 0) + && (getSleepTimeMillis() >= 0) && (getIdleTimeMillis() >= 0)); } } |