Accumulate network statistics based on deltas.
Network stats are now read out of the kernel in one sweep, instead of
reading per-UID. We now accumulate the delta traffic between each
stats snapshot using the well-tested SamplingCounter pattern.
Since Wi-Fi and mobile traffic have different costs, track each
separately. Avoids counting misc interfaces like loopback and
ethernet under total.
Bug: 5543387
Change-Id: I642004dc530113c27ef79f2abbae51d8af30117f
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 78bf9af..ffcc297 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -464,6 +464,21 @@
}
/**
+ * Checks if the given network type is backed by a Wi-Fi radio.
+ *
+ * @hide
+ */
+ public static boolean isNetworkTypeWifi(int networkType) {
+ switch (networkType) {
+ case TYPE_WIFI:
+ case TYPE_WIFI_P2P:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
* Specifies the preferred network type. When the device has more
* than one type available the preferred network type will be used.
* Note that this made sense when we only had 2 network types,
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d0f7511..32bbfbd 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -130,7 +130,7 @@
/**
* Bump the version on this if the checkin format changes.
*/
- private static final int BATTERY_STATS_CHECKIN_VERSION = 6;
+ private static final int BATTERY_STATS_CHECKIN_VERSION = 7;
private static final long BYTES_PER_KB = 1024;
private static final long BYTES_PER_MB = 1048576; // 1024^2
@@ -259,17 +259,7 @@
* {@hide}
*/
public abstract int getUid();
-
- /**
- * {@hide}
- */
- public abstract long getTcpBytesReceived(int which);
-
- /**
- * {@hide}
- */
- public abstract long getTcpBytesSent(int which);
-
+
public abstract void noteWifiRunningLocked();
public abstract void noteWifiStoppedLocked();
public abstract void noteFullWifiLockAcquiredLocked();
@@ -304,11 +294,14 @@
};
public static final int NUM_USER_ACTIVITY_TYPES = 3;
-
+
public abstract void noteUserActivityLocked(int type);
public abstract boolean hasUserActivity();
public abstract int getUserActivityCount(int type, int which);
-
+
+ public abstract boolean hasNetworkActivity();
+ public abstract long getNetworkActivityCount(int type, int which);
+
public static abstract class Sensor {
/*
* FIXME: it's not correct to use this magic value because it
@@ -929,6 +922,15 @@
*/
public abstract long getBluetoothOnTime(long batteryRealtime, int which);
+ public static final int NETWORK_MOBILE_RX_BYTES = 0;
+ public static final int NETWORK_MOBILE_TX_BYTES = 1;
+ public static final int NETWORK_WIFI_RX_BYTES = 2;
+ public static final int NETWORK_WIFI_TX_BYTES = 3;
+
+ public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_WIFI_TX_BYTES + 1;
+
+ public abstract long getNetworkActivityCount(int type, int which);
+
/**
* Return whether we are currently running on battery.
*/
@@ -1246,16 +1248,20 @@
totalRealtime / 1000, totalUptime / 1000);
// Calculate total network and wakelock times across all uids.
- long rxTotal = 0;
- long txTotal = 0;
+ long mobileRxTotal = 0;
+ long mobileTxTotal = 0;
+ long wifiRxTotal = 0;
+ long wifiTxTotal = 0;
long fullWakeLockTimeTotal = 0;
long partialWakeLockTimeTotal = 0;
for (int iu = 0; iu < NU; iu++) {
Uid u = uidStats.valueAt(iu);
- rxTotal += u.getTcpBytesReceived(which);
- txTotal += u.getTcpBytesSent(which);
-
+ mobileRxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
+ mobileTxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
+ wifiRxTotal += u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
+ wifiTxTotal += u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
+
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
@@ -1279,7 +1285,8 @@
// Dump misc stats
dumpLine(pw, 0 /* uid */, category, MISC_DATA,
screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
- wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal,
+ wifiRunningTime / 1000, bluetoothOnTime / 1000,
+ mobileRxTotal, mobileTxTotal, wifiRxTotal, wifiTxTotal,
fullWakeLockTimeTotal, partialWakeLockTimeTotal,
getInputEventCount(which));
@@ -1350,14 +1357,18 @@
}
Uid u = uidStats.valueAt(iu);
// Dump Network stats per uid, if any
- long rx = u.getTcpBytesReceived(which);
- long tx = u.getTcpBytesSent(which);
+ long mobileRx = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
+ long mobileTx = u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
+ long wifiRx = u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
+ long wifiTx = u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
-
- if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
-
+
+ if (mobileRx > 0 || mobileTx > 0 || wifiRx > 0 || wifiTx > 0) {
+ dumpLine(pw, uid, category, NETWORK_DATA, mobileRx, mobileTx, wifiRx, wifiTx);
+ }
+
if (fullWifiLockOnTime != 0 || wifiScanTime != 0
|| uidWifiRunningTime != 0) {
dumpLine(pw, uid, category, WIFI_DATA,
@@ -1569,8 +1580,10 @@
pw.println(sb.toString());
// Calculate total network and wakelock times across all uids.
- long rxTotal = 0;
- long txTotal = 0;
+ long mobileRxTotal = 0;
+ long mobileTxTotal = 0;
+ long wifiRxTotal = 0;
+ long wifiTxTotal = 0;
long fullWakeLockTimeTotalMicros = 0;
long partialWakeLockTimeTotalMicros = 0;
@@ -1623,9 +1636,11 @@
for (int iu = 0; iu < NU; iu++) {
Uid u = uidStats.valueAt(iu);
- rxTotal += u.getTcpBytesReceived(which);
- txTotal += u.getTcpBytesSent(which);
-
+ mobileRxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
+ mobileTxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
+ wifiRxTotal += u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
+ wifiTxTotal += u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
+
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
@@ -1658,8 +1673,11 @@
}
pw.print(prefix);
- pw.print(" Total received: "); pw.print(formatBytesLocked(rxTotal));
- pw.print(", Total sent: "); pw.println(formatBytesLocked(txTotal));
+ pw.print(" Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotal));
+ pw.print(", Total sent: "); pw.println(formatBytesLocked(mobileTxTotal));
+ pw.print(prefix);
+ pw.print(" Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotal));
+ pw.print(", Total sent: "); pw.println(formatBytesLocked(wifiTxTotal));
sb.setLength(0);
sb.append(prefix);
sb.append(" Total full wakelock time: "); formatTimeMs(sb,
@@ -1801,18 +1819,25 @@
pw.println(prefix + " #" + uid + ":");
boolean uidActivity = false;
- long tcpReceived = u.getTcpBytesReceived(which);
- long tcpSent = u.getTcpBytesSent(which);
+ long mobileRxBytes = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
+ long mobileTxBytes = u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
+ long wifiRxBytes = u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
+ long wifiTxBytes = u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
-
- if (tcpReceived != 0 || tcpSent != 0) {
- pw.print(prefix); pw.print(" Network: ");
- pw.print(formatBytesLocked(tcpReceived)); pw.print(" received, ");
- pw.print(formatBytesLocked(tcpSent)); pw.println(" sent");
+
+ if (mobileRxBytes > 0 || mobileTxBytes > 0) {
+ pw.print(prefix); pw.print(" Mobile network: ");
+ pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
+ pw.print(formatBytesLocked(mobileTxBytes)); pw.println(" sent");
}
-
+ if (wifiRxBytes > 0 || wifiTxBytes > 0) {
+ pw.print(prefix); pw.print(" Wi-Fi network: ");
+ pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
+ pw.print(formatBytesLocked(wifiTxBytes)); pw.println(" sent");
+ }
+
if (u.hasUserActivity()) {
boolean hasData = false;
for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 823e19f..525517c 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -71,6 +71,7 @@
void noteWifiMulticastEnabledFromSource(in WorkSource ws);
void noteWifiMulticastDisabledFromSource(in WorkSource ws);
void noteNetworkInterfaceType(String iface, int type);
+ void noteNetworkStatsEnabled();
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 601d3ac4..38a8c19 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -16,7 +16,6 @@
package com.android.internal.os;
-import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
import android.bluetooth.BluetoothDevice;
@@ -46,6 +45,7 @@
import android.util.SparseArray;
import android.util.TimeUtils;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.JournaledFile;
import com.google.android.collect.Sets;
@@ -83,7 +83,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 65 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 66 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -231,6 +231,9 @@
final StopwatchTimer[] mPhoneDataConnectionsTimer =
new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
+ final LongSamplingCounter[] mNetworkActivityCounters =
+ new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
+
boolean mWifiOn;
StopwatchTimer mWifiOnTimer;
int mWifiOnUid = -1;
@@ -275,12 +278,6 @@
long mLastWriteTime = 0; // Milliseconds
- // Mobile data transferred while on battery
- private long[] mMobileDataTx = new long[4];
- private long[] mMobileDataRx = new long[4];
- private long[] mTotalDataTx = new long[4];
- private long[] mTotalDataRx = new long[4];
-
private long mRadioDataUptime;
private long mRadioDataStart;
@@ -337,9 +334,12 @@
private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>();
private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
+ private NetworkStats mLastSnapshot;
- /** Network ifaces that {@link ConnectivityManager} has claimed as mobile. */
+ @GuardedBy("this")
private HashSet<String> mMobileIfaces = Sets.newHashSet();
+ @GuardedBy("this")
+ private HashSet<String> mWifiIfaces = Sets.newHashSet();
// For debugging
public BatteryStatsImpl() {
@@ -466,7 +466,6 @@
}
public static class SamplingCounter extends Counter {
-
SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) {
super(unpluggables, in);
}
@@ -480,6 +479,93 @@
}
}
+ public static class LongSamplingCounter implements Unpluggable {
+ final ArrayList<Unpluggable> mUnpluggables;
+ long mCount;
+ long mLoadedCount;
+ long mLastCount;
+ long mUnpluggedCount;
+ long mPluggedCount;
+
+ LongSamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) {
+ mUnpluggables = unpluggables;
+ mPluggedCount = in.readLong();
+ mCount = mPluggedCount;
+ mLoadedCount = in.readLong();
+ mLastCount = 0;
+ mUnpluggedCount = in.readLong();
+ unpluggables.add(this);
+ }
+
+ LongSamplingCounter(ArrayList<Unpluggable> unpluggables) {
+ mUnpluggables = unpluggables;
+ unpluggables.add(this);
+ }
+
+ public void writeToParcel(Parcel out) {
+ out.writeLong(mCount);
+ out.writeLong(mLoadedCount);
+ out.writeLong(mUnpluggedCount);
+ }
+
+ @Override
+ public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+ mUnpluggedCount = mPluggedCount;
+ mCount = mPluggedCount;
+ }
+
+ @Override
+ public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+ mPluggedCount = mCount;
+ }
+
+ public long getCountLocked(int which) {
+ long val;
+ if (which == STATS_LAST) {
+ val = mLastCount;
+ } else {
+ val = mCount;
+ if (which == STATS_SINCE_UNPLUGGED) {
+ val -= mUnpluggedCount;
+ } else if (which != STATS_SINCE_CHARGED) {
+ val -= mLoadedCount;
+ }
+ }
+
+ return val;
+ }
+
+ void addCountLocked(long count) {
+ mCount += count;
+ }
+
+ /**
+ * Clear state of this counter.
+ */
+ void reset(boolean detachIfReset) {
+ mCount = 0;
+ mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
+ if (detachIfReset) {
+ detach();
+ }
+ }
+
+ void detach() {
+ mUnpluggables.remove(this);
+ }
+
+ void writeSummaryFromParcelLocked(Parcel out) {
+ out.writeLong(mCount);
+ }
+
+ void readSummaryFromParcelLocked(Parcel in) {
+ mLoadedCount = in.readLong();
+ mCount = mLoadedCount;
+ mLastCount = 0;
+ mUnpluggedCount = mPluggedCount = mLoadedCount;
+ }
+ }
+
/**
* State for keeping track of timing information.
*/
@@ -1316,15 +1402,6 @@
return kwlt;
}
- private void doDataPlug(long[] dataTransfer, long currentBytes) {
- dataTransfer[STATS_LAST] = dataTransfer[STATS_SINCE_UNPLUGGED];
- dataTransfer[STATS_SINCE_UNPLUGGED] = -1;
- }
-
- private void doDataUnplug(long[] dataTransfer, long currentBytes) {
- dataTransfer[STATS_SINCE_UNPLUGGED] = currentBytes;
- }
-
/**
* Radio uptime in microseconds when transferring data. This value is very approximate.
* @return
@@ -1571,34 +1648,10 @@
}
public void doUnplugLocked(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
- NetworkStats.Entry entry = null;
-
- // Track UID data usage
- final NetworkStats uidStats = getNetworkStatsDetailGroupedByUid();
- final int size = uidStats.size();
- for (int i = 0; i < size; i++) {
- entry = uidStats.getValues(i, entry);
-
- final Uid u = getUidStatsLocked(entry.uid);
- u.mStartedTcpBytesReceived = entry.rxBytes;
- u.mStartedTcpBytesSent = entry.txBytes;
- u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived;
- u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent;
- }
-
for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
mUnpluggables.get(i).unplug(elapsedRealtime, batteryUptime, batteryRealtime);
}
- // Track both mobile and total overall data
- final NetworkStats ifaceStats = getNetworkStatsSummary();
- entry = ifaceStats.getTotal(entry, mMobileIfaces);
- doDataUnplug(mMobileDataRx, entry.rxBytes);
- doDataUnplug(mMobileDataTx, entry.txBytes);
- entry = ifaceStats.getTotal(entry);
- doDataUnplug(mTotalDataRx, entry.rxBytes);
- doDataUnplug(mTotalDataTx, entry.txBytes);
-
// Track radio awake time
mRadioDataStart = getCurrentRadioDataUptime();
mRadioDataUptime = 0;
@@ -1609,32 +1662,10 @@
}
public void doPlugLocked(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
- NetworkStats.Entry entry = null;
-
- for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
- Uid u = mUidStats.valueAt(iu);
- if (u.mStartedTcpBytesReceived >= 0) {
- u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived();
- u.mStartedTcpBytesReceived = -1;
- }
- if (u.mStartedTcpBytesSent >= 0) {
- u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent();
- u.mStartedTcpBytesSent = -1;
- }
- }
for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
mUnpluggables.get(i).plug(elapsedRealtime, batteryUptime, batteryRealtime);
}
- // Track both mobile and total overall data
- final NetworkStats ifaceStats = getNetworkStatsSummary();
- entry = ifaceStats.getTotal(entry, mMobileIfaces);
- doDataPlug(mMobileDataRx, entry.rxBytes);
- doDataPlug(mMobileDataTx, entry.txBytes);
- entry = ifaceStats.getTotal(entry);
- doDataPlug(mTotalDataRx, entry.rxBytes);
- doDataPlug(mTotalDataTx, entry.txBytes);
-
// Track radio awake time
mRadioDataUptime = getRadioDataUptime();
mRadioDataStart = -1;
@@ -2441,6 +2472,18 @@
} else {
mMobileIfaces.remove(iface);
}
+ if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
+ mWifiIfaces.add(iface);
+ } else {
+ mWifiIfaces.remove(iface);
+ }
+ }
+
+ public void noteNetworkStatsEnabledLocked() {
+ // 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();
}
@Override public long getScreenOnTime(long batteryRealtime, int which) {
@@ -2499,6 +2542,15 @@
return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
+ @Override
+ public long getNetworkActivityCount(int type, int which) {
+ if (type >= 0 && type < mNetworkActivityCounters.length) {
+ return mNetworkActivityCounters[type].getCountLocked(which);
+ } else {
+ return 0;
+ }
+ }
+
@Override public boolean getIsOnBattery() {
return mOnBattery;
}
@@ -2513,17 +2565,6 @@
public final class Uid extends BatteryStats.Uid {
final int mUid;
- long mLoadedTcpBytesReceived;
- long mLoadedTcpBytesSent;
- long mCurrentTcpBytesReceived;
- long mCurrentTcpBytesSent;
- long mTcpBytesReceivedAtLastUnplug;
- long mTcpBytesSentAtLastUnplug;
-
- // These are not saved/restored when parcelling, since we want
- // to return from the parcel with a snapshot of the state.
- long mStartedTcpBytesReceived = -1;
- long mStartedTcpBytesSent = -1;
boolean mWifiRunning;
StopwatchTimer mWifiRunningTimer;
@@ -2549,6 +2590,8 @@
Counter[] mUserActivityCounters;
+ LongSamplingCounter[] mNetworkActivityCounters;
+
/**
* The statistics we have collected for this uid's wake locks.
*/
@@ -2612,43 +2655,6 @@
}
@Override
- public long getTcpBytesReceived(int which) {
- if (which == STATS_LAST) {
- return mLoadedTcpBytesReceived;
- } else {
- long current = computeCurrentTcpBytesReceived();
- if (which == STATS_SINCE_UNPLUGGED) {
- current -= mTcpBytesReceivedAtLastUnplug;
- } else if (which == STATS_SINCE_CHARGED) {
- current += mLoadedTcpBytesReceived;
- }
- return current;
- }
- }
-
- public long computeCurrentTcpBytesReceived() {
- final long uidRxBytes = getNetworkStatsDetailGroupedByUid().getTotal(
- null, mUid).rxBytes;
- return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
- ? (uidRxBytes - mStartedTcpBytesReceived) : 0);
- }
-
- @Override
- public long getTcpBytesSent(int which) {
- if (which == STATS_LAST) {
- return mLoadedTcpBytesSent;
- } else {
- long current = computeCurrentTcpBytesSent();
- if (which == STATS_SINCE_UNPLUGGED) {
- current -= mTcpBytesSentAtLastUnplug;
- } else if (which == STATS_SINCE_CHARGED) {
- current += mLoadedTcpBytesSent;
- }
- return current;
- }
- }
-
- @Override
public void noteWifiRunningLocked() {
if (!mWifiRunning) {
mWifiRunning = true;
@@ -2911,11 +2917,38 @@
}
}
- public long computeCurrentTcpBytesSent() {
- final long uidTxBytes = getNetworkStatsDetailGroupedByUid().getTotal(
- null, mUid).txBytes;
- return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
- ? (uidTxBytes - mStartedTcpBytesSent) : 0);
+ void noteNetworkActivityLocked(int type, long delta) {
+ if (mNetworkActivityCounters == null) {
+ initNetworkActivityLocked();
+ }
+ if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
+ mNetworkActivityCounters[type].addCountLocked(delta);
+ } else {
+ Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
+ new Throwable());
+ }
+ }
+
+ @Override
+ public boolean hasNetworkActivity() {
+ return mNetworkActivityCounters != null;
+ }
+
+ @Override
+ public long getNetworkActivityCount(int type, int which) {
+ if (mNetworkActivityCounters != null && type >= 0
+ && type < mNetworkActivityCounters.length) {
+ return mNetworkActivityCounters[type].getCountLocked(which);
+ } else {
+ return 0;
+ }
+ }
+
+ void initNetworkActivityLocked() {
+ mNetworkActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
+ }
}
/**
@@ -2961,15 +2994,18 @@
}
}
- mLoadedTcpBytesReceived = mLoadedTcpBytesSent = 0;
- mCurrentTcpBytesReceived = mCurrentTcpBytesSent = 0;
-
if (mUserActivityCounters != null) {
for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
mUserActivityCounters[i].reset(false);
}
}
+ if (mNetworkActivityCounters != null) {
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].reset(false);
+ }
+ }
+
if (mWakelockStats.size() > 0) {
Iterator<Map.Entry<String, Wakelock>> it = mWakelockStats.entrySet().iterator();
while (it.hasNext()) {
@@ -3060,6 +3096,11 @@
mUserActivityCounters[i].detach();
}
}
+ if (mNetworkActivityCounters != null) {
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].detach();
+ }
+ }
}
return !active;
@@ -3094,12 +3135,6 @@
pkg.writeToParcelLocked(out);
}
- out.writeLong(mLoadedTcpBytesReceived);
- out.writeLong(mLoadedTcpBytesSent);
- out.writeLong(computeCurrentTcpBytesReceived());
- out.writeLong(computeCurrentTcpBytesSent());
- out.writeLong(mTcpBytesReceivedAtLastUnplug);
- out.writeLong(mTcpBytesSentAtLastUnplug);
if (mWifiRunningTimer != null) {
out.writeInt(1);
mWifiRunningTimer.writeToParcel(out, batteryRealtime);
@@ -3156,6 +3191,14 @@
} else {
out.writeInt(0);
}
+ if (mNetworkActivityCounters != null) {
+ out.writeInt(1);
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].writeToParcel(out);
+ }
+ } else {
+ out.writeInt(0);
+ }
}
void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
@@ -3198,12 +3241,6 @@
mPackageStats.put(packageName, pkg);
}
- mLoadedTcpBytesReceived = in.readLong();
- mLoadedTcpBytesSent = in.readLong();
- mCurrentTcpBytesReceived = in.readLong();
- mCurrentTcpBytesSent = in.readLong();
- mTcpBytesReceivedAtLastUnplug = in.readLong();
- mTcpBytesSentAtLastUnplug = in.readLong();
mWifiRunning = false;
if (in.readInt() != 0) {
mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
@@ -3266,6 +3303,14 @@
} else {
mUserActivityCounters = null;
}
+ if (in.readInt() != 0) {
+ mNetworkActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
+ }
+ } else {
+ mNetworkActivityCounters = null;
+ }
}
/**
@@ -4340,6 +4385,9 @@
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null, mUnpluggables);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
+ }
mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables);
mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mUnpluggables);
@@ -4515,6 +4563,9 @@
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i].reset(this, false);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].reset(false);
+ }
mWifiOnTimer.reset(this, false);
mGlobalWifiRunningTimer.reset(this, false);
mBluetoothOnTimer.reset(this, false);
@@ -4590,6 +4641,7 @@
mDischargeStartLevel = level;
}
updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
mHistoryCur.batteryLevel = (byte)level;
mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
@@ -4612,6 +4664,7 @@
doUnplugLocked(realtime, mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
} else {
updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
mHistoryCur.batteryLevel = (byte)level;
mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
@@ -4744,6 +4797,52 @@
}
}
+ private void updateNetworkActivityLocked() {
+ if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return;
+
+ final NetworkStats snapshot;
+ try {
+ snapshot = mNetworkStatsFactory.readNetworkStatsDetail();
+ } catch (IOException e) {
+ Log.wtf(TAG, "Failed to read network stats", e);
+ return;
+ }
+
+ if (mLastSnapshot == null) {
+ mLastSnapshot = snapshot;
+ return;
+ }
+
+ final NetworkStats delta = snapshot.subtract(mLastSnapshot);
+ mLastSnapshot = snapshot;
+
+ NetworkStats.Entry entry = null;
+ final int size = delta.size();
+ for (int i = 0; i < size; i++) {
+ entry = delta.getValues(i, entry);
+
+ if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
+ if (entry.tag != NetworkStats.TAG_NONE) continue;
+
+ final Uid u = getUidStatsLocked(entry.uid);
+
+ if (mMobileIfaces.contains(entry.iface)) {
+ u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_BYTES, entry.rxBytes);
+ u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_BYTES, entry.txBytes);
+
+ mNetworkActivityCounters[NETWORK_MOBILE_RX_BYTES].addCountLocked(entry.rxBytes);
+ mNetworkActivityCounters[NETWORK_MOBILE_TX_BYTES].addCountLocked(entry.txBytes);
+
+ } else if (mWifiIfaces.contains(entry.iface)) {
+ u.noteNetworkActivityLocked(NETWORK_WIFI_RX_BYTES, entry.rxBytes);
+ u.noteNetworkActivityLocked(NETWORK_WIFI_TX_BYTES, entry.txBytes);
+
+ mNetworkActivityCounters[NETWORK_WIFI_RX_BYTES].addCountLocked(entry.rxBytes);
+ mNetworkActivityCounters[NETWORK_WIFI_TX_BYTES].addCountLocked(entry.txBytes);
+ }
+ }
+ }
+
public long getAwakeTimeBattery() {
return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
}
@@ -4834,47 +4933,6 @@
return getBatteryRealtimeLocked(curTime);
}
- private long getTcpBytes(long current, long[] dataBytes, int which) {
- if (which == STATS_LAST) {
- return dataBytes[STATS_LAST];
- } else {
- if (which == STATS_SINCE_UNPLUGGED) {
- if (dataBytes[STATS_SINCE_UNPLUGGED] < 0) {
- return dataBytes[STATS_LAST];
- } else {
- return current - dataBytes[STATS_SINCE_UNPLUGGED];
- }
- } else if (which == STATS_SINCE_CHARGED) {
- return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_SINCE_CHARGED];
- }
- return current - dataBytes[STATS_CURRENT];
- }
- }
-
- /** Only STATS_UNPLUGGED works properly */
- public long getMobileTcpBytesSent(int which) {
- final long mobileTxBytes = getNetworkStatsSummary().getTotal(null, mMobileIfaces).txBytes;
- return getTcpBytes(mobileTxBytes, mMobileDataTx, which);
- }
-
- /** Only STATS_UNPLUGGED works properly */
- public long getMobileTcpBytesReceived(int which) {
- final long mobileRxBytes = getNetworkStatsSummary().getTotal(null, mMobileIfaces).rxBytes;
- return getTcpBytes(mobileRxBytes, mMobileDataRx, which);
- }
-
- /** Only STATS_UNPLUGGED works properly */
- public long getTotalTcpBytesSent(int which) {
- final long totalTxBytes = getNetworkStatsSummary().getTotal(null).txBytes;
- return getTcpBytes(totalTxBytes, mTotalDataTx, which);
- }
-
- /** Only STATS_UNPLUGGED works properly */
- public long getTotalTcpBytesReceived(int which) {
- final long totalRxBytes = getNetworkStatsSummary().getTotal(null).rxBytes;
- return getTcpBytes(totalRxBytes, mTotalDataRx, which);
- }
-
@Override
public int getDischargeStartLevel() {
synchronized(this) {
@@ -5354,6 +5412,9 @@
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].readSummaryFromParcelLocked(in);
+ }
mWifiOn = false;
mWifiOnTimer.readSummaryFromParcelLocked(in);
mGlobalWifiRunning = false;
@@ -5425,6 +5486,15 @@
}
}
+ if (in.readInt() != 0) {
+ if (u.mNetworkActivityCounters == null) {
+ u.initNetworkActivityLocked();
+ }
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ u.mNetworkActivityCounters[i].readSummaryFromParcelLocked(in);
+ }
+ }
+
int NW = in.readInt();
if (NW > 100) {
Slog.w(TAG, "File corrupt: too many wake locks " + NW);
@@ -5507,9 +5577,6 @@
s.mLaunches = s.mLoadedLaunches = in.readInt();
}
}
-
- u.mLoadedTcpBytesReceived = in.readLong();
- u.mLoadedTcpBytesSent = in.readLong();
}
}
@@ -5522,6 +5589,7 @@
public void writeSummaryToParcel(Parcel out) {
// Need to update with current kernel wake lock counts.
updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
@@ -5557,6 +5625,9 @@
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].writeSummaryFromParcelLocked(out);
+ }
mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
@@ -5638,6 +5709,15 @@
}
}
+ if (u.mNetworkActivityCounters == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(1);
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ u.mNetworkActivityCounters[i].writeSummaryFromParcelLocked(out);
+ }
+ }
+
int NW = u.mWakelockStats.size();
out.writeInt(NW);
if (NW > 0) {
@@ -5730,9 +5810,6 @@
}
}
}
-
- out.writeLong(u.getTcpBytesReceived(STATS_SINCE_CHARGED));
- out.writeLong(u.getTcpBytesSent(STATS_SINCE_CHARGED));
}
}
@@ -5771,6 +5848,9 @@
mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
null, mUnpluggables, in);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
+ }
mWifiOn = false;
mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mGlobalWifiRunning = false;
@@ -5801,15 +5881,6 @@
mDischargeAmountScreenOffSinceCharge = in.readInt();
mLastWriteTime = in.readLong();
- mMobileDataRx[STATS_LAST] = in.readLong();
- mMobileDataRx[STATS_SINCE_UNPLUGGED] = -1;
- mMobileDataTx[STATS_LAST] = in.readLong();
- mMobileDataTx[STATS_SINCE_UNPLUGGED] = -1;
- mTotalDataRx[STATS_LAST] = in.readLong();
- mTotalDataRx[STATS_SINCE_UNPLUGGED] = -1;
- mTotalDataTx[STATS_LAST] = in.readLong();
- mTotalDataTx[STATS_SINCE_UNPLUGGED] = -1;
-
mRadioDataUptime = in.readLong();
mRadioDataStart = -1;
@@ -5859,6 +5930,7 @@
void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
// Need to update with current kernel wake lock counts.
updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
final long uSecUptime = SystemClock.uptimeMillis() * 1000;
final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
@@ -5885,6 +5957,9 @@
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].writeToParcel(out);
+ }
mWifiOnTimer.writeToParcel(out, batteryRealtime);
mGlobalWifiRunningTimer.writeToParcel(out, batteryRealtime);
mBluetoothOnTimer.writeToParcel(out, batteryRealtime);
@@ -5909,11 +5984,6 @@
out.writeInt(mDischargeAmountScreenOffSinceCharge);
out.writeLong(mLastWriteTime);
- out.writeLong(getMobileTcpBytesReceived(STATS_SINCE_UNPLUGGED));
- out.writeLong(getMobileTcpBytesSent(STATS_SINCE_UNPLUGGED));
- out.writeLong(getTotalTcpBytesReceived(STATS_SINCE_UNPLUGGED));
- out.writeLong(getTotalTcpBytesSent(STATS_SINCE_UNPLUGGED));
-
// Write radio uptime for data
out.writeLong(getRadioDataUptime());
@@ -5965,6 +6035,7 @@
public void prepareForDumpLocked() {
// Need to retrieve current kernel wake lock stats before printing.
updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
}
public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly) {
@@ -5996,59 +6067,7 @@
mGlobalWifiRunningTimer.logState(pr, " ");
pr.println("*** Bluetooth timer:");
mBluetoothOnTimer.logState(pr, " ");
- pr.println("*** Mobile ifaces:");
- pr.println(mMobileIfaces.toString());
}
super.dumpLocked(pw, isUnpluggedOnly);
}
-
- private NetworkStats mNetworkSummaryCache;
- private NetworkStats mNetworkDetailCache;
-
- private NetworkStats getNetworkStatsSummary() {
- // NOTE: calls from BatteryStatsService already hold this lock
- synchronized (this) {
- if (mNetworkSummaryCache == null
- || mNetworkSummaryCache.getElapsedRealtimeAge() > SECOND_IN_MILLIS) {
- mNetworkSummaryCache = null;
-
- if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
- try {
- mNetworkSummaryCache = mNetworkStatsFactory.readNetworkStatsSummaryDev();
- } catch (IOException e) {
- Log.wtf(TAG, "problem reading network stats", e);
- }
- }
-
- if (mNetworkSummaryCache == null) {
- mNetworkSummaryCache = new NetworkStats(SystemClock.elapsedRealtime(), 0);
- }
- }
- return mNetworkSummaryCache;
- }
- }
-
- private NetworkStats getNetworkStatsDetailGroupedByUid() {
- // NOTE: calls from BatteryStatsService already hold this lock
- synchronized (this) {
- if (mNetworkDetailCache == null
- || mNetworkDetailCache.getElapsedRealtimeAge() > SECOND_IN_MILLIS) {
- mNetworkDetailCache = null;
-
- if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
- try {
- mNetworkDetailCache = mNetworkStatsFactory
- .readNetworkStatsDetail().groupedByUid();
- } catch (IOException e) {
- Log.wtf(TAG, "problem reading network stats", e);
- }
- }
-
- if (mNetworkDetailCache == null) {
- mNetworkDetailCache = new NetworkStats(SystemClock.elapsedRealtime(), 0);
- }
- }
- return mNetworkDetailCache;
- }
- }
}