diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/net/NetworkStats.java | 11 | ||||
-rw-r--r-- | core/java/android/os/BatteryStats.java | 140 | ||||
-rw-r--r-- | core/java/com/android/internal/os/BatterySipper.java | 7 | ||||
-rw-r--r-- | core/java/com/android/internal/os/BatteryStatsHelper.java | 79 | ||||
-rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 144 |
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++) { |