Merge "Record ModemActivityInfo and distribute power blame to apps"

This commit is contained in:
Adam Lesinski
2016-01-28 00:03:56 +00:00
committed by Android (Google) Code Review
8 changed files with 770 additions and 410 deletions

View File

@@ -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<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 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<Uid.NUM_USER_ACTIVITY_TYPES; i++) {

View File

@@ -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;
final LongSamplingCounter[] mWifiActivityCounters =
new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
/**
* 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;
/**
* 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);
}
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; 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);
}
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);
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 (DEBUG_ENERGY) {
Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
+ " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
+ " txPackets=" + 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;
}
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));
// 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);
}
}
}
}
}
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;
// Whoops, there is some radio time we can't blame on an app!
mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
mMobileRadioActiveUnknownCount.addCountLocked(1);
}
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 (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);

View File

@@ -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.

View File

@@ -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";

View File

@@ -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)

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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));
}
}