diff options
author | Jeff Sharkey <jsharkey@android.com> | 2011-07-11 14:36:15 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2011-07-11 14:39:56 -0700 |
commit | fd8be3e5e7420f3cca591daeec8a44487f5f65aa (patch) | |
tree | a19cda042b7d7d40e0db95fb7c758562316b101d | |
parent | ddafb64f94053aeafcaf6b6cb6073ed4cb56dacb (diff) | |
download | frameworks_base-fd8be3e5e7420f3cca591daeec8a44487f5f65aa.zip frameworks_base-fd8be3e5e7420f3cca591daeec8a44487f5f65aa.tar.gz frameworks_base-fd8be3e5e7420f3cca591daeec8a44487f5f65aa.tar.bz2 |
Return stats from inactive ifaces, packet counts.
When an iface goes inactive, xt_qtaguid maintains historical counters
instead of discarding. Now reading and returning those values in
NetworkManagementService summary calls. Tests to verify stats are
returned.
Modify NetworkStats to include rxPackets and txPackets values, and
move to Entry to eventually hide internal storage details.
Bug: 4984539
Change-Id: I1ba0bb5580c62e946d9dff2cc2a6f64aff403efc
5 files changed, 290 insertions, 63 deletions
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 9d40c42..a4c66e4 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -43,17 +43,41 @@ public class NetworkStats implements Parcelable { /** {@link #tag} value for without tag. */ public static final int TAG_NONE = 0; + // TODO: move public fields to Entry accessors, then undeprecate + // TODO: refactor rx/tx to rxBytes/txBytes + /** * {@link SystemClock#elapsedRealtime()} timestamp when this data was * generated. */ + @Deprecated public final long elapsedRealtime; + @Deprecated public int size; + @Deprecated public String[] iface; + @Deprecated public int[] uid; + @Deprecated public int[] tag; + @Deprecated public long[] rx; + @Deprecated + public long[] rxPackets; + @Deprecated public long[] tx; + @Deprecated + public long[] txPackets; + + public static class Entry { + public String iface; + public int uid; + public int tag; + public long rxBytes; + public long rxPackets; + public long txBytes; + public long txPackets; + } public NetworkStats(long elapsedRealtime, int initialSize) { this.elapsedRealtime = elapsedRealtime; @@ -62,7 +86,9 @@ public class NetworkStats implements Parcelable { this.uid = new int[initialSize]; this.tag = new int[initialSize]; this.rx = new long[initialSize]; + this.rxPackets = new long[initialSize]; this.tx = new long[initialSize]; + this.txPackets = new long[initialSize]; } public NetworkStats(Parcel parcel) { @@ -72,38 +98,82 @@ public class NetworkStats implements Parcelable { uid = parcel.createIntArray(); tag = parcel.createIntArray(); rx = parcel.createLongArray(); + rxPackets = parcel.createLongArray(); tx = parcel.createLongArray(); + txPackets = parcel.createLongArray(); } /** * Add new stats entry with given values. */ public NetworkStats addEntry(String iface, int uid, int tag, long rx, long tx) { + final Entry entry = new Entry(); + entry.iface = iface; + entry.uid = uid; + entry.tag = tag; + entry.rxBytes = rx; + entry.txBytes = tx; + return addValues(entry); + } + + /** + * Add new stats entry, copying from given {@link Entry}. The {@link Entry} + * object can be recycled across multiple calls. + */ + public NetworkStats addValues(Entry entry) { if (size >= this.iface.length) { - final int newLength = Math.max(this.iface.length, 10) * 3 / 2; - this.iface = Arrays.copyOf(this.iface, newLength); - this.uid = Arrays.copyOf(this.uid, newLength); - this.tag = Arrays.copyOf(this.tag, newLength); - this.rx = Arrays.copyOf(this.rx, newLength); - this.tx = Arrays.copyOf(this.tx, newLength); + final int newLength = Math.max(iface.length, 10) * 3 / 2; + iface = Arrays.copyOf(iface, newLength); + uid = Arrays.copyOf(uid, newLength); + tag = Arrays.copyOf(tag, newLength); + rx = Arrays.copyOf(rx, newLength); + rxPackets = Arrays.copyOf(rxPackets, newLength); + tx = Arrays.copyOf(tx, newLength); + txPackets = Arrays.copyOf(txPackets, newLength); } - this.iface[size] = iface; - this.uid[size] = uid; - this.tag[size] = tag; - this.rx[size] = rx; - this.tx[size] = tx; + iface[size] = entry.iface; + uid[size] = entry.uid; + tag[size] = entry.tag; + rx[size] = entry.rxBytes; + rxPackets[size] = entry.rxPackets; + tx[size] = entry.txBytes; + txPackets[size] = entry.txPackets; size++; return this; } /** + * Return specific stats entry. + */ + public Entry getValues(int i, Entry recycle) { + final Entry entry = recycle != null ? recycle : new Entry(); + entry.iface = iface[i]; + entry.uid = uid[i]; + entry.tag = tag[i]; + entry.rxBytes = rx[i]; + entry.rxPackets = rxPackets[i]; + entry.txBytes = tx[i]; + entry.txPackets = txPackets[i]; + return entry; + } + + public long getElapsedRealtime() { + return elapsedRealtime; + } + + public int size() { + return size; + } + + /** * Combine given values with an existing row, or create a new row if * {@link #findIndex(String, int, int)} is unable to find match. Can also be * used to subtract values from existing rows. */ public NetworkStats combineEntry(String iface, int uid, int tag, long rx, long tx) { + // TODO: extent to accept rxPackets/txPackets final int i = findIndex(iface, uid, tag); if (i == -1) { // only create new entry when positive contribution @@ -199,30 +269,41 @@ public class NetworkStats implements Parcelable { } // result will have our rows, and elapsed time between snapshots + final Entry entry = new Entry(); final NetworkStats result = new NetworkStats(deltaRealtime, size); for (int i = 0; i < size; i++) { - final String iface = this.iface[i]; - final int uid = this.uid[i]; - final int tag = this.tag[i]; + entry.iface = iface[i]; + entry.uid = uid[i]; + entry.tag = tag[i]; // find remote row that matches, and subtract - final int j = value.findIndex(iface, uid, tag); + final int j = value.findIndex(entry.iface, entry.uid, entry.tag); if (j == -1) { // newly appearing row, return entire value - result.addEntry(iface, uid, tag, this.rx[i], this.tx[i]); + entry.rxBytes = rx[i]; + entry.rxPackets = rxPackets[i]; + entry.txBytes = tx[i]; + entry.txPackets = txPackets[i]; } else { // existing row, subtract remote value - long rx = this.rx[i] - value.rx[j]; - long tx = this.tx[i] - value.tx[j]; - if (enforceMonotonic && (rx < 0 || tx < 0)) { + entry.rxBytes = rx[i] - value.rx[j]; + entry.rxPackets = rxPackets[i] - value.rxPackets[j]; + entry.txBytes = tx[i] - value.tx[j]; + entry.txPackets = txPackets[i] - value.txPackets[j]; + if (enforceMonotonic + && (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 + || entry.txPackets < 0)) { throw new IllegalArgumentException("found non-monotonic values"); } if (clampNegative) { - rx = Math.max(0, rx); - tx = Math.max(0, tx); + entry.rxBytes = Math.max(0, entry.rxBytes); + entry.rxPackets = Math.max(0, entry.rxPackets); + entry.txBytes = Math.max(0, entry.txBytes); + entry.txPackets = Math.max(0, entry.txPackets); } - result.addEntry(iface, uid, tag, rx, tx); } + + result.addValues(entry); } return result; @@ -235,13 +316,15 @@ public class NetworkStats implements Parcelable { public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime); - for (int i = 0; i < iface.length; i++) { + for (int i = 0; i < size; i++) { pw.print(prefix); pw.print(" iface="); pw.print(iface[i]); pw.print(" uid="); pw.print(uid[i]); pw.print(" tag="); pw.print(tag[i]); - pw.print(" rx="); pw.print(rx[i]); - pw.print(" tx="); pw.println(tx[i]); + pw.print(" rxBytes="); pw.print(rx[i]); + pw.print(" rxPackets="); pw.print(rxPackets[i]); + pw.print(" txBytes="); pw.print(tx[i]); + pw.print(" txPackets="); pw.println(txPackets[i]); } } @@ -265,7 +348,9 @@ public class NetworkStats implements Parcelable { dest.writeIntArray(uid); dest.writeIntArray(tag); dest.writeLongArray(rx); + dest.writeLongArray(rxPackets); dest.writeLongArray(tx); + dest.writeLongArray(txPackets); } public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() { diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java index 3cb64c7..82345e2 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java @@ -44,20 +44,20 @@ public class NetworkStatsTest extends TestCase { public void testAddEntryGrow() throws Exception { final NetworkStats stats = new NetworkStats(TEST_START, 2); - assertEquals(0, stats.size); + assertEquals(0, stats.size()); assertEquals(2, stats.iface.length); stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 1L, 2L); stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L); - assertEquals(2, stats.size); + assertEquals(2, stats.size()); assertEquals(2, stats.iface.length); stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 3L, 4L); stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 4L, 4L); stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 5L, 5L); - assertEquals(5, stats.size); + assertEquals(5, stats.size()); assertTrue(stats.iface.length >= 5); assertEquals(1L, stats.rx[0]); diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index da1bf83..829df39 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -77,11 +77,15 @@ class NetworkManagementService extends INetworkManagementService.Stub { /** Path to {@code /proc/uid_stat}. */ @Deprecated - private final File mProcStatsUidstat; + private final File mStatsUid; + /** Path to {@code /proc/net/dev}. */ + private final File mStatsIface; /** Path to {@code /proc/net/xt_qtaguid/stats}. */ - private final File mProcStatsNetfilter; + private final File mStatsXtUid; + /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */ + private final File mStatsXtIface; - /** {@link #mProcStatsNetfilter} headers. */ + /** {@link #mStatsXtUid} headers. */ private static final String KEY_IFACE = "iface"; private static final String KEY_TAG_HEX = "acct_tag_hex"; private static final String KEY_UID = "uid_tag_int"; @@ -137,8 +141,10 @@ class NetworkManagementService extends INetworkManagementService.Stub { mContext = context; mObservers = new ArrayList<INetworkManagementEventObserver>(); - mProcStatsUidstat = new File(procRoot, "uid_stat"); - mProcStatsNetfilter = new File(procRoot, "net/xt_qtaguid/stats"); + mStatsUid = new File(procRoot, "uid_stat"); + mStatsIface = new File(procRoot, "net/dev"); + mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); + mStatsXtIface = new File(procRoot, "net/xt_qtaguid/iface_stat"); if ("simulator".equals(SystemProperties.get("ro.product.device"))) { return; @@ -161,9 +167,12 @@ class NetworkManagementService extends INetworkManagementService.Stub { } // @VisibleForTesting - public static NetworkManagementService createForTest(Context context, File procRoot) { + public static NetworkManagementService createForTest( + Context context, File procRoot, boolean bandwidthControlEnabled) { // TODO: eventually connect with mock netd - return new NetworkManagementService(context, procRoot); + final NetworkManagementService service = new NetworkManagementService(context, procRoot); + service.mBandwidthControlEnabled = bandwidthControlEnabled; + return service; } public void systemReady() { @@ -930,13 +939,68 @@ class NetworkManagementService extends INetworkManagementService.Stub { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); - final String[] ifaces = listInterfaces(); - final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), ifaces.length); + final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); + final NetworkStats.Entry entry = new NetworkStats.Entry(); + + final HashSet<String> activeIfaces = Sets.newHashSet(); + final ArrayList<String> values = Lists.newArrayList(); + + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(mStatsIface)); + + // skip first two header lines + reader.readLine(); + reader.readLine(); + + // parse remaining lines + String line; + while ((line = reader.readLine()) != null) { + splitLine(line, values); + + try { + entry.iface = values.get(0); + entry.uid = UID_ALL; + entry.tag = TAG_NONE; + entry.rxBytes = Long.parseLong(values.get(1)); + entry.rxPackets = Long.parseLong(values.get(2)); + entry.txBytes = Long.parseLong(values.get(9)); + entry.txPackets = Long.parseLong(values.get(10)); + + activeIfaces.add(entry.iface); + stats.addValues(entry); + } catch (NumberFormatException e) { + Slog.w(TAG, "problem parsing stats row '" + line + "': " + e); + } + } + } catch (IOException e) { + Slog.w(TAG, "problem parsing stats: " + e); + } finally { + IoUtils.closeQuietly(reader); + } + + if (DBG) Slog.d(TAG, "recorded active stats from " + activeIfaces); + + // splice in stats from any disabled ifaces + if (mBandwidthControlEnabled) { + final HashSet<String> xtIfaces = Sets.newHashSet(fileListWithoutNull(mStatsXtIface)); + xtIfaces.removeAll(activeIfaces); + + for (String iface : xtIfaces) { + final File ifacePath = new File(mStatsXtIface, iface); + + entry.iface = iface; + entry.uid = UID_ALL; + entry.tag = TAG_NONE; + entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes")); + entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets")); + entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes")); + entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets")); - for (String iface : ifaces) { - final long rx = getInterfaceCounter(iface, true); - final long tx = getInterfaceCounter(iface, false); - stats.addEntry(iface, UID_ALL, TAG_NONE, rx, tx); + stats.addValues(entry); + } + + if (DBG) Slog.d(TAG, "recorded stale stats from " + xtIfaces); } return stats; @@ -1063,13 +1127,15 @@ class NetworkManagementService extends INetworkManagementService.Stub { */ private NetworkStats getNetworkStatsDetailNetfilter(int limitUid) { final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24); + final NetworkStats.Entry entry = new NetworkStats.Entry(); + final ArrayList<String> keys = Lists.newArrayList(); final ArrayList<String> values = Lists.newArrayList(); final HashMap<String, String> parsed = Maps.newHashMap(); BufferedReader reader = null; try { - reader = new BufferedReader(new FileReader(mProcStatsNetfilter)); + reader = new BufferedReader(new FileReader(mStatsXtUid)); // parse first line as header String line = reader.readLine(); @@ -1081,15 +1147,16 @@ class NetworkManagementService extends INetworkManagementService.Stub { parseLine(keys, values, parsed); try { - final String iface = parsed.get(KEY_IFACE); - final int tag = NetworkManagementSocketTagger.kernelToTag( + // TODO: add rxPackets/txPackets once kernel exports + entry.iface = parsed.get(KEY_IFACE); + entry.tag = NetworkManagementSocketTagger.kernelToTag( parsed.get(KEY_TAG_HEX)); - final int uid = Integer.parseInt(parsed.get(KEY_UID)); - final long rx = Long.parseLong(parsed.get(KEY_RX)); - final long tx = Long.parseLong(parsed.get(KEY_TX)); + entry.uid = Integer.parseInt(parsed.get(KEY_UID)); + entry.rxBytes = Long.parseLong(parsed.get(KEY_RX)); + entry.txBytes = Long.parseLong(parsed.get(KEY_TX)); - if (limitUid == UID_ALL || limitUid == uid) { - stats.addEntry(iface, uid, tag, rx, tx); + if (limitUid == UID_ALL || limitUid == entry.uid) { + stats.addValues(entry); } } catch (NumberFormatException e) { Slog.w(TAG, "problem parsing stats row '" + line + "': " + e); @@ -1114,19 +1181,27 @@ class NetworkManagementService extends INetworkManagementService.Stub { private NetworkStats getNetworkStatsDetailUidstat(int limitUid) { final String[] knownUids; if (limitUid == UID_ALL) { - knownUids = mProcStatsUidstat.list(); + knownUids = fileListWithoutNull(mStatsUid); } else { knownUids = new String[] { String.valueOf(limitUid) }; } final NetworkStats stats = new NetworkStats( SystemClock.elapsedRealtime(), knownUids.length); + final NetworkStats.Entry entry = new NetworkStats.Entry(); for (String uid : knownUids) { final int uidInt = Integer.parseInt(uid); - final File uidPath = new File(mProcStatsUidstat, uid); - final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv")); - final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd")); - stats.addEntry(IFACE_ALL, uidInt, TAG_NONE, rx, tx); + final File uidPath = new File(mStatsUid, uid); + + entry.iface = IFACE_ALL; + entry.uid = uidInt; + entry.tag = TAG_NONE; + entry.rxBytes = readSingleLongFromFile(new File(uidPath, "tcp_rcv")); + entry.rxPackets = readSingleLongFromFile(new File(uidPath, "tcp_rcv_pkt")); + entry.txBytes = readSingleLongFromFile(new File(uidPath, "tcp_snd")); + entry.txPackets = readSingleLongFromFile(new File(uidPath, "tcp_snd_pkt")); + + stats.addValues(entry); } return stats; @@ -1197,7 +1272,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { private static void splitLine(String line, ArrayList<String> outSplit) { outSplit.clear(); - final StringTokenizer t = new StringTokenizer(line); + final StringTokenizer t = new StringTokenizer(line, " \t\n\r\f:"); while (t.hasMoreTokens()) { outSplit.add(t.nextToken()); } @@ -1232,6 +1307,15 @@ class NetworkManagementService extends INetworkManagementService.Stub { } } + /** + * Wrapper for {@link File#list()} that returns empty array instead of + * {@code null}. + */ + private static String[] fileListWithoutNull(File file) { + final String[] list = file.list(); + return list != null ? list : new String[0]; + } + public void setDefaultInterfaceForDns(String iface) throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); diff --git a/services/tests/servicestests/res/raw/net_dev_typical b/services/tests/servicestests/res/raw/net_dev_typical new file mode 100644 index 0000000..290bf03 --- /dev/null +++ b/services/tests/servicestests/res/raw/net_dev_typical @@ -0,0 +1,8 @@ +Inter-| Receive | Transmit + face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed + lo: 8308 116 0 0 0 0 0 0 8308 116 0 0 0 0 0 0 +rmnet0: 1507570 2205 0 0 0 0 0 0 489339 2237 0 0 0 0 0 0 + ifb0: 52454 151 0 151 0 0 0 0 0 0 0 0 0 0 0 0 + ifb1: 52454 151 0 151 0 0 0 0 0 0 0 0 0 0 0 0 + sit0: 0 0 0 0 0 0 0 0 0 0 148 0 0 0 0 0 +ip6tnl0: 0 0 0 0 0 0 0 0 0 0 151 151 0 0 0 0 diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java index ac7cb5a..56ef995 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java @@ -16,6 +16,8 @@ package com.android.server; +import static android.net.NetworkStats.TAG_NONE; +import static android.net.NetworkStats.UID_ALL; import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import static com.android.server.NetworkManagementSocketTagger.tagToKernel; @@ -25,9 +27,11 @@ import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.LargeTest; import com.android.frameworks.servicestests.R; +import com.google.common.io.Files; import java.io.File; import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.InputStream; import java.io.OutputStream; @@ -46,14 +50,23 @@ public class NetworkManagementServiceTest extends AndroidTestCase { public void setUp() throws Exception { super.setUp(); - mTestProc = getContext().getFilesDir(); - mService = NetworkManagementService.createForTest(mContext, mTestProc); + final File canonicalFilesDir = getContext().getFilesDir().getCanonicalFile(); + mTestProc = new File(canonicalFilesDir, "proc"); + if (mTestProc.exists()) { + Files.deleteRecursively(mTestProc); + } + + mService = NetworkManagementService.createForTest(mContext, mTestProc, true); } @Override public void tearDown() throws Exception { mService = null; + if (mTestProc.exists()) { + Files.deleteRecursively(mTestProc); + } + super.tearDown(); } @@ -61,7 +74,7 @@ public class NetworkManagementServiceTest extends AndroidTestCase { stageFile(R.raw.xt_qtaguid_typical, new File(mTestProc, "net/xt_qtaguid/stats")); final NetworkStats stats = mService.getNetworkStatsDetail(); - assertEquals(31, stats.size); + assertEquals(31, stats.size()); assertStatsEntry(stats, "wlan0", 0, 0, 14615L, 4270L); assertStatsEntry(stats, "wlan0", 10004, 0, 333821L, 53558L); assertStatsEntry(stats, "wlan0", 10004, 1947740890, 18725L, 1066L); @@ -73,11 +86,37 @@ public class NetworkManagementServiceTest extends AndroidTestCase { stageFile(R.raw.xt_qtaguid_extended, new File(mTestProc, "net/xt_qtaguid/stats")); final NetworkStats stats = mService.getNetworkStatsDetail(); - assertEquals(2, stats.size); + assertEquals(2, stats.size()); assertStatsEntry(stats, "test0", 1000, 0, 1024L, 2048L); assertStatsEntry(stats, "test0", 1000, 0xF00D, 512L, 512L); } + public void testNetworkStatsSummary() throws Exception { + stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev")); + + final NetworkStats stats = mService.getNetworkStatsSummary(); + assertEquals(6, stats.size()); + assertStatsEntry(stats, "lo", UID_ALL, TAG_NONE, 8308L, 8308L); + assertStatsEntry(stats, "rmnet0", UID_ALL, TAG_NONE, 1507570L, 489339L); + assertStatsEntry(stats, "ifb0", UID_ALL, TAG_NONE, 52454L, 0L); + assertStatsEntry(stats, "ifb1", UID_ALL, TAG_NONE, 52454L, 0L); + assertStatsEntry(stats, "sit0", UID_ALL, TAG_NONE, 0L, 0L); + assertStatsEntry(stats, "ip6tnl0", UID_ALL, TAG_NONE, 0L, 0L); + } + + public void testNetworkStatsSummaryDown() throws Exception { + stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev")); + stageLong(1024L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/rx_bytes")); + stageLong(128L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/rx_packets")); + stageLong(2048L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/tx_bytes")); + stageLong(256L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/tx_packets")); + + final NetworkStats stats = mService.getNetworkStatsSummary(); + assertEquals(7, stats.size()); + assertStatsEntry(stats, "rmnet0", UID_ALL, TAG_NONE, 1507570L, 489339L); + assertStatsEntry(stats, "wlan0", UID_ALL, TAG_NONE, 1024L, 2048L); + } + public void testKernelTags() throws Exception { assertEquals("0", tagToKernel(0x0)); assertEquals("214748364800", tagToKernel(0x32)); @@ -90,7 +129,6 @@ public class NetworkManagementServiceTest extends AndroidTestCase { assertEquals(2147483647, kernelToTag("0x7fffffff00000000")); assertEquals(0, kernelToTag("0x0000000000000000")); assertEquals(2147483136, kernelToTag("0x7FFFFE0000000000")); - } /** @@ -111,11 +149,23 @@ public class NetworkManagementServiceTest extends AndroidTestCase { } } + private void stageLong(long value, File file) throws Exception { + new File(file.getParent()).mkdirs(); + FileWriter out = null; + try { + out = new FileWriter(file); + out.write(Long.toString(value)); + } finally { + IoUtils.closeQuietly(out); + } + } + private static void assertStatsEntry( - NetworkStats stats, String iface, int uid, int tag, long rx, long tx) { + NetworkStats stats, String iface, int uid, int tag, long rxBytes, long txBytes) { final int i = stats.findIndex(iface, uid, tag); - assertEquals(rx, stats.rx[i]); - assertEquals(tx, stats.tx[i]); + final NetworkStats.Entry entry = stats.getValues(i, null); + assertEquals(rxBytes, entry.rxBytes); + assertEquals(txBytes, entry.txBytes); } } |