Merge "Track xtables summary, move tether stats, time."

This commit is contained in:
Jeff Sharkey
2011-10-04 13:12:06 -07:00
committed by Android (Google) Code Review
6 changed files with 369 additions and 121 deletions

View File

@@ -271,6 +271,17 @@ public class NetworkStats implements Parcelable {
return this; return this;
} }
/**
* Combine all values from another {@link NetworkStats} into this object.
*/
public void combineAllValues(NetworkStats another) {
NetworkStats.Entry entry = null;
for (int i = 0; i < another.size; i++) {
entry = another.getValues(i, entry);
combineValues(entry);
}
}
/** /**
* Find first stats index that matches the requested parameters. * Find first stats index that matches the requested parameters.
*/ */
@@ -456,6 +467,34 @@ public class NetworkStats implements Parcelable {
return result; return result;
} }
/**
* Return total statistics grouped by {@link #iface}; doesn't mutate the
* original structure.
*/
public NetworkStats groupedByIface() {
final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
final Entry entry = new Entry();
entry.uid = UID_ALL;
entry.set = SET_ALL;
entry.tag = TAG_NONE;
entry.operations = 0L;
for (int i = 0; i < size; i++) {
// skip specific tags, since already counted in TAG_NONE
if (tag[i] != TAG_NONE) continue;
entry.iface = iface[i];
entry.rxBytes = rxBytes[i];
entry.rxPackets = rxPackets[i];
entry.txBytes = txBytes[i];
entry.txPackets = txPackets[i];
stats.combineValues(entry);
}
return stats;
}
public void dump(String prefix, PrintWriter pw) { public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print(prefix);
pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime); pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);

View File

@@ -18,6 +18,8 @@ package android.net;
import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.SET_FOREGROUND; import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStats.UID_ALL;
@@ -176,8 +178,63 @@ public class NetworkStatsTest extends TestCase {
assertEquals(64L, uidTag.getTotalBytes()); assertEquals(64L, uidTag.getTotalBytes());
} }
public void testGroupedByIfaceEmpty() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 3);
final NetworkStats grouped = uidStats.groupedByIface();
assertEquals(0, uidStats.size());
assertEquals(0, grouped.size());
}
public void testGroupedByIfaceAll() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
.addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
.addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, 128L, 8L, 0L, 2L, 20L);
final NetworkStats grouped = uidStats.groupedByIface();
assertEquals(2, uidStats.size());
assertEquals(1, grouped.size());
assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, 256L, 16L, 0L, 4L, 0L);
}
public void testGroupedByIface() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
.addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L)
.addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 64L, 4L, 0L, 0L, 0L)
.addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 512L, 32L, 0L, 0L, 0L)
.addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L)
.addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 128L, 8L, 0L, 0L, 0L);
final NetworkStats grouped = uidStats.groupedByIface();
assertEquals(6, uidStats.size());
assertEquals(2, grouped.size());
assertValues(grouped, 0, TEST_IFACE, UID_ALL, SET_ALL, TAG_NONE, 256L, 16L, 0L, 2L, 0L);
assertValues(grouped, 1, TEST_IFACE2, UID_ALL, SET_ALL, TAG_NONE, 1024L, 64L, 0L, 0L, 0L);
}
public void testAddAllValues() {
final NetworkStats first = new NetworkStats(TEST_START, 5)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
.addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
final NetworkStats second = new NetworkStats(TEST_START, 2)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
.addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
first.combineAllValues(second);
assertEquals(3, first.size());
assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 64L, 0L, 0L, 0L, 0L);
assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
assertValues(first, 2, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
}
private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set, private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set,
int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) { int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
final NetworkStats.Entry entry = stats.getValues(index, null); final NetworkStats.Entry entry = stats.getValues(index, null);
assertEquals(iface, entry.iface); assertEquals(iface, entry.iface);
assertEquals(uid, entry.uid); assertEquals(uid, entry.uid);

View File

@@ -142,5 +142,5 @@ option java_package com.android.server
# --------------------------- # ---------------------------
# NetworkStatsService.java # NetworkStatsService.java
# --------------------------- # ---------------------------
51100 netstats_mobile_sample (iface_rx_bytes|2|2),(iface_tx_bytes|2|2),(iface_rx_pkts|2|1),(iface_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1) 51100 netstats_mobile_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3)
51101 netstats_wifi_sample (iface_rx_bytes|2|2),(iface_tx_bytes|2|2),(iface_rx_pkts|2|1),(iface_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1) 51101 netstats_wifi_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3)

View File

@@ -21,6 +21,7 @@ import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.TAG_NONE;
import static android.net.TrafficStats.UID_TETHERING;
import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStats.UID_ALL;
import static android.provider.Settings.Secure.NETSTATS_ENABLED; import static android.provider.Settings.Secure.NETSTATS_ENABLED;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
@@ -1522,7 +1523,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
try { try {
final NetworkStats.Entry entry = new NetworkStats.Entry(); final NetworkStats.Entry entry = new NetworkStats.Entry();
entry.iface = ifaceIn; entry.iface = ifaceIn;
entry.uid = UID_ALL; entry.uid = UID_TETHERING;
entry.set = SET_DEFAULT; entry.set = SET_DEFAULT;
entry.tag = TAG_NONE; entry.tag = TAG_NONE;
entry.rxBytes = Long.parseLong(tok[3]); entry.rxBytes = Long.parseLong(tok[3]);

View File

@@ -35,7 +35,6 @@ import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll; import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi; import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.UID_REMOVED; import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION; import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY; import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD; import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
@@ -72,7 +71,6 @@ import android.net.NetworkState;
import android.net.NetworkStats; import android.net.NetworkStats;
import android.net.NetworkStatsHistory; import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate; import android.net.NetworkTemplate;
import android.net.TrafficStats;
import android.os.Binder; import android.os.Binder;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
@@ -140,11 +138,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private static final int MSG_UPDATE_IFACES = 2; private static final int MSG_UPDATE_IFACES = 2;
/** Flags to control detail level of poll event. */ /** Flags to control detail level of poll event. */
private static final int FLAG_PERSIST_NETWORK = 0x10; private static final int FLAG_PERSIST_NETWORK = 0x1;
private static final int FLAG_PERSIST_UID = 0x20; private static final int FLAG_PERSIST_UID = 0x2;
private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID; private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
private static final int FLAG_PERSIST_FORCE = 0x100; private static final int FLAG_PERSIST_FORCE = 0x100;
/** Sample recent usage after each poll event. */
private static final boolean ENABLE_SAMPLE_AFTER_POLL = true;
private final Context mContext; private final Context mContext;
private final INetworkManagementService mNetworkManager; private final INetworkManagementService mNetworkManager;
private final IAlarmManager mAlarmManager; private final IAlarmManager mAlarmManager;
@@ -188,20 +189,23 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
/** Set of currently active ifaces. */ /** Set of currently active ifaces. */
private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap(); private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
/** Set of historical network layer stats for known networks. */ /** Set of historical {@code dev} stats for known networks. */
private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap(); private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkDevStats = Maps.newHashMap();
/** Set of historical network layer stats for known UIDs. */ /** Set of historical {@code xtables} stats for known networks. */
private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkXtStats = Maps.newHashMap();
/** Set of historical {@code xtables} stats for known UIDs. */
private HashMap<UidStatsKey, NetworkStatsHistory> mUidStats = Maps.newHashMap(); private HashMap<UidStatsKey, NetworkStatsHistory> mUidStats = Maps.newHashMap();
/** Flag if {@link #mUidStats} have been loaded from disk. */ /** Flag if {@link #mUidStats} have been loaded from disk. */
private boolean mUidStatsLoaded = false; private boolean mUidStatsLoaded = false;
private NetworkStats mLastPollNetworkSnapshot; private NetworkStats mLastPollNetworkDevSnapshot;
private NetworkStats mLastPollNetworkXtSnapshot;
private NetworkStats mLastPollUidSnapshot; private NetworkStats mLastPollUidSnapshot;
private NetworkStats mLastPollOperationsSnapshot; private NetworkStats mLastPollOperationsSnapshot;
private NetworkStats mLastPollTetherSnapshot;
private NetworkStats mLastPersistNetworkSnapshot; private NetworkStats mLastPersistNetworkDevSnapshot;
private NetworkStats mLastPersistNetworkXtSnapshot;
private NetworkStats mLastPersistUidSnapshot; private NetworkStats mLastPersistUidSnapshot;
/** Current counter sets for each UID. */ /** Current counter sets for each UID. */
@@ -213,7 +217,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private final HandlerThread mHandlerThread; private final HandlerThread mHandlerThread;
private final Handler mHandler; private final Handler mHandler;
private final AtomicFile mNetworkFile; private final AtomicFile mNetworkDevFile;
private final AtomicFile mNetworkXtFile;
private final AtomicFile mUidFile; private final AtomicFile mUidFile;
public NetworkStatsService( public NetworkStatsService(
@@ -244,7 +249,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mHandlerThread.start(); mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
mNetworkFile = new AtomicFile(new File(systemDir, "netstats.bin")); mNetworkDevFile = new AtomicFile(new File(systemDir, "netstats.bin"));
mNetworkXtFile = new AtomicFile(new File(systemDir, "netstats_xt.bin"));
mUidFile = new AtomicFile(new File(systemDir, "netstats_uid.bin")); mUidFile = new AtomicFile(new File(systemDir, "netstats_uid.bin"));
} }
@@ -257,7 +263,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// read historical network stats from disk, since policy service // read historical network stats from disk, since policy service
// might need them right away. we delay loading detailed UID stats // might need them right away. we delay loading detailed UID stats
// until actually needed. // until actually needed.
readNetworkStatsLocked(); readNetworkDevStatsLocked();
readNetworkXtStatsLocked();
} }
// watch for network interfaces to be claimed // watch for network interfaces to be claimed
@@ -306,11 +313,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mTeleManager.listen(mPhoneListener, LISTEN_NONE); mTeleManager.listen(mPhoneListener, LISTEN_NONE);
writeNetworkStatsLocked(); writeNetworkDevStatsLocked();
writeNetworkXtStatsLocked();
if (mUidStatsLoaded) { if (mUidStatsLoaded) {
writeUidStatsLocked(); writeUidStatsLocked();
} }
mNetworkStats.clear(); mNetworkDevStats.clear();
mNetworkXtStats.clear();
mUidStats.clear(); mUidStats.clear();
mUidStatsLoaded = false; mUidStatsLoaded = false;
} }
@@ -355,14 +364,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override @Override
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
return getHistoryForNetworkDev(template, fields);
}
private NetworkStatsHistory getHistoryForNetworkDev(NetworkTemplate template, int fields) {
return getHistoryForNetwork(template, fields, mNetworkDevStats);
}
private NetworkStatsHistory getHistoryForNetworkXt(NetworkTemplate template, int fields) {
return getHistoryForNetwork(template, fields, mNetworkXtStats);
}
private NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields,
HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
synchronized (mStatsLock) { synchronized (mStatsLock) {
// combine all interfaces that match template // combine all interfaces that match template
final NetworkStatsHistory combined = new NetworkStatsHistory( final NetworkStatsHistory combined = new NetworkStatsHistory(
mSettings.getNetworkBucketDuration(), estimateNetworkBuckets(), fields); mSettings.getNetworkBucketDuration(), estimateNetworkBuckets(), fields);
for (NetworkIdentitySet ident : mNetworkStats.keySet()) { for (NetworkIdentitySet ident : source.keySet()) {
if (templateMatches(template, ident)) { if (templateMatches(template, ident)) {
final NetworkStatsHistory history = mNetworkStats.get(ident); final NetworkStatsHistory history = source.get(ident);
if (history != null) { if (history != null) {
combined.recordEntireHistory(history); combined.recordEntireHistory(history);
} }
@@ -399,7 +420,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override @Override
public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) { public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
return getSummaryForNetworkDev(template, start, end);
}
private NetworkStats getSummaryForNetworkDev(NetworkTemplate template, long start, long end) {
return getSummaryForNetwork(template, start, end, mNetworkDevStats);
}
private NetworkStats getSummaryForNetworkXt(NetworkTemplate template, long start, long end) {
return getSummaryForNetwork(template, start, end, mNetworkXtStats);
}
private NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end,
HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
synchronized (mStatsLock) { synchronized (mStatsLock) {
// use system clock to be externally consistent // use system clock to be externally consistent
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
@@ -409,9 +442,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
NetworkStatsHistory.Entry historyEntry = null; NetworkStatsHistory.Entry historyEntry = null;
// combine total from all interfaces that match template // combine total from all interfaces that match template
for (NetworkIdentitySet ident : mNetworkStats.keySet()) { for (NetworkIdentitySet ident : source.keySet()) {
if (templateMatches(template, ident)) { if (templateMatches(template, ident)) {
final NetworkStatsHistory history = mNetworkStats.get(ident); final NetworkStatsHistory history = source.get(ident);
historyEntry = history.getValues(start, end, now, historyEntry); historyEntry = history.getValues(start, end, now, historyEntry);
entry.iface = IFACE_ALL; entry.iface = IFACE_ALL;
@@ -716,8 +749,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
*/ */
private void bootstrapStats() { private void bootstrapStats() {
try { try {
mLastPollNetworkSnapshot = mNetworkManager.getNetworkStatsSummary();
mLastPollUidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); mLastPollUidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
mLastPollNetworkDevSnapshot = mNetworkManager.getNetworkStatsSummary();
mLastPollNetworkXtSnapshot = computeNetworkXtSnapshotFromUid(mLastPollUidSnapshot);
mLastPollOperationsSnapshot = new NetworkStats(0L, 0); mLastPollOperationsSnapshot = new NetworkStats(0L, 0);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
Slog.w(TAG, "problem reading network stats: " + e); Slog.w(TAG, "problem reading network stats: " + e);
@@ -759,42 +793,56 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
: System.currentTimeMillis(); : System.currentTimeMillis();
final long threshold = mSettings.getPersistThreshold(); final long threshold = mSettings.getPersistThreshold();
final NetworkStats uidSnapshot;
final NetworkStats networkXtSnapshot;
final NetworkStats networkDevSnapshot;
try { try {
// record tethering stats; persisted during normal UID cycle below // collect any tethering stats
final String[] ifacePairs = mConnManager.getTetheredIfacePairs(); final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs();
final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering( final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering(
ifacePairs); tetheredIfacePairs);
performTetherPollLocked(tetherSnapshot, currentTime);
// record uid stats // record uid stats, folding in tethering stats
final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
uidSnapshot.combineAllValues(tetherSnapshot);
performUidPollLocked(uidSnapshot, currentTime); performUidPollLocked(uidSnapshot, currentTime);
// persist when enough network data has occurred // record dev network stats
final NetworkStats persistUidDelta = computeStatsDelta( networkDevSnapshot = mNetworkManager.getNetworkStatsSummary();
mLastPersistUidSnapshot, uidSnapshot, true); performNetworkDevPollLocked(networkDevSnapshot, currentTime);
final boolean uidPastThreshold = persistUidDelta.getTotalBytes() > threshold;
if (persistForce || (persistUid && uidPastThreshold)) {
writeUidStatsLocked();
mLastPersistUidSnapshot = uidSnapshot;
}
// record network stats // record xt network stats
final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary(); networkXtSnapshot = computeNetworkXtSnapshotFromUid(uidSnapshot);
performNetworkPollLocked(networkSnapshot, currentTime); performNetworkXtPollLocked(networkXtSnapshot, currentTime);
// persist when enough network data has occurred
final NetworkStats persistNetworkDelta = computeStatsDelta(
mLastPersistNetworkSnapshot, networkSnapshot, true);
final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold;
if (persistForce || (persistNetwork && networkPastThreshold)) {
writeNetworkStatsLocked();
mLastPersistNetworkSnapshot = networkSnapshot;
}
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
Log.wtf(TAG, "problem reading network stats", e); Log.wtf(TAG, "problem reading network stats", e);
return;
} catch (RemoteException e) { } catch (RemoteException e) {
// ignored; service lives in system_server // ignored; service lives in system_server
return;
}
// persist when enough network data has occurred
final long persistNetworkDevDelta = computeStatsDelta(
mLastPersistNetworkDevSnapshot, networkDevSnapshot, true).getTotalBytes();
final long persistNetworkXtDelta = computeStatsDelta(
mLastPersistNetworkXtSnapshot, networkXtSnapshot, true).getTotalBytes();
final boolean networkOverThreshold = persistNetworkDevDelta > threshold
|| persistNetworkXtDelta > threshold;
if (persistForce || (persistNetwork && networkOverThreshold)) {
writeNetworkDevStatsLocked();
writeNetworkXtStatsLocked();
mLastPersistNetworkDevSnapshot = networkDevSnapshot;
mLastPersistNetworkXtSnapshot = networkXtSnapshot;
}
// persist when enough uid data has occurred
final long persistUidDelta = computeStatsDelta(mLastPersistUidSnapshot, uidSnapshot, true)
.getTotalBytes();
if (persistForce || (persistUid && persistUidDelta > threshold)) {
writeUidStatsLocked();
mLastPersistUidSnapshot = uidSnapshot;
} }
if (LOGV) { if (LOGV) {
@@ -802,8 +850,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
Slog.v(TAG, "performPollLocked() took " + duration + "ms"); Slog.v(TAG, "performPollLocked() took " + duration + "ms");
} }
// sample stats after each full poll if (ENABLE_SAMPLE_AFTER_POLL) {
performSample(); // sample stats after each full poll
performSample();
}
// finally, dispatch updated event to any listeners // finally, dispatch updated event to any listeners
final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
@@ -812,12 +862,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
/** /**
* Update {@link #mNetworkStats} historical usage. * Update {@link #mNetworkDevStats} historical usage.
*/ */
private void performNetworkPollLocked(NetworkStats networkSnapshot, long currentTime) { private void performNetworkDevPollLocked(NetworkStats networkDevSnapshot, long currentTime) {
final HashSet<String> unknownIface = Sets.newHashSet(); final HashSet<String> unknownIface = Sets.newHashSet();
final NetworkStats delta = computeStatsDelta(mLastPollNetworkSnapshot, networkSnapshot, false); final NetworkStats delta = computeStatsDelta(
mLastPollNetworkDevSnapshot, networkDevSnapshot, false);
final long timeStart = currentTime - delta.getElapsedRealtime(); final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null; NetworkStats.Entry entry = null;
@@ -829,14 +880,44 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
continue; continue;
} }
final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident); final NetworkStatsHistory history = findOrCreateNetworkDevStatsLocked(ident);
history.recordData(timeStart, currentTime, entry); history.recordData(timeStart, currentTime, entry);
} }
mLastPollNetworkSnapshot = networkSnapshot; mLastPollNetworkDevSnapshot = networkDevSnapshot;
if (LOGD && unknownIface.size() > 0) { if (LOGD && unknownIface.size() > 0) {
Slog.w(TAG, "unknown interfaces " + unknownIface.toString() + ", ignoring those stats"); Slog.w(TAG, "unknown dev interfaces " + unknownIface + ", ignoring those stats");
}
}
/**
* Update {@link #mNetworkXtStats} historical usage.
*/
private void performNetworkXtPollLocked(NetworkStats networkXtSnapshot, long currentTime) {
final HashSet<String> unknownIface = Sets.newHashSet();
final NetworkStats delta = computeStatsDelta(
mLastPollNetworkXtSnapshot, networkXtSnapshot, false);
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
for (int i = 0; i < delta.size(); i++) {
entry = delta.getValues(i, entry);
final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
if (ident == null) {
unknownIface.add(entry.iface);
continue;
}
final NetworkStatsHistory history = findOrCreateNetworkXtStatsLocked(ident);
history.recordData(timeStart, currentTime, entry);
}
mLastPollNetworkXtSnapshot = networkXtSnapshot;
if (LOGD && unknownIface.size() > 0) {
Slog.w(TAG, "unknown xt interfaces " + unknownIface + ", ignoring those stats");
} }
} }
@@ -881,38 +962,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mOperations = new NetworkStats(0L, 10); mOperations = new NetworkStats(0L, 10);
} }
/**
* Update {@link #mUidStats} historical usage for
* {@link TrafficStats#UID_TETHERING} based on tethering statistics.
*/
private void performTetherPollLocked(NetworkStats tetherSnapshot, long currentTime) {
ensureUidStatsLoadedLocked();
final NetworkStats delta = computeStatsDelta(
mLastPollTetherSnapshot, tetherSnapshot, false);
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
for (int i = 0; i < delta.size(); i++) {
entry = delta.getValues(i, entry);
final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
if (ident == null) {
if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0
|| entry.txPackets > 0) {
Log.w(TAG, "dropping tether delta from unknown iface: " + entry);
}
continue;
}
final NetworkStatsHistory history = findOrCreateUidStatsLocked(
ident, UID_TETHERING, SET_DEFAULT, TAG_NONE);
history.recordData(timeStart, currentTime, entry);
}
// normal UID poll will trim any history beyond max
mLastPollTetherSnapshot = tetherSnapshot;
}
/** /**
* Sample recent statistics summary into {@link EventLog}. * Sample recent statistics summary into {@link EventLog}.
*/ */
@@ -925,25 +974,34 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final long end = now - (now % largestBucketSize) + largestBucketSize; final long end = now - (now % largestBucketSize) + largestBucketSize;
final long start = end - largestBucketSize; final long start = end - largestBucketSize;
final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
NetworkTemplate template = null; NetworkTemplate template = null;
NetworkStats.Entry ifaceTotal = null; NetworkStats.Entry devTotal = null;
NetworkStats.Entry xtTotal = null;
NetworkStats.Entry uidTotal = null; NetworkStats.Entry uidTotal = null;
// collect mobile sample // collect mobile sample
template = buildTemplateMobileAll(getActiveSubscriberId(mContext)); template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal); devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal);
xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal);
uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal); uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
EventLogTags.writeNetstatsMobileSample(ifaceTotal.rxBytes, ifaceTotal.rxPackets, EventLogTags.writeNetstatsMobileSample(
ifaceTotal.txBytes, ifaceTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets, devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
uidTotal.txBytes, uidTotal.txPackets); xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
trustedTime);
// collect wifi sample // collect wifi sample
template = buildTemplateWifi(); template = buildTemplateWifi();
ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal); devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal);
xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal);
uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal); uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
EventLogTags.writeNetstatsWifiSample(ifaceTotal.rxBytes, ifaceTotal.rxPackets, EventLogTags.writeNetstatsWifiSample(
ifaceTotal.txBytes, ifaceTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets, devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
uidTotal.txBytes, uidTotal.txPackets); xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
trustedTime);
} }
/** /**
@@ -976,8 +1034,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
writeUidStatsLocked(); writeUidStatsLocked();
} }
private NetworkStatsHistory findOrCreateNetworkStatsLocked(NetworkIdentitySet ident) { private NetworkStatsHistory findOrCreateNetworkXtStatsLocked(NetworkIdentitySet ident) {
final NetworkStatsHistory existing = mNetworkStats.get(ident); return findOrCreateNetworkStatsLocked(ident, mNetworkXtStats);
}
private NetworkStatsHistory findOrCreateNetworkDevStatsLocked(NetworkIdentitySet ident) {
return findOrCreateNetworkStatsLocked(ident, mNetworkDevStats);
}
private NetworkStatsHistory findOrCreateNetworkStatsLocked(
NetworkIdentitySet ident, HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
final NetworkStatsHistory existing = source.get(ident);
// update when no existing, or when bucket duration changed // update when no existing, or when bucket duration changed
final long bucketDuration = mSettings.getNetworkBucketDuration(); final long bucketDuration = mSettings.getNetworkBucketDuration();
@@ -991,7 +1058,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
if (updated != null) { if (updated != null) {
mNetworkStats.put(ident, updated); source.put(ident, updated);
return updated; return updated;
} else { } else {
return existing; return existing;
@@ -1024,15 +1091,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
} }
private void readNetworkStatsLocked() { private void readNetworkDevStatsLocked() {
if (LOGV) Slog.v(TAG, "readNetworkStatsLocked()"); if (LOGV) Slog.v(TAG, "readNetworkDevStatsLocked()");
readNetworkStats(mNetworkDevFile, mNetworkDevStats);
}
private void readNetworkXtStatsLocked() {
if (LOGV) Slog.v(TAG, "readNetworkXtStatsLocked()");
readNetworkStats(mNetworkXtFile, mNetworkXtStats);
}
private static void readNetworkStats(
AtomicFile inputFile, HashMap<NetworkIdentitySet, NetworkStatsHistory> output) {
// clear any existing stats and read from disk // clear any existing stats and read from disk
mNetworkStats.clear(); output.clear();
DataInputStream in = null; DataInputStream in = null;
try { try {
in = new DataInputStream(new BufferedInputStream(mNetworkFile.openRead())); in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
// verify file magic header intact // verify file magic header intact
final int magic = in.readInt(); final int magic = in.readInt();
@@ -1048,7 +1124,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
final NetworkIdentitySet ident = new NetworkIdentitySet(in); final NetworkIdentitySet ident = new NetworkIdentitySet(in);
final NetworkStatsHistory history = new NetworkStatsHistory(in); final NetworkStatsHistory history = new NetworkStatsHistory(in);
mNetworkStats.put(ident, history); output.put(ident, history);
} }
break; break;
} }
@@ -1138,41 +1214,50 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
} }
private void writeNetworkStatsLocked() { private void writeNetworkDevStatsLocked() {
if (LOGV) Slog.v(TAG, "writeNetworkStatsLocked()"); if (LOGV) Slog.v(TAG, "writeNetworkDevStatsLocked()");
writeNetworkStats(mNetworkDevStats, mNetworkDevFile);
}
private void writeNetworkXtStatsLocked() {
if (LOGV) Slog.v(TAG, "writeNetworkXtStatsLocked()");
writeNetworkStats(mNetworkXtStats, mNetworkXtFile);
}
private void writeNetworkStats(
HashMap<NetworkIdentitySet, NetworkStatsHistory> input, AtomicFile outputFile) {
// TODO: consider duplicating stats and releasing lock while writing // TODO: consider duplicating stats and releasing lock while writing
// trim any history beyond max // trim any history beyond max
if (mTime.hasCache()) { if (mTime.hasCache()) {
final long currentTime = mTime.currentTimeMillis(); final long currentTime = mTime.currentTimeMillis();
final long maxHistory = mSettings.getNetworkMaxHistory(); final long maxHistory = mSettings.getNetworkMaxHistory();
for (NetworkStatsHistory history : mNetworkStats.values()) { for (NetworkStatsHistory history : input.values()) {
history.removeBucketsBefore(currentTime - maxHistory); history.removeBucketsBefore(currentTime - maxHistory);
} }
} }
FileOutputStream fos = null; FileOutputStream fos = null;
try { try {
fos = mNetworkFile.startWrite(); fos = outputFile.startWrite();
final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos)); final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
out.writeInt(FILE_MAGIC); out.writeInt(FILE_MAGIC);
out.writeInt(VERSION_NETWORK_INIT); out.writeInt(VERSION_NETWORK_INIT);
out.writeInt(mNetworkStats.size()); out.writeInt(input.size());
for (NetworkIdentitySet ident : mNetworkStats.keySet()) { for (NetworkIdentitySet ident : input.keySet()) {
final NetworkStatsHistory history = mNetworkStats.get(ident); final NetworkStatsHistory history = input.get(ident);
ident.writeToStream(out); ident.writeToStream(out);
history.writeToStream(out); history.writeToStream(out);
} }
out.flush(); out.flush();
mNetworkFile.finishWrite(fos); outputFile.finishWrite(fos);
} catch (IOException e) { } catch (IOException e) {
Log.wtf(TAG, "problem writing stats", e); Log.wtf(TAG, "problem writing stats", e);
if (fos != null) { if (fos != null) {
mNetworkFile.failWrite(fos); outputFile.failWrite(fos);
} }
} }
} }
@@ -1280,9 +1365,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
pw.print(" ident="); pw.println(ident.toString()); pw.print(" ident="); pw.println(ident.toString());
} }
pw.println("Known historical stats:"); pw.println("Known historical dev stats:");
for (NetworkIdentitySet ident : mNetworkStats.keySet()) { for (NetworkIdentitySet ident : mNetworkDevStats.keySet()) {
final NetworkStatsHistory history = mNetworkStats.get(ident); final NetworkStatsHistory history = mNetworkDevStats.get(ident);
pw.print(" ident="); pw.println(ident.toString());
history.dump(" ", pw, fullHistory);
}
pw.println("Known historical xt stats:");
for (NetworkIdentitySet ident : mNetworkXtStats.keySet()) {
final NetworkStatsHistory history = mNetworkXtStats.get(ident);
pw.print(" ident="); pw.println(ident.toString()); pw.print(" ident="); pw.println(ident.toString());
history.dump(" ", pw, fullHistory); history.dump(" ", pw, fullHistory);
} }
@@ -1333,10 +1425,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final List<ApplicationInfo> installedApps = mContext final List<ApplicationInfo> installedApps = mContext
.getPackageManager().getInstalledApplications(0); .getPackageManager().getInstalledApplications(0);
mNetworkStats.clear(); mNetworkDevStats.clear();
mNetworkXtStats.clear();
mUidStats.clear(); mUidStats.clear();
for (NetworkIdentitySet ident : mActiveIfaces.values()) { for (NetworkIdentitySet ident : mActiveIfaces.values()) {
findOrCreateNetworkStatsLocked(ident).generateRandom(NET_START, NET_END, NET_RX_BYTES, findOrCreateNetworkDevStatsLocked(ident).generateRandom(NET_START, NET_END,
NET_RX_BYTES, NET_RX_PACKETS, NET_TX_BYTES, NET_TX_PACKETS, 0L);
findOrCreateNetworkXtStatsLocked(ident).generateRandom(NET_START, NET_END, NET_RX_BYTES,
NET_RX_PACKETS, NET_TX_BYTES, NET_TX_PACKETS, 0L); NET_RX_PACKETS, NET_TX_BYTES, NET_TX_PACKETS, 0L);
for (ApplicationInfo info : installedApps) { for (ApplicationInfo info : installedApps) {
@@ -1369,6 +1464,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
} }
private static NetworkStats computeNetworkXtSnapshotFromUid(NetworkStats uidSnapshot) {
return uidSnapshot.groupedByIface();
}
private int estimateNetworkBuckets() { private int estimateNetworkBuckets() {
return (int) (mSettings.getNetworkMaxHistory() / mSettings.getNetworkBucketDuration()); return (int) (mSettings.getNetworkMaxHistory() / mSettings.getNetworkBucketDuration());
} }

View File

@@ -32,6 +32,7 @@ import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll; import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi; import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.UID_REMOVED; import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -179,6 +180,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay(); replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE)); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -232,6 +234,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay(); replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE)); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -327,6 +330,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay(); replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE)); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -378,6 +382,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkState(buildMobile3gState(IMSI_1));
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay(); replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE)); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -459,6 +464,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay(); replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE)); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -518,6 +524,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkState(buildMobile3gState(IMSI_1));
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay(); replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE)); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -585,6 +592,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay(); replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE)); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -648,6 +656,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildWifiState()); expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay(); replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE)); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
@@ -705,6 +714,42 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
verifyAndReset(); verifyAndReset();
} }
public void testTethering() throws Exception {
// pretend first mobile network comes online
expectCurrentTime();
expectDefaultSettings();
expectNetworkState(buildMobile3gState(IMSI_1));
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
verifyAndReset();
// create some tethering traffic
incrementCurrentTime(HOUR_IN_MILLIS);
expectCurrentTime();
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L));
final String[] tetherIfacePairs = new String[] { TEST_IFACE, "wlan0" };
expectNetworkStatsPoll(tetherIfacePairs, new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, 0L));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// verify service recorded history
assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0);
assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 0);
assertUidTotal(sTemplateImsi1, UID_TETHERING, 1920L, 14L, 384L, 2L, 0);
verifyAndReset();
}
private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long rxPackets, private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long rxPackets,
long txBytes, long txPackets, int operations) { long txBytes, long txPackets, int operations) {
final NetworkStatsHistory history = mService.getHistoryForNetwork(template, FIELD_ALL); final NetworkStatsHistory history = mService.getHistoryForNetwork(template, FIELD_ALL);
@@ -774,9 +819,16 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
} }
private void expectNetworkStatsPoll() throws Exception { private void expectNetworkStatsPoll() throws Exception {
expectNetworkStatsPoll(new String[0], new NetworkStats(getElapsedRealtime(), 0));
}
private void expectNetworkStatsPoll(String[] tetherIfacePairs, NetworkStats tetherStats)
throws Exception {
mNetManager.setGlobalAlert(anyLong()); mNetManager.setGlobalAlert(anyLong());
expectLastCall().anyTimes(); expectLastCall().anyTimes();
expect(mConnManager.getTetheredIfacePairs()).andReturn(null).anyTimes(); expect(mConnManager.getTetheredIfacePairs()).andReturn(tetherIfacePairs).anyTimes();
expect(mNetManager.getNetworkStatsTethering(eq(tetherIfacePairs)))
.andReturn(tetherStats).anyTimes();
} }
private void assertStatsFilesExist(boolean exist) { private void assertStatsFilesExist(boolean exist) {