Merge "Return stats from inactive ifaces, packet counts."
This commit is contained in:
@@ -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>() {
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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();
|
||||
|
||||
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);
|
||||
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"));
|
||||
|
||||
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");
|
||||
|
||||
8
services/tests/servicestests/res/raw/net_dev_typical
Normal file
8
services/tests/servicestests/res/raw/net_dev_typical
Normal file
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user