summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/net/NetworkStats.java11
-rw-r--r--core/java/android/os/BatteryStats.java140
-rw-r--r--core/java/com/android/internal/os/BatterySipper.java7
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHelper.java79
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java144
5 files changed, 333 insertions, 48 deletions
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 25514f4..54d43d3 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -507,6 +507,17 @@ public class NetworkStats implements Parcelable {
}
/**
+ * Fast path for battery stats.
+ */
+ public long getTotalPackets() {
+ long total = 0;
+ for (int i = size-1; i >= 0; i--) {
+ total += rxPackets[i] + txPackets[i];
+ }
+ return total;
+ }
+
+ /**
* Subtract the given {@link NetworkStats}, effectively leaving the delta
* between two snapshots in time. Assumes that statistics rows collect over
* time, and that none of them have disappeared.
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index e91f7d7..bfce0c1 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -326,6 +326,8 @@ public abstract class BatteryStats implements Parcelable {
public abstract boolean hasNetworkActivity();
public abstract long getNetworkActivityBytes(int type, int which);
public abstract long getNetworkActivityPackets(int type, int which);
+ public abstract long getMobileRadioActiveTime(int which);
+ public abstract int getMobileRadioActiveCount(int which);
public static abstract class Sensor {
/*
@@ -899,6 +901,28 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract long getMobileRadioActiveTime(long batteryRealtime, int which);
+ /**
+ * Returns the number of times that the mobile network has transitioned to the
+ * active state.
+ *
+ * {@hide}
+ */
+ public abstract int getMobileRadioActiveCount(int which);
+
+ /**
+ * Returns the time in microseconds that the mobile network has been active
+ * (in a high power state) but not being able to blame on an app.
+ *
+ * {@hide}
+ */
+ public abstract long getMobileRadioActiveUnknownTime(int which);
+
+ /**
+ * Return count of number of times radio was app that could not be blamed on apps.
+ *
+ * {@hide}
+ */
+ public abstract int getMobileRadioActiveUnknownCount(int which);
public static final int DATA_CONNECTION_NONE = 0;
public static final int DATA_CONNECTION_GPRS = 1;
@@ -1238,6 +1262,13 @@ public abstract class BatteryStats implements Parcelable {
sb.append("ms ");
}
+ private final static void formatTimeMsNoSpace(StringBuilder sb, long time) {
+ long sec = time / 1000;
+ formatTimeRaw(sb, sec);
+ sb.append(time - (sec * 1000));
+ sb.append("ms");
+ }
+
private final String formatRatioLocked(long num, long den) {
if (den == 0L) {
return "--%";
@@ -1590,6 +1621,8 @@ public abstract class BatteryStats implements Parcelable {
long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
+ long mobileActiveTime = u.getMobileRadioActiveTime(which);
+ int mobileActiveCount = u.getMobileRadioActiveCount(which);
long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
@@ -1598,11 +1631,12 @@ public abstract class BatteryStats implements Parcelable {
if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
|| mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
- || wifiPacketsTx > 0) {
+ || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0) {
dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
wifiBytesRx, wifiBytesTx,
mobilePacketsRx, mobilePacketsTx,
- wifiPacketsRx, wifiPacketsTx);
+ wifiPacketsRx, wifiPacketsTx,
+ mobileActiveTime, mobileActiveCount);
}
if (fullWifiLockOnTime != 0 || wifiScanTime != 0
@@ -1932,9 +1966,9 @@ public abstract class BatteryStats implements Parcelable {
pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")");
sb.setLength(0);
sb.append(prefix);
- sb.append(" Total full wakelock time: "); formatTimeMs(sb,
+ sb.append(" Total full wakelock time: "); formatTimeMsNoSpace(sb,
(fullWakeLockTimeTotalMicros + 500) / 1000);
- sb.append(", Total partial wakelock time: "); formatTimeMs(sb,
+ sb.append(", Total partial wakelock time: "); formatTimeMsNoSpace(sb,
(partialWakeLockTimeTotalMicros + 500) / 1000);
pw.println(sb.toString());
@@ -1964,7 +1998,7 @@ public abstract class BatteryStats implements Parcelable {
sb.setLength(0);
sb.append(prefix);
sb.append(" Signal scanning time: ");
- formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
+ formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
pw.println(sb.toString());
sb.setLength(0);
@@ -1993,9 +2027,26 @@ public abstract class BatteryStats implements Parcelable {
sb.setLength(0);
sb.append(prefix);
sb.append(" Mobile radio active time: ");
- formatTimeMs(sb, getMobileRadioActiveTime(batteryRealtime, which) / 1000);
+ final long mobileActiveTime = getMobileRadioActiveTime(batteryRealtime, which);
+ formatTimeMs(sb, mobileActiveTime / 1000);
+ sb.append("("); sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime));
+ sb.append(") "); sb.append(getMobileRadioActiveCount(which));
+ sb.append("x");
pw.println(sb.toString());
+ final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which);
+ if (mobileActiveUnknownTime != 0) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Mobile radio active unknown time: ");
+ formatTimeMs(sb, mobileActiveUnknownTime / 1000);
+ sb.append("(");
+ sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime));
+ sb.append(") "); sb.append(getMobileRadioActiveUnknownCount(which));
+ sb.append("x");
+ pw.println(sb.toString());
+ }
+
sb.setLength(0);
sb.append(prefix);
sb.append(" Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
@@ -2132,7 +2183,8 @@ public abstract class BatteryStats implements Parcelable {
pw.println();
break;
case APP:
- pw.print(prefix); pw.print(" Uid "); pw.print(bs.uidObj.getUid());
+ pw.print(prefix); pw.print(" Uid ");
+ UserHandle.formatUid(pw, bs.uidObj.getUid());
pw.print(": "); printmAh(pw, bs.value); pw.println();
break;
case USER:
@@ -2152,6 +2204,23 @@ public abstract class BatteryStats implements Parcelable {
pw.println();
}
+ sippers = helper.getMobilemsppList();
+ if (sippers != null && sippers.size() > 0) {
+ pw.print(prefix); pw.println(" Per-app mobile ms per packet:");
+ for (int i=0; i<sippers.size(); i++) {
+ BatterySipper bs = sippers.get(i);
+ sb.setLength(0);
+ sb.append(prefix); sb.append(" Uid ");
+ UserHandle.formatUid(sb, bs.uidObj.getUid());
+ sb.append(": "); sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
+ sb.append(" ("); sb.append(bs.mobileRxPackets+bs.mobileTxPackets);
+ sb.append(" packets over "); formatTimeMsNoSpace(sb, bs.mobileActive);
+ sb.append(")");
+ pw.println(sb.toString());
+ }
+ pw.println();
+ }
+
if (timers.size() > 0) {
Collections.sort(timers, timerComparator);
pw.print(prefix); pw.println(" All partial wake locks:");
@@ -2183,13 +2252,15 @@ public abstract class BatteryStats implements Parcelable {
UserHandle.formatUid(pw, uid);
pw.println(":");
boolean uidActivity = false;
-
+
long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
+ long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
+ int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
@@ -2204,6 +2275,23 @@ public abstract class BatteryStats implements Parcelable {
pw.print(" sent (packets "); pw.print(mobileRxPackets);
pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
}
+ if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
+ sb.setLength(0);
+ sb.append(prefix); sb.append(" Mobile radio active: ");
+ formatTimeMs(sb, uidMobileActiveTime / 1000);
+ sb.append("(");
+ sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
+ sb.append(") "); sb.append(uidMobileActiveCount); sb.append("x");
+ long packets = mobileRxPackets + mobileTxPackets;
+ if (packets == 0) {
+ packets = 1;
+ }
+ sb.append(" @ ");
+ sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double)packets));
+ sb.append(" mspp");
+ pw.println(sb.toString());
+ }
+
if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
pw.print(prefix); pw.print(" Wi-Fi network: ");
pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
@@ -2212,6 +2300,24 @@ public abstract class BatteryStats implements Parcelable {
pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
}
+ if (fullWifiLockOnTime != 0 || wifiScanTime != 0
+ || uidWifiRunningTime != 0) {
+ sb.setLength(0);
+ sb.append(prefix); sb.append(" Wifi Running: ");
+ formatTimeMs(sb, uidWifiRunningTime / 1000);
+ sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
+ whichBatteryRealtime)); sb.append(")\n");
+ sb.append(prefix); sb.append(" Full Wifi Lock: ");
+ formatTimeMs(sb, fullWifiLockOnTime / 1000);
+ sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
+ whichBatteryRealtime)); sb.append(")\n");
+ sb.append(prefix); sb.append(" Wifi Scan: ");
+ formatTimeMs(sb, wifiScanTime / 1000);
+ sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
+ whichBatteryRealtime)); sb.append(")");
+ pw.println(sb.toString());
+ }
+
if (u.hasUserActivity()) {
boolean hasData = false;
for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
@@ -2233,24 +2339,6 @@ public abstract class BatteryStats implements Parcelable {
pw.println(sb.toString());
}
}
-
- if (fullWifiLockOnTime != 0 || wifiScanTime != 0
- || uidWifiRunningTime != 0) {
- sb.setLength(0);
- sb.append(prefix); sb.append(" Wifi Running: ");
- formatTimeMs(sb, uidWifiRunningTime / 1000);
- sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
- whichBatteryRealtime)); sb.append(")\n");
- sb.append(prefix); sb.append(" Full Wifi Lock: ");
- formatTimeMs(sb, fullWifiLockOnTime / 1000);
- sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
- whichBatteryRealtime)); sb.append(")\n");
- sb.append(prefix); sb.append(" Wifi Scan: ");
- formatTimeMs(sb, wifiScanTime / 1000);
- sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
- whichBatteryRealtime)); sb.append(")");
- pw.println(sb.toString());
- }
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
index 4eff5ac..565cee4 100644
--- a/core/java/com/android/internal/os/BatterySipper.java
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -34,6 +34,8 @@ public class BatterySipper implements Comparable<BatterySipper> {
public long wakeLockTime;
public long mobileRxPackets;
public long mobileTxPackets;
+ public long mobileActive;
+ public double mobilemspp; // milliseconds per packet
public long wifiRxPackets;
public long wifiTxPackets;
public long mobileRxBytes;
@@ -69,6 +71,11 @@ public class BatterySipper implements Comparable<BatterySipper> {
return values;
}
+ public void computeMobilemspp() {
+ long packets = mobileRxPackets+mobileTxPackets;
+ mobilemspp = packets > 0 ? (mobileActive / (double)packets) : 0;
+ }
+
@Override
public int compareTo(BatterySipper other) {
// Return the flipped value because we want the items in descending order
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index e0cf435..755530c 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -43,6 +43,7 @@ import com.android.internal.os.BatterySipper.DrainType;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -73,6 +74,8 @@ public class BatteryStatsHelper {
= new SparseArray<List<BatterySipper>>();
private final SparseArray<Double> mUserPower = new SparseArray<Double>();
+ private final List<BatterySipper> mMobilemsppList = new ArrayList<BatterySipper>();
+
private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
private int mAsUser = 0;
@@ -90,6 +93,9 @@ public class BatteryStatsHelper {
private double mMinDrainedPower;
private double mMaxDrainedPower;
+ // How much the apps together have kept the mobile radio active.
+ private long mAppMobileActive;
+
// How much the apps together have left WIFI running.
private long mAppWifiRunning;
@@ -132,7 +138,7 @@ public class BatteryStatsHelper {
}
public static String makemAh(double power) {
- if (power < .0001) return String.format("%.8f", power);
+ if (power < .00001) return String.format("%.8f", power);
else if (power < .0001) return String.format("%.7f", power);
else if (power < .001) return String.format("%.6f", power);
else if (power < .01) return String.format("%.5f", power);
@@ -160,6 +166,7 @@ public class BatteryStatsHelper {
mTotalPower = 0;
mWifiPower = 0;
mBluetoothPower = 0;
+ mAppMobileActive = 0;
mAppWifiRunning = 0;
mUsageList.clear();
@@ -167,6 +174,7 @@ public class BatteryStatsHelper {
mBluetoothSippers.clear();
mUserSippers.clear();
mUserPower.clear();
+ mMobilemsppList.clear();
if (mStats == null) {
return;
@@ -193,6 +201,37 @@ public class BatteryStatsHelper {
* mPowerProfile.getBatteryCapacity()) / 100;
processAppUsage();
+
+ // Before aggregating apps in to users, collect all apps to sort by their ms per packet.
+ for (int i=0; i<mUsageList.size(); i++) {
+ BatterySipper bs = mUsageList.get(i);
+ bs.computeMobilemspp();
+ if (bs.mobilemspp != 0) {
+ 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++) {
+ BatterySipper bs = user.get(j);
+ bs.computeMobilemspp();
+ if (bs.mobilemspp != 0) {
+ mMobilemsppList.add(bs);
+ }
+ }
+ }
+ Collections.sort(mMobilemsppList, new Comparator<BatterySipper>() {
+ @Override
+ public int compare(BatterySipper lhs, BatterySipper rhs) {
+ if (lhs.mobilemspp < rhs.mobilemspp) {
+ return 1;
+ } else if (lhs.mobilemspp > rhs.mobilemspp) {
+ return -1;
+ }
+ return 0;
+ }
+ });
+
processMiscUsage();
if (DEBUG) {
@@ -225,6 +264,7 @@ public class BatteryStatsHelper {
powerCpuNormal[p] = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p);
}
final double mobilePowerPerPacket = getMobilePowerPerPacket();
+ final double mobilePowerPerMs = getMobilePowerPerMs();
final double wifiPowerPerPacket = getWifiPowerPerPacket();
long appWakelockTime = 0;
BatterySipper osApp = null;
@@ -320,9 +360,20 @@ public class BatteryStatsHelper {
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);
- p = (mobileRx + mobileTx) * mobilePowerPerPacket;
+ final long mobileActive = u.getMobileRadioActiveTime(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;
+ } 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;
+ }
if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": mobile packets "
- + (mobileRx+mobileTx) + " power=" + makemAh(p));
+ + (mobileRx+mobileTx) + " active time " + mobileActive
+ + " power=" + makemAh(p));
power += p;
// Add cost of wifi traffic
@@ -406,6 +457,7 @@ public class BatteryStatsHelper {
app.wakeLockTime = wakelockTime;
app.mobileRxPackets = mobileRx;
app.mobileTxPackets = mobileTx;
+ app.mobileActive = mobileActive / 1000;
app.wifiRxPackets = wifiRx;
app.wifiTxPackets = wifiTx;
app.mobileRxBytes = mobileRxB;
@@ -474,7 +526,7 @@ public class BatteryStatsHelper {
double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
* phoneOnTimeMs / (60*60*1000);
if (phoneOnPower != 0) {
- addEntry(BatterySipper.DrainType.PHONE, phoneOnTimeMs, phoneOnPower);
+ BatterySipper bs = addEntry(BatterySipper.DrainType.PHONE, phoneOnTimeMs, phoneOnPower);
}
}
@@ -531,12 +583,18 @@ public class BatteryStatsHelper {
Log.d(TAG, "Cell radio scanning: time=" + scanningTimeMs + " power=" + makemAh(p));
}
power += p;
+ long radioActiveTimeUs = mStats.getMobileRadioActiveTime(mBatteryRealtime, mStatsType);
+ long remainingActiveTime = (radioActiveTimeUs - mAppMobileActive) / 1000;
+ if (remainingActiveTime > 0) {
+ power += getMobilePowerPerMs() * remainingActiveTime;
+ }
if (power != 0) {
BatterySipper bs =
addEntry(BatterySipper.DrainType.CELL, signalTimeMs, power);
if (signalTimeMs != 0) {
bs.noCoveragePercent = noCoverageTimeMs * 100.0 / signalTimeMs;
}
+ bs.mobileActive = remainingActiveTime;
}
}
@@ -551,6 +609,7 @@ public class BatteryStatsHelper {
bs.wakeLockTime += wbs.wakeLockTime;
bs.mobileRxPackets += wbs.mobileRxPackets;
bs.mobileTxPackets += wbs.mobileTxPackets;
+ bs.mobileActive += wbs.mobileActive;
bs.wifiRxPackets += wbs.wifiRxPackets;
bs.wifiTxPackets += wbs.wifiTxPackets;
bs.mobileRxBytes += wbs.mobileRxBytes;
@@ -558,6 +617,7 @@ public class BatteryStatsHelper {
bs.wifiRxBytes += wbs.wifiRxBytes;
bs.wifiTxBytes += wbs.wifiTxBytes;
}
+ bs.computeMobilemspp();
}
private void addWiFiUsage() {
@@ -650,6 +710,13 @@ public class BatteryStatsHelper {
}
/**
+ * Return estimated power (in mAs) of keeping the radio up
+ */
+ private double getMobilePowerPerMs() {
+ return mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE) / (60*60*1000);
+ }
+
+ /**
* Return estimated power (in mAs) of sending a byte with the Wi-Fi radio.
*/
private double getWifiPowerPerPacket() {
@@ -691,6 +758,10 @@ public class BatteryStatsHelper {
return mUsageList;
}
+ public List<BatterySipper> getMobilemsppList() {
+ return mMobilemsppList;
+ }
+
public long getStatsPeriod() { return mStatsPeriod; }
public int getStatsType() { return mStatsType; };
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 8843500..46983ab 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -87,7 +87,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 85 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 90 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -283,6 +283,8 @@ public final class BatteryStatsImpl extends BatteryStats {
boolean mMobileRadioActive;
StopwatchTimer mMobileRadioActiveTimer;
+ LongSamplingCounter mMobileRadioActiveUnknownTime;
+ LongSamplingCounter mMobileRadioActiveUnknownCount;
/** Bluetooth headset object */
BluetoothHeadset mBtHeadset;
@@ -1176,11 +1178,12 @@ public final class BatteryStatsImpl extends BatteryStats {
void startRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) {
if (mNesting++ == 0) {
- mUpdateTime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000);
+ final long batteryRealtime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000);
+ mUpdateTime = batteryRealtime;
if (mTimerPool != null) {
// Accumulate time to all currently active timers before adding
// this new one to the pool.
- refreshTimersLocked(stats, mTimerPool);
+ refreshTimersLocked(stats, batteryRealtime, mTimerPool, null);
// Add this timer to the active pool
mTimerPool.add(this);
}
@@ -1199,21 +1202,35 @@ public final class BatteryStatsImpl extends BatteryStats {
return mNesting > 0;
}
+ long checkpointRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) {
+ if (mNesting > 0) {
+ // We are running...
+ final long batteryRealtime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000);
+ if (mTimerPool != null) {
+ return refreshTimersLocked(stats, batteryRealtime, mTimerPool, this);
+ }
+ final long heldTime = batteryRealtime - mUpdateTime;
+ mUpdateTime = batteryRealtime;
+ mTotalTime += heldTime;
+ return heldTime;
+ }
+ return 0;
+ }
+
void stopRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) {
// Ignore attempt to stop a timer that isn't running
if (mNesting == 0) {
return;
}
if (--mNesting == 0) {
+ final long batteryRealtime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000);
if (mTimerPool != null) {
// Accumulate time to all active counters, scaled by the total
// active in the pool, before taking this one out of the pool.
- refreshTimersLocked(stats, mTimerPool);
+ refreshTimersLocked(stats, batteryRealtime, mTimerPool, null);
// Remove this timer from the active pool
mTimerPool.remove(this);
} else {
- final long batteryRealtime = stats.getBatteryRealtimeLocked(
- elapsedRealtime * 1000);
mNesting = 1;
mTotalTime = computeRunTimeLocked(batteryRealtime);
mNesting = 0;
@@ -1235,19 +1252,23 @@ public final class BatteryStatsImpl extends BatteryStats {
// Update the total time for all other running Timers with the same type as this Timer
// due to a change in timer count
- private static void refreshTimersLocked(final BatteryStatsImpl stats,
- final ArrayList<StopwatchTimer> pool) {
- final long realtime = SystemClock.elapsedRealtime() * 1000;
- final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
+ private static long refreshTimersLocked(final BatteryStatsImpl stats,
+ long batteryRealtime, final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
+ long selfTime = 0;
final int N = pool.size();
for (int i=N-1; i>= 0; i--) {
final StopwatchTimer t = pool.get(i);
long heldTime = batteryRealtime - t.mUpdateTime;
if (heldTime > 0) {
- t.mTotalTime += heldTime / N;
+ final long myTime = heldTime / N;
+ if (t == self) {
+ selfTime = myTime;
+ }
+ t.mTotalTime += myTime;
}
t.mUpdateTime = batteryRealtime;
}
+ return selfTime;
}
@Override
@@ -2368,8 +2389,12 @@ public final class BatteryStatsImpl extends BatteryStats {
+ Integer.toHexString(mHistoryCur.states));
addHistoryRecordLocked(elapsedRealtime);
mMobileRadioActive = active;
- if (active) mMobileRadioActiveTimer.startRunningLocked(this, elapsedRealtime);
- else mMobileRadioActiveTimer.stopRunningLocked(this, elapsedRealtime);
+ if (active) {
+ mMobileRadioActiveTimer.startRunningLocked(this, elapsedRealtime);
+ } else {
+ updateNetworkActivityLocked(NET_UPDATE_MOBILE, elapsedRealtime);
+ mMobileRadioActiveTimer.stopRunningLocked(this, elapsedRealtime);
+ }
}
}
} catch (NumberFormatException e) {
@@ -3006,7 +3031,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.
- updateNetworkActivityLocked();
+ updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
}
@Override public long getScreenOnTime(long batteryRealtime, int which) {
@@ -3057,6 +3082,18 @@ public final class BatteryStatsImpl extends BatteryStats {
return mMobileRadioActiveTimer.getTotalTimeLocked(batteryRealtime, which);
}
+ @Override public int getMobileRadioActiveCount(int which) {
+ return mMobileRadioActiveTimer.getCountLocked(which);
+ }
+
+ @Override public long getMobileRadioActiveUnknownTime(int which) {
+ return mMobileRadioActiveUnknownTime.getCountLocked(which);
+ }
+
+ @Override public int getMobileRadioActiveUnknownCount(int which) {
+ return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
+ }
+
@Override public long getWifiOnTime(long batteryRealtime, int which) {
return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@@ -3156,6 +3193,8 @@ public final class BatteryStatsImpl extends BatteryStats {
LongSamplingCounter[] mNetworkByteActivityCounters;
LongSamplingCounter[] mNetworkPacketActivityCounters;
+ LongSamplingCounter mMobileRadioActiveTime;
+ LongSamplingCounter mMobileRadioActiveCount;
/**
* The statistics we have collected for this uid's wake locks.
@@ -3556,6 +3595,14 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ void noteMobileRadioActiveTimeLocked(long batteryUptime) {
+ if (mNetworkByteActivityCounters == null) {
+ initNetworkActivityLocked();
+ }
+ mMobileRadioActiveTime.addCountLocked(batteryUptime);
+ mMobileRadioActiveCount.addCountLocked(1);
+ }
+
@Override
public boolean hasNetworkActivity() {
return mNetworkByteActivityCounters != null;
@@ -3581,6 +3628,18 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ @Override
+ public long getMobileRadioActiveTime(int which) {
+ return mMobileRadioActiveTime != null
+ ? mMobileRadioActiveTime.getCountLocked(which) : 0;
+ }
+
+ @Override
+ public int getMobileRadioActiveCount(int which) {
+ return mMobileRadioActiveCount != null
+ ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
+ }
+
void initNetworkActivityLocked() {
mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
@@ -3588,6 +3647,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
}
+ mMobileRadioActiveTime = new LongSamplingCounter(mUnpluggables);
+ mMobileRadioActiveCount = new LongSamplingCounter(mUnpluggables);
}
/**
@@ -3652,6 +3713,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mNetworkByteActivityCounters[i].reset(false);
mNetworkPacketActivityCounters[i].reset(false);
}
+ mMobileRadioActiveTime.reset(false);
+ mMobileRadioActiveCount.reset(false);
}
if (mWakelockStats.size() > 0) {
@@ -3859,6 +3922,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mNetworkByteActivityCounters[i].writeToParcel(out);
mNetworkPacketActivityCounters[i].writeToParcel(out);
}
+ mMobileRadioActiveTime.writeToParcel(out);
+ mMobileRadioActiveCount.writeToParcel(out);
} else {
out.writeInt(0);
}
@@ -3982,6 +4047,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
}
+ mMobileRadioActiveTime = new LongSamplingCounter(mUnpluggables, in);
+ mMobileRadioActiveCount = new LongSamplingCounter(mUnpluggables, in);
} else {
mNetworkByteActivityCounters = null;
mNetworkPacketActivityCounters = null;
@@ -5076,6 +5143,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
}
mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mUnpluggables);
+ mMobileRadioActiveUnknownTime = new LongSamplingCounter(mUnpluggables);
+ mMobileRadioActiveUnknownCount = new LongSamplingCounter(mUnpluggables);
mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables);
mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
for (int i=0; i<NUM_WIFI_STATES; i++) {
@@ -5342,6 +5411,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mNetworkPacketActivityCounters[i].reset(false);
}
mMobileRadioActiveTimer.reset(this, false);
+ mMobileRadioActiveUnknownTime.reset(false);
+ mMobileRadioActiveUnknownCount.reset(false);
mWifiOnTimer.reset(this, false);
mGlobalWifiRunningTimer.reset(this, false);
for (int i=0; i<NUM_WIFI_STATES; i++) {
@@ -5419,7 +5490,7 @@ public final class BatteryStatsImpl extends BatteryStats {
public void pullPendingStateUpdatesLocked() {
updateKernelWakelocksLocked();
- updateNetworkActivityLocked();
+ updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
}
void setOnBatteryLocked(boolean onBattery, int oldStatus, int level) {
@@ -5604,10 +5675,14 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
- private void updateNetworkActivityLocked() {
+ static final int NET_UPDATE_MOBILE = 1<<0;
+ static final int NET_UPDATE_WIFI = 1<<1;
+ static final int NET_UPDATE_ALL = 0xffff;
+
+ private void updateNetworkActivityLocked(int which, long elapsedRealtime) {
if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return;
- if (mMobileIfaces.length > 0) {
+ if ((which&NET_UPDATE_MOBILE) != 0 && mMobileIfaces.length > 0) {
final NetworkStats snapshot;
final NetworkStats last = mCurMobileSnapshot;
try {
@@ -5625,6 +5700,10 @@ public final class BatteryStatsImpl extends BatteryStats {
null, null, mTmpNetworkStats);
mTmpNetworkStats = delta;
+ long radioTime = mMobileRadioActiveTimer.checkpointRunningLocked(this,
+ elapsedRealtime);
+ long totalPackets = delta.getTotalPackets();
+
final int size = delta.size();
for (int i = 0; i < size; i++) {
final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
@@ -5637,6 +5716,17 @@ public final class BatteryStatsImpl extends BatteryStats {
u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
entry.txPackets);
+ 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;
+ }
+
mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(entry.rxBytes);
mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(entry.txBytes);
mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
@@ -5644,9 +5734,15 @@ public final class BatteryStatsImpl extends BatteryStats {
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 (mWifiIfaces.length > 0) {
+ if ((which&NET_UPDATE_WIFI) != 0 && mWifiIfaces.length > 0) {
final NetworkStats snapshot;
final NetworkStats last = mCurWifiSnapshot;
try {
@@ -6275,6 +6371,8 @@ public final class BatteryStatsImpl extends BatteryStats {
}
mMobileRadioActive = false;
mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
+ mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
+ mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
mWifiOn = false;
mWifiOnTimer.readSummaryFromParcelLocked(in);
mGlobalWifiRunning = false;
@@ -6370,6 +6468,8 @@ public final class BatteryStatsImpl extends BatteryStats {
u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
}
+ u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
+ u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
}
int NW = in.readInt();
@@ -6506,6 +6606,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
}
mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+ mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
+ mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
for (int i=0; i<NUM_WIFI_STATES; i++) {
@@ -6609,6 +6711,8 @@ public final class BatteryStatsImpl extends BatteryStats {
u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
}
+ u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
+ u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
}
int NW = u.mWakelockStats.size();
@@ -6748,6 +6852,8 @@ public final class BatteryStatsImpl extends BatteryStats {
}
mMobileRadioActive = false;
mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mUnpluggables, in);
+ mMobileRadioActiveUnknownTime = new LongSamplingCounter(mUnpluggables, in);
+ mMobileRadioActiveUnknownCount = new LongSamplingCounter(mUnpluggables, in);
mWifiOn = false;
mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mGlobalWifiRunning = false;
@@ -6865,6 +6971,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mNetworkPacketActivityCounters[i].writeToParcel(out);
}
mMobileRadioActiveTimer.writeToParcel(out, batteryRealtime);
+ mMobileRadioActiveUnknownTime.writeToParcel(out);
+ mMobileRadioActiveUnknownCount.writeToParcel(out);
mWifiOnTimer.writeToParcel(out, batteryRealtime);
mGlobalWifiRunningTimer.writeToParcel(out, batteryRealtime);
for (int i=0; i<NUM_WIFI_STATES; i++) {