summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorAdam Lesinski <adamlesinski@google.com>2015-03-10 01:35:53 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-03-10 01:35:54 +0000
commit216f3edcb9fb0089b1bd621f88a682d7a2ebf115 (patch)
tree35389fcf25daba878870730e309b0353025882ac /core
parenta080050e4209cab9c81ae2144eed9c7c67e87f17 (diff)
parent33dac5593519a3e9eb83550faf0d55f9f0caefdf (diff)
downloadframeworks_base-216f3edcb9fb0089b1bd621f88a682d7a2ebf115.zip
frameworks_base-216f3edcb9fb0089b1bd621f88a682d7a2ebf115.tar.gz
frameworks_base-216f3edcb9fb0089b1bd621f88a682d7a2ebf115.tar.bz2
Merge "BatteryStats: Record energy info stats from WiFi and Bluetooth controllers"
Diffstat (limited to 'core')
-rw-r--r--core/java/android/os/BatteryStats.java78
-rw-r--r--core/java/com/android/internal/os/BatterySipper.java38
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHelper.java538
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java126
-rw-r--r--core/java/com/android/internal/os/PowerProfile.java27
5 files changed, 582 insertions, 225 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d03fe41..d96a0e9 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -441,14 +441,14 @@ public abstract class BatteryStats implements Parcelable {
public abstract boolean isActive();
/**
- * Returns the total time (in 1/100 sec) spent executing in user code.
+ * Returns the total time (in milliseconds) spent executing in user code.
*
* @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
*/
public abstract long getUserTime(int which);
/**
- * Returns the total time (in 1/100 sec) spent executing in system code.
+ * Returns the total time (in milliseconds) spent executing in system code.
*
* @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
*/
@@ -476,14 +476,14 @@ public abstract class BatteryStats implements Parcelable {
public abstract int getNumAnrs(int which);
/**
- * Returns the cpu time spent in microseconds while the process was in the foreground.
+ * Returns the cpu time (milliseconds) spent while the process was in the foreground.
* @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
* @return foreground cpu time in microseconds
*/
public abstract long getForegroundTime(int which);
/**
- * Returns the approximate cpu time spent in microseconds, at a certain CPU speed.
+ * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed.
* @param speedStep the index of the CPU speed. This is not the actual speed of the
* CPU.
* @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
@@ -1858,6 +1858,15 @@ public abstract class BatteryStats implements Parcelable {
public abstract long getNetworkActivityBytes(int type, int which);
public abstract long getNetworkActivityPackets(int type, int which);
+ public static final int CONTROLLER_IDLE_TIME = 0;
+ public static final int CONTROLLER_RX_TIME = 1;
+ public static final int CONTROLLER_TX_TIME = 2;
+ public static final int CONTROLLER_ENERGY = 3;
+ public static final int NUM_CONTROLLER_ACTIVITY_TYPES = CONTROLLER_ENERGY + 1;
+
+ public abstract long getBluetoothControllerActivity(int type, int which);
+ public abstract long getWifiControllerActivity(int type, int which);
+
/**
* Return the wall clock time when battery stats data collection started.
*/
@@ -3142,6 +3151,35 @@ public abstract class BatteryStats implements Parcelable {
if (!didOne) sb.append(" (no activity)");
pw.println(sb.toString());
+ final long wifiIdleTimeMs = getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
+ final long wifiRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
+ final long wifiTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
+ final long wifiTotalTimeMs = wifiIdleTimeMs + wifiRxTimeMs + wifiTxTimeMs;
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" WiFi Idle time: "); formatTimeMs(sb, wifiIdleTimeMs);
+ sb.append(" (");
+ sb.append(formatRatioLocked(wifiIdleTimeMs, wifiTotalTimeMs));
+ sb.append(")");
+ pw.println(sb.toString());
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" WiFi Rx time: "); formatTimeMs(sb, wifiRxTimeMs);
+ sb.append(" (");
+ sb.append(formatRatioLocked(wifiRxTimeMs, wifiTotalTimeMs));
+ sb.append(")");
+ pw.println(sb.toString());
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" WiFi Tx time: "); formatTimeMs(sb, wifiTxTimeMs);
+ sb.append(" (");
+ sb.append(formatRatioLocked(wifiTxTimeMs, wifiTotalTimeMs));
+ sb.append(")");
+ pw.println(sb.toString());
+
sb.setLength(0);
sb.append(prefix);
sb.append(" Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
@@ -3169,9 +3207,41 @@ public abstract class BatteryStats implements Parcelable {
sb.append(getPhoneDataConnectionCount(i, which));
sb.append("x");
}
+
if (!didOne) sb.append(" (no activity)");
pw.println(sb.toString());
+ final long bluetoothIdleTimeMs =
+ getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
+ final long bluetoothRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
+ final long bluetoothTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
+ final long bluetoothTotalTimeMs = bluetoothIdleTimeMs + bluetoothRxTimeMs +
+ bluetoothTxTimeMs;
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Bluetooth Idle time: "); formatTimeMs(sb, bluetoothIdleTimeMs);
+ sb.append(" (");
+ sb.append(formatRatioLocked(bluetoothIdleTimeMs, bluetoothTotalTimeMs));
+ sb.append(")");
+ pw.println(sb.toString());
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Bluetooth Rx time: "); formatTimeMs(sb, bluetoothRxTimeMs);
+ sb.append(" (");
+ sb.append(formatRatioLocked(bluetoothRxTimeMs, bluetoothTotalTimeMs));
+ sb.append(")");
+ pw.println(sb.toString());
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Bluetooth Tx time: "); formatTimeMs(sb, bluetoothTxTimeMs);
+ sb.append(" (");
+ sb.append(formatRatioLocked(bluetoothTxTimeMs, bluetoothTotalTimeMs));
+ sb.append(")");
+ pw.println(sb.toString());
+
pw.println();
if (which == STATS_SINCE_UNPLUGGED) {
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
index cfeca08..4cd959f 100644
--- a/core/java/com/android/internal/os/BatterySipper.java
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -26,12 +26,15 @@ public class BatterySipper implements Comparable<BatterySipper> {
public double value;
public double[] values;
public DrainType drainType;
+
+ // Measured in milliseconds.
public long usageTime;
public long cpuTime;
public long gpsTime;
public long wifiRunningTime;
public long cpuFgTime;
public long wakeLockTime;
+
public long mobileRxPackets;
public long mobileTxPackets;
public long mobileActive;
@@ -48,6 +51,14 @@ public class BatterySipper implements Comparable<BatterySipper> {
public String[] mPackages;
public String packageWithHighestDrain;
+ // Measured in mAh (milli-ampere per hour).
+ public double wifiPower;
+ public double cpuPower;
+ public double wakeLockPower;
+ public double mobileRadioPower;
+ public double gpsPower;
+ public double sensorPower;
+
public enum DrainType {
IDLE,
CELL,
@@ -107,4 +118,31 @@ public class BatterySipper implements Comparable<BatterySipper> {
}
return uidObj.getUid();
}
+
+ /**
+ * Add stats from other to this BatterySipper.
+ */
+ public void add(BatterySipper other) {
+ cpuTime += other.cpuTime;
+ gpsTime += other.gpsTime;
+ wifiRunningTime += other.wifiRunningTime;
+ cpuFgTime += other.cpuFgTime;
+ wakeLockTime += other.wakeLockTime;
+ mobileRxPackets += other.mobileRxPackets;
+ mobileTxPackets += other.mobileTxPackets;
+ mobileActive += other.mobileActive;
+ mobileActiveCount += other.mobileActiveCount;
+ wifiRxPackets += other.wifiRxPackets;
+ wifiTxPackets += other.wifiTxPackets;
+ mobileRxBytes += other.mobileRxBytes;
+ mobileTxBytes += other.mobileTxBytes;
+ wifiRxBytes += other.wifiRxBytes;
+ wifiTxBytes += other.wifiTxBytes;
+ wifiPower += other.wifiPower;
+ gpsPower += other.gpsPower;
+ cpuPower += other.cpuPower;
+ sensorPower += other.sensorPower;
+ mobileRadioPower += other.mobileRadioPower;
+ wakeLockPower += other.wakeLockPower;
+ }
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 5d73be0..d3611bf 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -344,6 +344,7 @@ public final class BatteryStatsHelper {
mMobilemsppList.add(bs);
}
}
+
for (int i=0; i<mUserSippers.size(); i++) {
List<BatterySipper> user = mUserSippers.valueAt(i);
for (int j=0; j<user.size(); j++) {
@@ -389,8 +390,8 @@ public final class BatteryStatsHelper {
private void processAppUsage(SparseArray<UserHandle> asUsers) {
final boolean forAllUsers = (asUsers.get(UserHandle.USER_ALL) != null);
- SensorManager sensorManager = (SensorManager) mContext.getSystemService(
- Context.SENSOR_SERVICE);
+ final SensorManager sensorManager =
+ (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
final int which = mStatsType;
final int speedSteps = mPowerProfile.getNumSpeedSteps();
final double[] powerCpuNormal = new double[speedSteps];
@@ -401,238 +402,317 @@ public final class BatteryStatsHelper {
final double mobilePowerPerPacket = getMobilePowerPerPacket();
final double mobilePowerPerMs = getMobilePowerPerMs();
final double wifiPowerPerPacket = getWifiPowerPerPacket();
- long appWakelockTimeUs = 0;
+ long totalAppWakelockTimeUs = 0;
BatterySipper osApp = null;
mStatsPeriod = mTypeBatteryRealtime;
- SparseArray<? extends Uid> uidStats = mStats.getUidStats();
+
+ final ArrayList<BatterySipper> appList = new ArrayList<>();
+
+ // Max values used to normalize later.
+ double maxWifiPower = 0;
+ double maxCpuPower = 0;
+ double maxWakeLockPower = 0;
+ double maxMobileRadioPower = 0;
+ double maxGpsPower = 0;
+ double maxSensorPower = 0;
+
+ final SparseArray<? extends Uid> uidStats = mStats.getUidStats();
final int NU = uidStats.size();
for (int iu = 0; iu < NU; iu++) {
- Uid u = uidStats.valueAt(iu);
- double p; // in mAs
- double power = 0; // in mAs
- double highestDrain = 0;
- String packageWithHighestDrain = null;
- Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
- long cpuTime = 0;
- long cpuFgTime = 0;
- long wakelockTime = 0;
- long gpsTime = 0;
+ final Uid u = uidStats.valueAt(iu);
+ final BatterySipper app = new BatterySipper(
+ BatterySipper.DrainType.APP, u, new double[]{0});
+
+ final Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
if (processStats.size() > 0) {
- // Process CPU time
+ // Process CPU time.
+
+ // Keep track of the package with highest drain.
+ double highestDrain = 0;
+
for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
: processStats.entrySet()) {
Uid.Proc ps = ent.getValue();
- final long userTime = ps.getUserTime(which);
- final long systemTime = ps.getSystemTime(which);
- final long foregroundTime = ps.getForegroundTime(which);
- cpuFgTime += foregroundTime;
- final long tmpCpuTime = userTime + systemTime;
- int totalTimeAtSpeeds = 0;
- // Get the total first
+ app.cpuFgTime += ps.getForegroundTime(which);
+ final long totalCpuTime = ps.getUserTime(which) + ps.getSystemTime(which);
+ app.cpuTime += totalCpuTime;
+
+ // Calculate the total CPU time spent at the various speed steps.
+ long totalTimeAtSpeeds = 0;
for (int step = 0; step < speedSteps; step++) {
cpuSpeedStepTimes[step] = ps.getTimeAtCpuSpeedStep(step, which);
totalTimeAtSpeeds += cpuSpeedStepTimes[step];
}
- if (totalTimeAtSpeeds == 0) totalTimeAtSpeeds = 1;
- // Then compute the ratio of time spent at each speed
- double processPower = 0;
+ totalTimeAtSpeeds = Math.max(totalTimeAtSpeeds, 1);
+
+ // Then compute the ratio of time spent at each speed and figure out
+ // the total power consumption.
+ double cpuPower = 0;
for (int step = 0; step < speedSteps; step++) {
- double ratio = (double) cpuSpeedStepTimes[step] / totalTimeAtSpeeds;
- if (DEBUG && ratio != 0) Log.d(TAG, "UID " + u.getUid() + ": CPU step #"
- + step + " ratio=" + makemAh(ratio) + " power="
- + makemAh(ratio*tmpCpuTime*powerCpuNormal[step] / (60*60*1000)));
- processPower += ratio * tmpCpuTime * powerCpuNormal[step];
+ final double ratio = (double) cpuSpeedStepTimes[step] / totalTimeAtSpeeds;
+ final double cpuSpeedStepPower =
+ ratio * totalCpuTime * powerCpuNormal[step];
+ if (DEBUG && ratio != 0) {
+ Log.d(TAG, "UID " + u.getUid() + ": CPU step #"
+ + step + " ratio=" + makemAh(ratio) + " power="
+ + makemAh(cpuSpeedStepPower / (60 * 60 * 1000)));
+ }
+ cpuPower += cpuSpeedStepPower;
}
- cpuTime += tmpCpuTime;
- if (DEBUG && processPower != 0) {
+
+ if (DEBUG && cpuPower != 0) {
Log.d(TAG, String.format("process %s, cpu power=%s",
- ent.getKey(), makemAh(processPower / (60*60*1000))));
+ ent.getKey(), makemAh(cpuPower / (60 * 60 * 1000))));
}
- power += processPower;
- if (packageWithHighestDrain == null
- || packageWithHighestDrain.startsWith("*")) {
- highestDrain = processPower;
- packageWithHighestDrain = ent.getKey();
- } else if (highestDrain < processPower
- && !ent.getKey().startsWith("*")) {
- highestDrain = processPower;
- packageWithHighestDrain = ent.getKey();
+ app.cpuPower += cpuPower;
+
+ // Each App can have multiple packages and with multiple running processes.
+ // Keep track of the package who's process has the highest drain.
+ if (app.packageWithHighestDrain == null ||
+ app.packageWithHighestDrain.startsWith("*")) {
+ highestDrain = cpuPower;
+ app.packageWithHighestDrain = ent.getKey();
+ } else if (highestDrain < cpuPower && !ent.getKey().startsWith("*")) {
+ highestDrain = cpuPower;
+ app.packageWithHighestDrain = ent.getKey();
}
}
}
- if (cpuFgTime > cpuTime) {
- if (DEBUG && cpuFgTime > cpuTime + 10000) {
+
+ // Ensure that the CPU times make sense.
+ if (app.cpuFgTime > app.cpuTime) {
+ if (DEBUG && app.cpuFgTime > app.cpuTime + 10000) {
Log.d(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
}
- cpuTime = cpuFgTime; // Statistics may not have been gathered yet.
+
+ // Statistics may not have been gathered yet.
+ app.cpuTime = app.cpuFgTime;
}
- power /= (60*60*1000);
+
+ // Convert the CPU power to mAh
+ app.cpuPower /= (60 * 60 * 1000);
+ maxCpuPower = Math.max(maxCpuPower, app.cpuPower);
// Process wake lock usage
- Map<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats = u.getWakelockStats();
+ final Map<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats =
+ u.getWakelockStats();
+ long wakeLockTimeUs = 0;
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> wakelockEntry
: wakelockStats.entrySet()) {
- Uid.Wakelock wakelock = wakelockEntry.getValue();
+ final Uid.Wakelock wakelock = wakelockEntry.getValue();
+
// Only care about partial wake locks since full wake locks
// are canceled when the user turns the screen off.
BatteryStats.Timer timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
if (timer != null) {
- wakelockTime += timer.getTotalTimeLocked(mRawRealtime, which);
+ wakeLockTimeUs += timer.getTotalTimeLocked(mRawRealtime, which);
}
}
- appWakelockTimeUs += wakelockTime;
- wakelockTime /= 1000; // convert to millis
-
- // Add cost of holding a wake lock
- p = (wakelockTime
- * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / (60*60*1000);
- if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": wake "
- + wakelockTime + " power=" + makemAh(p));
- power += p;
+ app.wakeLockTime = wakeLockTimeUs / 1000; // convert to millis
+ totalAppWakelockTimeUs += wakeLockTimeUs;
+
+ // Add cost of holding a wake lock.
+ app.wakeLockPower = (app.wakeLockTime *
+ mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / (60 * 60 * 1000);
+ if (DEBUG && app.wakeLockPower != 0) {
+ Log.d(TAG, "UID " + u.getUid() + ": wake "
+ + app.wakeLockTime + " power=" + makemAh(app.wakeLockPower));
+ }
+ maxWakeLockPower = Math.max(maxWakeLockPower, app.wakeLockPower);
- // Add cost of mobile traffic
- final long mobileRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, mStatsType);
- final long mobileTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, mStatsType);
- final long mobileRxB = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, mStatsType);
- final long mobileTxB = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, mStatsType);
+ // Add cost of mobile traffic.
final long mobileActive = u.getMobileRadioActiveTime(mStatsType);
+ app.mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, mStatsType);
+ app.mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, mStatsType);
+ app.mobileActive = mobileActive / 1000;
+ app.mobileActiveCount = u.getMobileRadioActiveCount(mStatsType);
+ app.mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, mStatsType);
+ app.mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, mStatsType);
+
if (mobileActive > 0) {
// We are tracking when the radio is up, so can use the active time to
// determine power use.
mAppMobileActive += mobileActive;
- p = (mobilePowerPerMs * mobileActive) / 1000;
+ app.mobileRadioPower = (mobilePowerPerMs * mobileActive) / 1000;
} else {
// We are not tracking when the radio is up, so must approximate power use
// based on the number of packets.
- p = (mobileRx + mobileTx) * mobilePowerPerPacket;
+ app.mobileRadioPower = (app.mobileRxPackets + app.mobileTxPackets)
+ * mobilePowerPerPacket;
}
- if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": mobile packets "
- + (mobileRx+mobileTx) + " active time " + mobileActive
- + " power=" + makemAh(p));
- power += p;
+ if (DEBUG && app.mobileRadioPower != 0) {
+ Log.d(TAG, "UID " + u.getUid() + ": mobile packets "
+ + (app.mobileRxPackets + app.mobileTxPackets)
+ + " active time " + mobileActive
+ + " power=" + makemAh(app.mobileRadioPower));
+ }
+ maxMobileRadioPower = Math.max(maxMobileRadioPower, app.mobileRadioPower);
// Add cost of wifi traffic
- final long wifiRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, mStatsType);
- final long wifiTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, mStatsType);
- final long wifiRxB = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, mStatsType);
- final long wifiTxB = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, mStatsType);
- p = (wifiRx + wifiTx) * wifiPowerPerPacket;
- if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": wifi packets "
- + (mobileRx+mobileTx) + " power=" + makemAh(p));
- power += p;
+ app.wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, mStatsType);
+ app.wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, mStatsType);
+ app.wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, mStatsType);
+ app.wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, mStatsType);
+
+ final double wifiPacketPower = (app.wifiRxPackets + app.wifiTxPackets)
+ * wifiPowerPerPacket;
+ if (DEBUG && wifiPacketPower != 0) {
+ Log.d(TAG, "UID " + u.getUid() + ": wifi packets "
+ + (app.wifiRxPackets + app.wifiTxPackets)
+ + " power=" + makemAh(wifiPacketPower));
+ }
// Add cost of keeping WIFI running.
- long wifiRunningTimeMs = u.getWifiRunningTime(mRawRealtime, which) / 1000;
- mAppWifiRunning += wifiRunningTimeMs;
- p = (wifiRunningTimeMs
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / (60*60*1000);
- if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": wifi running "
- + wifiRunningTimeMs + " power=" + makemAh(p));
- power += p;
+ app.wifiRunningTime = u.getWifiRunningTime(mRawRealtime, which) / 1000;
+ mAppWifiRunning += app.wifiRunningTime;
+
+ final double wifiLockPower = (app.wifiRunningTime
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / (60 * 60 * 1000);
+ if (DEBUG && wifiLockPower != 0) {
+ Log.d(TAG, "UID " + u.getUid() + ": wifi running "
+ + app.wifiRunningTime + " power=" + makemAh(wifiLockPower));
+ }
// Add cost of WIFI scans
- long wifiScanTimeMs = u.getWifiScanTime(mRawRealtime, which) / 1000;
- p = (wifiScanTimeMs
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN)) / (60*60*1000);
- if (DEBUG) Log.d(TAG, "UID " + u.getUid() + ": wifi scan " + wifiScanTimeMs
- + " power=" + makemAh(p));
- power += p;
+ final long wifiScanTimeMs = u.getWifiScanTime(mRawRealtime, which) / 1000;
+ final double wifiScanPower = (wifiScanTimeMs
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN))
+ / (60 * 60 * 1000);
+ if (DEBUG && wifiScanPower != 0) {
+ Log.d(TAG, "UID " + u.getUid() + ": wifi scan " + wifiScanTimeMs
+ + " power=" + makemAh(wifiScanPower));
+ }
+
+ // Add cost of WIFI batch scans.
+ double wifiBatchScanPower = 0;
for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
- long batchScanTimeMs = u.getWifiBatchedScanTime(bin, mRawRealtime, which) / 1000;
- p = ((batchScanTimeMs
+ final long batchScanTimeMs =
+ u.getWifiBatchedScanTime(bin, mRawRealtime, which) / 1000;
+ final double batchScanPower = ((batchScanTimeMs
* mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, bin))
- ) / (60*60*1000);
- if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": wifi batched scan # " + bin
- + " time=" + batchScanTimeMs + " power=" + makemAh(p));
- power += p;
+ ) / (60 * 60 * 1000);
+ if (DEBUG && batchScanPower != 0) {
+ Log.d(TAG, "UID " + u.getUid() + ": wifi batched scan # " + bin
+ + " time=" + batchScanTimeMs + " power=" + makemAh(batchScanPower));
+ }
+ wifiBatchScanPower += batchScanPower;
}
+ // Add up all the WiFi costs.
+ app.wifiPower = wifiPacketPower + wifiLockPower + wifiScanPower + wifiBatchScanPower;
+ maxWifiPower = Math.max(maxWifiPower, app.wifiPower);
+
// Process Sensor usage
- SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
- int NSE = sensorStats.size();
- for (int ise=0; ise<NSE; ise++) {
- Uid.Sensor sensor = sensorStats.valueAt(ise);
- int sensorHandle = sensorStats.keyAt(ise);
- BatteryStats.Timer timer = sensor.getSensorTime();
- long sensorTime = timer.getTotalTimeLocked(mRawRealtime, which) / 1000;
- double multiplier = 0;
+ final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
+ final int NSE = sensorStats.size();
+ for (int ise = 0; ise < NSE; ise++) {
+ final Uid.Sensor sensor = sensorStats.valueAt(ise);
+ final int sensorHandle = sensorStats.keyAt(ise);
+ final BatteryStats.Timer timer = sensor.getSensorTime();
+ final long sensorTime = timer.getTotalTimeLocked(mRawRealtime, which) / 1000;
+ double sensorPower = 0;
switch (sensorHandle) {
case Uid.Sensor.GPS:
- multiplier = mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_ON);
- gpsTime = sensorTime;
+ app.gpsTime = sensorTime;
+ app.gpsPower = (app.gpsTime
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_ON))
+ / (60 * 60 * 1000);
+ sensorPower = app.gpsPower;
+ maxGpsPower = Math.max(maxGpsPower, app.gpsPower);
break;
default:
List<Sensor> sensorList = sensorManager.getSensorList(
android.hardware.Sensor.TYPE_ALL);
for (android.hardware.Sensor s : sensorList) {
if (s.getHandle() == sensorHandle) {
- multiplier = s.getPower();
+ sensorPower = (sensorTime * s.getPower()) / (60 * 60 * 1000);
+ app.sensorPower += sensorPower;
break;
}
}
}
- p = (multiplier * sensorTime) / (60*60*1000);
- if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": sensor #" + sensorHandle
- + " time=" + sensorTime + " power=" + makemAh(p));
- power += p;
+ if (DEBUG && sensorPower != 0) {
+ Log.d(TAG, "UID " + u.getUid() + ": sensor #" + sensorHandle
+ + " time=" + sensorTime + " power=" + makemAh(sensorPower));
+ }
}
+ maxSensorPower = Math.max(maxSensorPower, app.sensorPower);
- if (DEBUG && power != 0) Log.d(TAG, String.format("UID %d: total power=%s",
- u.getUid(), makemAh(power)));
-
- // Add the app to the list if it is consuming power
- final int userId = UserHandle.getUserId(u.getUid());
- if (power != 0 || u.getUid() == 0) {
- BatterySipper app = new BatterySipper(BatterySipper.DrainType.APP, u,
- new double[] {power});
- app.cpuTime = cpuTime;
- app.gpsTime = gpsTime;
- app.wifiRunningTime = wifiRunningTimeMs;
- app.cpuFgTime = cpuFgTime;
- app.wakeLockTime = wakelockTime;
- app.mobileRxPackets = mobileRx;
- app.mobileTxPackets = mobileTx;
- app.mobileActive = mobileActive / 1000;
- app.mobileActiveCount = u.getMobileRadioActiveCount(mStatsType);
- app.wifiRxPackets = wifiRx;
- app.wifiTxPackets = wifiTx;
- app.mobileRxBytes = mobileRxB;
- app.mobileTxBytes = mobileTxB;
- app.wifiRxBytes = wifiRxB;
- app.wifiTxBytes = wifiTxB;
- app.packageWithHighestDrain = packageWithHighestDrain;
- if (u.getUid() == Process.WIFI_UID) {
- mWifiSippers.add(app);
- mWifiPower += power;
- } else if (u.getUid() == Process.BLUETOOTH_UID) {
- mBluetoothSippers.add(app);
- mBluetoothPower += power;
- } else if (!forAllUsers && asUsers.get(userId) == null
- && UserHandle.getAppId(u.getUid()) >= Process.FIRST_APPLICATION_UID) {
- List<BatterySipper> list = mUserSippers.get(userId);
- if (list == null) {
- list = new ArrayList<BatterySipper>();
- mUserSippers.put(userId, list);
- }
- list.add(app);
- if (power != 0) {
- Double userPower = mUserPower.get(userId);
- if (userPower == null) {
- userPower = power;
- } else {
- userPower += power;
- }
- mUserPower.put(userId, userPower);
- }
- } else {
- mUsageList.add(app);
- if (power > mMaxPower) mMaxPower = power;
- if (power > mMaxRealPower) mMaxRealPower = power;
- mComputedPower += power;
+ final double totalUnnormalizedPower = app.cpuPower + app.wifiPower + app.wakeLockPower
+ + app.mobileRadioPower + app.gpsPower + app.sensorPower;
+ if (DEBUG && totalUnnormalizedPower != 0) {
+ Log.d(TAG, String.format("UID %d: total power=%s",
+ u.getUid(), makemAh(totalUnnormalizedPower)));
+ }
+
+ // Add the app to the list if it is consuming power.
+ if (totalUnnormalizedPower != 0 || u.getUid() == 0) {
+ appList.add(app);
+ }
+ }
+
+ // Fetch real power consumption from hardware.
+ double actualTotalWifiPower = 0.0;
+ if (mStats.getWifiControllerActivity(BatteryStats.CONTROLLER_ENERGY, mStatsType) != 0) {
+ final double kDefaultVoltage = 3.36;
+ final long energy = mStats.getWifiControllerActivity(
+ BatteryStats.CONTROLLER_ENERGY, mStatsType);
+ final double voltage = mPowerProfile.getAveragePowerOrDefault(
+ PowerProfile.OPERATING_VOLTAGE_WIFI, kDefaultVoltage);
+ actualTotalWifiPower = energy / (voltage * 1000*60*60);
+ }
+
+ final int appCount = appList.size();
+ for (int i = 0; i < appCount; i++) {
+ // Normalize power where possible.
+ final BatterySipper app = appList.get(i);
+ if (actualTotalWifiPower != 0) {
+ app.wifiPower = (app.wifiPower / maxWifiPower) * actualTotalWifiPower;
+ }
+
+ // Assign the final power consumption here.
+ final double power = app.wifiPower + app.cpuPower + app.wakeLockPower
+ + app.mobileRadioPower + app.gpsPower + app.sensorPower;
+ app.values[0] = app.value = power;
+
+ //
+ // Add the app to the app list, WiFi, Bluetooth, etc, or into "Other Users" list.
+ //
+
+ final int uid = app.getUid();
+ final int userId = UserHandle.getUserId(uid);
+ if (uid == Process.WIFI_UID) {
+ mWifiSippers.add(app);
+ mWifiPower += power;
+ } else if (uid == Process.BLUETOOTH_UID) {
+ mBluetoothSippers.add(app);
+ mBluetoothPower += power;
+ } else if (!forAllUsers && asUsers.get(userId) == null
+ && UserHandle.getAppId(uid) >= Process.FIRST_APPLICATION_UID) {
+ // We are told to just report this user's apps as one large entry.
+ List<BatterySipper> list = mUserSippers.get(userId);
+ if (list == null) {
+ list = new ArrayList<>();
+ mUserSippers.put(userId, list);
}
- if (u.getUid() == 0) {
- osApp = app;
+ list.add(app);
+
+ Double userPower = mUserPower.get(userId);
+ if (userPower == null) {
+ userPower = power;
+ } else {
+ userPower += power;
}
+ mUserPower.put(userId, userPower);
+ } else {
+ mUsageList.add(app);
+ if (power > mMaxPower) mMaxPower = power;
+ if (power > mMaxRealPower) mMaxRealPower = power;
+ mComputedPower += power;
+ }
+
+ if (uid == 0) {
+ osApp = app;
}
}
@@ -641,7 +721,7 @@ public final class BatteryStatsHelper {
// this remainder to the OS, if possible.
if (osApp != null) {
long wakeTimeMillis = mBatteryUptime / 1000;
- wakeTimeMillis -= (appWakelockTimeUs / 1000)
+ wakeTimeMillis -= (totalAppWakelockTimeUs / 1000)
+ (mStats.getScreenOnTime(mRawRealtime, which) / 1000);
if (wakeTimeMillis > 0) {
double power = (wakeTimeMillis
@@ -741,46 +821,11 @@ public final class BatteryStatsHelper {
for (int i=0; i<from.size(); i++) {
BatterySipper wbs = from.get(i);
if (DEBUG) Log.d(TAG, tag + " adding sipper " + wbs + ": cpu=" + wbs.cpuTime);
- bs.cpuTime += wbs.cpuTime;
- bs.gpsTime += wbs.gpsTime;
- bs.wifiRunningTime += wbs.wifiRunningTime;
- bs.cpuFgTime += wbs.cpuFgTime;
- bs.wakeLockTime += wbs.wakeLockTime;
- bs.mobileRxPackets += wbs.mobileRxPackets;
- bs.mobileTxPackets += wbs.mobileTxPackets;
- bs.mobileActive += wbs.mobileActive;
- bs.mobileActiveCount += wbs.mobileActiveCount;
- bs.wifiRxPackets += wbs.wifiRxPackets;
- bs.wifiTxPackets += wbs.wifiTxPackets;
- bs.mobileRxBytes += wbs.mobileRxBytes;
- bs.mobileTxBytes += wbs.mobileTxBytes;
- bs.wifiRxBytes += wbs.wifiRxBytes;
- bs.wifiTxBytes += wbs.wifiTxBytes;
+ bs.add(wbs);
}
bs.computeMobilemspp();
}
- private void addWiFiUsage() {
- long onTimeMs = mStats.getWifiOnTime(mRawRealtime, mStatsType) / 1000;
- long runningTimeMs = mStats.getGlobalWifiRunningTime(mRawRealtime, mStatsType) / 1000;
- if (DEBUG) Log.d(TAG, "WIFI runningTime=" + runningTimeMs
- + " app runningTime=" + mAppWifiRunning);
- runningTimeMs -= mAppWifiRunning;
- if (runningTimeMs < 0) runningTimeMs = 0;
- double wifiPower = (onTimeMs * 0 /* TODO */
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)
- + runningTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON))
- / (60*60*1000);
- if (DEBUG && wifiPower != 0) {
- Log.d(TAG, "Wifi: time=" + runningTimeMs + " power=" + makemAh(wifiPower));
- }
- if ((wifiPower+mWifiPower) != 0) {
- BatterySipper bs = addEntry(BatterySipper.DrainType.WIFI, runningTimeMs,
- wifiPower + mWifiPower);
- aggregateSippers(bs, mWifiSippers, "WIFI");
- }
- }
-
private void addIdleUsage() {
long idleTimeMs = (mTypeBatteryRealtime
- mStats.getScreenOnTime(mRawRealtime, mStatsType)) / 1000;
@@ -794,24 +839,81 @@ public final class BatteryStatsHelper {
}
}
- private void addBluetoothUsage() {
- long btOnTimeMs = mStats.getBluetoothOnTime(mRawRealtime, mStatsType) / 1000;
- double btPower = btOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON)
- / (60*60*1000);
- if (DEBUG && btPower != 0) {
- Log.d(TAG, "Bluetooth: time=" + btOnTimeMs + " power=" + makemAh(btPower));
+ /**
+ * We do per-app blaming of WiFi activity. If energy info is reported from the controller,
+ * then only the WiFi process gets blamed here since we normalize power calculations and
+ * assign all the power drain to apps. If energy info is not reported, we attribute the
+ * difference between total running time of WiFi for all apps and the actual running time
+ * of WiFi to the WiFi subsystem.
+ */
+ private void addWiFiUsage() {
+ final long idleTimeMs = mStats.getWifiControllerActivity(
+ BatteryStats.CONTROLLER_IDLE_TIME, mStatsType);
+ final long txTimeMs = mStats.getWifiControllerActivity(
+ BatteryStats.CONTROLLER_TX_TIME, mStatsType);
+ final long rxTimeMs = mStats.getWifiControllerActivity(
+ BatteryStats.CONTROLLER_RX_TIME, mStatsType);
+ final long energy = mStats.getWifiControllerActivity(
+ BatteryStats.CONTROLLER_ENERGY, mStatsType);
+ final long totalTimeRunning = idleTimeMs + txTimeMs + rxTimeMs;
+
+ double powerDrain = 0;
+ if (energy == 0 && totalTimeRunning > 0) {
+ // Energy is not reported, which means we may have left over power drain not attributed
+ // to any app. Assign this power to the WiFi app.
+ // TODO(adamlesinski): This mimics the old behavior. However, mAppWifiRunningTime
+ // is the accumulation of the time each app kept the WiFi chip on. Multiple apps
+ // can do this at the same time, so these times do not add up to the total time
+ // the WiFi chip was on. Consider normalizing the time spent running and calculating
+ // power from that? Normalizing the times will assign a weight to each app which
+ // should better represent power usage.
+ powerDrain = ((totalTimeRunning - mAppWifiRunning)
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / (60*60*1000);
}
- int btPingCount = mStats.getBluetoothPingCount();
- double pingPower = (btPingCount
- * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_AT_CMD))
- / (60*60*1000);
- if (DEBUG && pingPower != 0) {
- Log.d(TAG, "Bluetooth ping: count=" + btPingCount + " power=" + makemAh(pingPower));
+
+ if (DEBUG && powerDrain != 0) {
+ Log.d(TAG, "Wifi active: time=" + (txTimeMs + rxTimeMs)
+ + " power=" + makemAh(powerDrain));
+ }
+
+ // TODO(adamlesinski): mWifiPower is already added as a BatterySipper...
+ // Are we double counting here?
+ final double power = mWifiPower + powerDrain;
+ if (power > 0) {
+ BatterySipper bs = addEntry(BatterySipper.DrainType.WIFI, totalTimeRunning, power);
+ aggregateSippers(bs, mWifiSippers, "WIFI");
}
- btPower += pingPower;
- if ((btPower+mBluetoothPower) != 0) {
- BatterySipper bs = addEntry(BatterySipper.DrainType.BLUETOOTH, btOnTimeMs,
- btPower + mBluetoothPower);
+ }
+
+ /**
+ * Bluetooth usage is not attributed to any apps yet, so the entire blame goes to the
+ * Bluetooth Category.
+ */
+ private void addBluetoothUsage() {
+ final double kDefaultVoltage = 3.36;
+ final long idleTimeMs = mStats.getBluetoothControllerActivity(
+ BatteryStats.CONTROLLER_IDLE_TIME, mStatsType);
+ final long txTimeMs = mStats.getBluetoothControllerActivity(
+ BatteryStats.CONTROLLER_TX_TIME, mStatsType);
+ final long rxTimeMs = mStats.getBluetoothControllerActivity(
+ BatteryStats.CONTROLLER_RX_TIME, mStatsType);
+ final long energy = mStats.getBluetoothControllerActivity(
+ BatteryStats.CONTROLLER_ENERGY, mStatsType);
+ final double voltage = mPowerProfile.getAveragePowerOrDefault(
+ PowerProfile.OPERATING_VOLTAGE_BLUETOOTH, kDefaultVoltage);
+
+ // energy is measured in mA * V * ms, and we are interested in mAh
+ final double powerDrain = energy / (voltage * 60*60*1000);
+
+ if (DEBUG && powerDrain != 0) {
+ Log.d(TAG, "Bluetooth active: time=" + (txTimeMs + rxTimeMs)
+ + " power=" + makemAh(powerDrain));
+ }
+
+ final long totalTime = idleTimeMs + txTimeMs + rxTimeMs;
+ final double power = mBluetoothPower + powerDrain;
+ if (power > 0) {
+ BatterySipper bs = addEntry(BatterySipper.DrainType.BLUETOOTH, totalTime, power);
aggregateSippers(bs, mBluetoothSippers, "Bluetooth");
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index e02b959..f9b1ca1 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -20,11 +20,15 @@ import static android.net.NetworkStats.UID_ALL;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
import android.app.ActivityManager;
+import android.bluetooth.BluetoothActivityEnergyInfo;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkStats;
+import android.net.wifi.IWifiManager;
+import android.net.wifi.WifiActivityEnergyInfo;
import android.net.wifi.WifiManager;
import android.os.BadParcelableException;
import android.os.BatteryManager;
@@ -38,6 +42,8 @@ import android.os.Parcel;
import android.os.ParcelFormatException;
import android.os.Parcelable;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.WorkSource;
@@ -332,6 +338,12 @@ public final class BatteryStatsImpl extends BatteryStats {
final LongSamplingCounter[] mNetworkPacketActivityCounters =
new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
+ final LongSamplingCounter[] mBluetoothActivityCounters =
+ new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
+
+ final LongSamplingCounter[] mWifiActivityCounters =
+ new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
+
boolean mWifiOn;
StopwatchTimer mWifiOnTimer;
@@ -4307,6 +4319,20 @@ public final class BatteryStatsImpl extends BatteryStats {
return mBluetoothStateTimer[bluetoothState].getCountLocked(which);
}
+ @Override public long getBluetoothControllerActivity(int type, int which) {
+ if (type >= 0 && type < mBluetoothActivityCounters.length) {
+ return mBluetoothActivityCounters[type].getCountLocked(which);
+ }
+ return 0;
+ }
+
+ @Override public long getWifiControllerActivity(int type, int which) {
+ if (type >= 0 && type < mWifiActivityCounters.length) {
+ return mWifiActivityCounters[type].getCountLocked(which);
+ }
+ return 0;
+ }
+
@Override public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
}
@@ -6652,6 +6678,10 @@ public final class BatteryStatsImpl extends BatteryStats {
mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
}
+ for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
+ mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
+ mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
+ }
mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase);
mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase);
mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
@@ -7239,6 +7269,10 @@ public final class BatteryStatsImpl extends BatteryStats {
for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
mBluetoothStateTimer[i].reset(false);
}
+ for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
+ mBluetoothActivityCounters[i].reset(false);
+ mWifiActivityCounters[i].reset(false);
+ }
mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
for (int i=0; i<mUidStats.size(); i++) {
@@ -7325,6 +7359,9 @@ public final class BatteryStatsImpl extends BatteryStats {
public void pullPendingStateUpdatesLocked() {
updateKernelWakelocksLocked();
updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
+ // TODO(adamlesinski): enable when bluedroid stops deadlocking. b/19248786
+ // updateBluetoothControllerActivityLocked();
+ updateWifiControllerActivityLocked();
if (mOnBatteryInternal) {
final boolean screenOn = mScreenState == Display.STATE_ON;
updateDischargeScreenLevelsLocked(screenOn, screenOn);
@@ -7761,6 +7798,65 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ private void updateBluetoothControllerActivityLocked() {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter == null) {
+ return;
+ }
+
+ // We read the data even if we are not on battery. Each read clears
+ // the previous data, so we must always read to make sure the
+ // data is for the current interval.
+ BluetoothActivityEnergyInfo info = adapter.getControllerActivityEnergyInfo(
+ BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED);
+ if (info == null || !info.isValid() || !mOnBatteryInternal) {
+ // Bad info or we are not on battery.
+ return;
+ }
+
+ mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
+ info.getControllerRxTimeMillis());
+ mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
+ info.getControllerTxTimeMillis());
+ mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
+ info.getControllerIdleTimeMillis());
+ mBluetoothActivityCounters[CONTROLLER_ENERGY].addCountLocked(
+ info.getControllerEnergyUsed());
+ }
+
+ private void updateWifiControllerActivityLocked() {
+ IWifiManager wifiManager = IWifiManager.Stub.asInterface(
+ ServiceManager.getService(Context.WIFI_SERVICE));
+ if (wifiManager == null) {
+ return;
+ }
+
+ WifiActivityEnergyInfo info;
+ try {
+ // We read the data even if we are not on battery. Each read clears
+ // the previous data, so we must always read to make sure the
+ // data is for the current interval.
+ info = wifiManager.reportActivityInfo();
+ } catch (RemoteException e) {
+ // Nothing to report, WiFi is dead.
+ return;
+ }
+
+ if (info == null || !info.isValid() || !mOnBatteryInternal) {
+ // Bad info or we are not on battery.
+ return;
+ }
+
+ mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
+ info.getControllerRxTimeMillis());
+ mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
+ info.getControllerTxTimeMillis());
+ mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
+ info.getControllerIdleTimeMillis());
+ mWifiActivityCounters[CONTROLLER_ENERGY].addCountLocked(
+ info.getControllerEnergyUsed());
+ }
+
public long getAwakeTimeBattery() {
return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
}
@@ -8475,6 +8571,15 @@ public final class BatteryStatsImpl extends BatteryStats {
for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
mBluetoothStateTimer[i].readSummaryFromParcelLocked(in);
}
+
+ for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
+ mBluetoothActivityCounters[i].readSummaryFromParcelLocked(in);
+ }
+
+ for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
+ mWifiActivityCounters[i].readSummaryFromParcelLocked(in);
+ }
+
mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
mFlashlightOn = false;
mFlashlightOnTimer.readSummaryFromParcelLocked(in);
@@ -8763,6 +8868,12 @@ public final class BatteryStatsImpl extends BatteryStats {
for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
mBluetoothStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
}
+ for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
+ mBluetoothActivityCounters[i].writeSummaryFromParcelLocked(out);
+ }
+ for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
+ mWifiActivityCounters[i].writeSummaryFromParcelLocked(out);
+ }
out.writeInt(mNumConnectivityChange);
mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -9067,6 +9178,15 @@ public final class BatteryStatsImpl extends BatteryStats {
mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i,
null, mOnBatteryTimeBase, in);
}
+
+ for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
+ mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
+ }
+
+ for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
+ mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
+ }
+
mNumConnectivityChange = in.readInt();
mLoadedNumConnectivityChange = in.readInt();
mUnpluggedNumConnectivityChange = in.readInt();
@@ -9212,6 +9332,12 @@ public final class BatteryStatsImpl extends BatteryStats {
for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
mBluetoothStateTimer[i].writeToParcel(out, uSecRealtime);
}
+ for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
+ mBluetoothActivityCounters[i].writeToParcel(out);
+ }
+ for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
+ mWifiActivityCounters[i].writeToParcel(out);
+ }
out.writeInt(mNumConnectivityChange);
out.writeInt(mLoadedNumConnectivityChange);
out.writeInt(mUnpluggedNumConnectivityChange);
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index b3bafa1..944eb5a 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -76,6 +76,11 @@ public class PowerProfile {
public static final String POWER_WIFI_ACTIVE = "wifi.active";
/**
+ * Operating voltage of the WiFi controller.
+ */
+ public static final String OPERATING_VOLTAGE_WIFI = "wifi.voltage";
+
+ /**
* Power consumption when GPS is on.
*/
public static final String POWER_GPS_ON = "gps.on";
@@ -96,6 +101,11 @@ public class PowerProfile {
public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at";
/**
+ * Operating voltage of the Bluetooth controller.
+ */
+ public static final String OPERATING_VOLTAGE_BLUETOOTH = "bluetooth.voltage";
+
+ /**
* Power consumption when screen is on, not including the backlight power.
*/
public static final String POWER_SCREEN_ON = "screen.on";
@@ -224,11 +234,13 @@ public class PowerProfile {
}
/**
- * Returns the average current in mA consumed by the subsystem
+ * Returns the average current in mA consumed by the subsystem, or the given
+ * default value if the subsystem has no recorded value.
* @param type the subsystem type
+ * @param defaultValue the value to return if the subsystem has no recorded value.
* @return the average current in milliAmps.
*/
- public double getAveragePower(String type) {
+ public double getAveragePowerOrDefault(String type, double defaultValue) {
if (sPowerMap.containsKey(type)) {
Object data = sPowerMap.get(type);
if (data instanceof Double[]) {
@@ -237,9 +249,18 @@ public class PowerProfile {
return (Double) sPowerMap.get(type);
}
} else {
- return 0;
+ return defaultValue;
}
}
+
+ /**
+ * Returns the average current in mA consumed by the subsystem
+ * @param type the subsystem type
+ * @return the average current in milliAmps.
+ */
+ public double getAveragePower(String type) {
+ return getAveragePowerOrDefault(type, 0);
+ }
/**
* Returns the average current in mA consumed by the subsystem for the given level.