Merge "Network stats with varint, omit parcel fields."

This commit is contained in:
Jeff Sharkey
2011-08-04 15:39:24 -07:00
committed by Android (Google) Code Review
2 changed files with 159 additions and 27 deletions

View File

@@ -16,6 +16,14 @@
package android.net; package android.net;
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkStatsHistory.FIELD_OPERATIONS;
import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
import static android.net.NetworkStatsHistory.FIELD_RX_PACKETS;
import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
import static android.net.NetworkStatsHistory.DataStreamUtils.readVarLong;
import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLong;
import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
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;
@@ -30,7 +38,10 @@ import android.util.Log;
import com.android.frameworks.coretests.R; import com.android.frameworks.coretests.R;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.util.Random; import java.util.Random;
@SmallTest @SmallTest
@@ -39,6 +50,10 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
private static final long TEST_START = 1194220800000L; private static final long TEST_START = 1194220800000L;
private static final long KB_IN_BYTES = 1024;
private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
private NetworkStatsHistory stats; private NetworkStatsHistory stats;
@Override @Override
@@ -80,10 +95,11 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
stats = new NetworkStatsHistory(BUCKET_SIZE); stats = new NetworkStatsHistory(BUCKET_SIZE);
// record data into narrow window to get single bucket // record data into narrow window to get single bucket
stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 1024L, 2048L); stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS,
new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));
assertEquals(1, stats.size()); assertEquals(1, stats.size());
assertValues(stats, 0, 1024L, 2048L); assertValues(stats, 0, 1024L, 10L, 2048L, 20L, 2L);
} }
public void testRecordEqualBuckets() throws Exception { public void testRecordEqualBuckets() throws Exception {
@@ -92,11 +108,12 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
// split equally across two buckets // split equally across two buckets
final long recordStart = TEST_START + (bucketDuration / 2); final long recordStart = TEST_START + (bucketDuration / 2);
stats.recordData(recordStart, recordStart + bucketDuration, 1024L, 128L); stats.recordData(recordStart, recordStart + bucketDuration,
new NetworkStats.Entry(1024L, 10L, 128L, 2L, 2L));
assertEquals(2, stats.size()); assertEquals(2, stats.size());
assertValues(stats, 0, 512L, 64L); assertValues(stats, 0, 512L, 5L, 64L, 1L, 1L);
assertValues(stats, 1, 512L, 64L); assertValues(stats, 1, 512L, 5L, 64L, 1L, 1L);
} }
public void testRecordTouchingBuckets() throws Exception { public void testRecordTouchingBuckets() throws Exception {
@@ -107,15 +124,16 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
// overlap into neighboring buckets. total record is 20 minutes. // overlap into neighboring buckets. total record is 20 minutes.
final long recordStart = (TEST_START + BUCKET_SIZE) - MINUTE_IN_MILLIS; final long recordStart = (TEST_START + BUCKET_SIZE) - MINUTE_IN_MILLIS;
final long recordEnd = (TEST_START + (BUCKET_SIZE * 2)) + (MINUTE_IN_MILLIS * 4); final long recordEnd = (TEST_START + (BUCKET_SIZE * 2)) + (MINUTE_IN_MILLIS * 4);
stats.recordData(recordStart, recordEnd, 1000L, 5000L); stats.recordData(recordStart, recordEnd,
new NetworkStats.Entry(1000L, 2000L, 5000L, 10000L, 100L));
assertEquals(3, stats.size()); assertEquals(3, stats.size());
// first bucket should have (1/20 of value) // first bucket should have (1/20 of value)
assertValues(stats, 0, 50L, 250L); assertValues(stats, 0, 50L, 100L, 250L, 500L, 5L);
// second bucket should have (15/20 of value) // second bucket should have (15/20 of value)
assertValues(stats, 1, 750L, 3750L); assertValues(stats, 1, 750L, 1500L, 3750L, 7500L, 75L);
// final bucket should have (4/20 of value) // final bucket should have (4/20 of value)
assertValues(stats, 2, 200L, 1000L); assertValues(stats, 2, 200L, 400L, 1000L, 2000L, 20L);
} }
public void testRecordGapBuckets() throws Exception { public void testRecordGapBuckets() throws Exception {
@@ -125,25 +143,28 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
// record some data today and next week with large gap // record some data today and next week with large gap
final long firstStart = TEST_START; final long firstStart = TEST_START;
final long lastStart = TEST_START + WEEK_IN_MILLIS; final long lastStart = TEST_START + WEEK_IN_MILLIS;
stats.recordData(firstStart, firstStart + SECOND_IN_MILLIS, 128L, 256L); stats.recordData(firstStart, firstStart + SECOND_IN_MILLIS,
stats.recordData(lastStart, lastStart + SECOND_IN_MILLIS, 64L, 512L); new NetworkStats.Entry(128L, 2L, 256L, 4L, 1L));
stats.recordData(lastStart, lastStart + SECOND_IN_MILLIS,
new NetworkStats.Entry(64L, 1L, 512L, 8L, 2L));
// we should have two buckets, far apart from each other // we should have two buckets, far apart from each other
assertEquals(2, stats.size()); assertEquals(2, stats.size());
assertValues(stats, 0, 128L, 256L); assertValues(stats, 0, 128L, 2L, 256L, 4L, 1L);
assertValues(stats, 1, 64L, 512L); assertValues(stats, 1, 64L, 1L, 512L, 8L, 2L);
// now record something in middle, spread across two buckets // now record something in middle, spread across two buckets
final long middleStart = TEST_START + DAY_IN_MILLIS; final long middleStart = TEST_START + DAY_IN_MILLIS;
final long middleEnd = middleStart + (HOUR_IN_MILLIS * 2); final long middleEnd = middleStart + (HOUR_IN_MILLIS * 2);
stats.recordData(middleStart, middleEnd, 2048L, 2048L); stats.recordData(middleStart, middleEnd,
new NetworkStats.Entry(2048L, 4L, 2048L, 4L, 2L));
// now should have four buckets, with new record in middle two buckets // now should have four buckets, with new record in middle two buckets
assertEquals(4, stats.size()); assertEquals(4, stats.size());
assertValues(stats, 0, 128L, 256L); assertValues(stats, 0, 128L, 2L, 256L, 4L, 1L);
assertValues(stats, 1, 1024L, 1024L); assertValues(stats, 1, 1024L, 2L, 1024L, 2L, 1L);
assertValues(stats, 2, 1024L, 1024L); assertValues(stats, 2, 1024L, 2L, 1024L, 2L, 1L);
assertValues(stats, 3, 64L, 512L); assertValues(stats, 3, 64L, 1L, 512L, 8L, 2L);
} }
public void testRecordOverlapBuckets() throws Exception { public void testRecordOverlapBuckets() throws Exception {
@@ -151,14 +172,16 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
stats = new NetworkStatsHistory(BUCKET_SIZE); stats = new NetworkStatsHistory(BUCKET_SIZE);
// record some data in one bucket, and another overlapping buckets // record some data in one bucket, and another overlapping buckets
stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 256L, 256L); stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS,
new NetworkStats.Entry(256L, 2L, 256L, 2L, 1L));
final long midStart = TEST_START + (HOUR_IN_MILLIS / 2); final long midStart = TEST_START + (HOUR_IN_MILLIS / 2);
stats.recordData(midStart, midStart + HOUR_IN_MILLIS, 1024L, 1024L); stats.recordData(midStart, midStart + HOUR_IN_MILLIS,
new NetworkStats.Entry(1024L, 10L, 1024L, 10L, 10L));
// should have two buckets, with some data mixed together // should have two buckets, with some data mixed together
assertEquals(2, stats.size()); assertEquals(2, stats.size());
assertValues(stats, 0, 768L, 768L); assertValues(stats, 0, 768L, 7L, 768L, 7L, 6L);
assertValues(stats, 1, 512L, 512L); assertValues(stats, 1, 512L, 5L, 512L, 5L, 5L);
} }
public void testRecordEntireGapIdentical() throws Exception { public void testRecordEntireGapIdentical() throws Exception {
@@ -283,6 +306,7 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
public void testFuzzing() throws Exception { public void testFuzzing() throws Exception {
try { try {
// fuzzing with random events, looking for crashes // fuzzing with random events, looking for crashes
final NetworkStats.Entry entry = new NetworkStats.Entry();
final Random r = new Random(); final Random r = new Random();
for (int i = 0; i < 500; i++) { for (int i = 0; i < 500; i++) {
stats = new NetworkStatsHistory(r.nextLong()); stats = new NetworkStatsHistory(r.nextLong());
@@ -291,7 +315,12 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
// add range // add range
final long start = r.nextLong(); final long start = r.nextLong();
final long end = start + r.nextInt(); final long end = start + r.nextInt();
stats.recordData(start, end, r.nextLong(), r.nextLong()); entry.rxBytes = nextPositiveLong(r);
entry.rxPackets = nextPositiveLong(r);
entry.txBytes = nextPositiveLong(r);
entry.txPackets = nextPositiveLong(r);
entry.operations = nextPositiveLong(r);
stats.recordData(start, end, entry);
} else { } else {
// trim something // trim something
stats.removeBucketsBefore(r.nextLong()); stats.removeBucketsBefore(r.nextLong());
@@ -305,6 +334,88 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
} }
} }
private static long nextPositiveLong(Random r) {
final long value = r.nextLong();
return value < 0 ? -value : value;
}
public void testIgnoreFields() throws Exception {
final NetworkStatsHistory history = new NetworkStatsHistory(
MINUTE_IN_MILLIS, 0, FIELD_RX_BYTES | FIELD_TX_BYTES);
history.recordData(0, MINUTE_IN_MILLIS,
new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
history.recordData(0, MINUTE_IN_MILLIS * 2,
new NetworkStats.Entry(2L, 2L, 2L, 2L, 2L));
assertValues(
history, Long.MIN_VALUE, Long.MAX_VALUE, 1026L, UNKNOWN, 2050L, UNKNOWN, UNKNOWN);
}
public void testIgnoreFieldsRecordIn() throws Exception {
final NetworkStatsHistory full = new NetworkStatsHistory(MINUTE_IN_MILLIS, 0, FIELD_ALL);
final NetworkStatsHistory partial = new NetworkStatsHistory(
MINUTE_IN_MILLIS, 0, FIELD_RX_PACKETS | FIELD_OPERATIONS);
full.recordData(0, MINUTE_IN_MILLIS,
new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
partial.recordEntireHistory(full);
assertValues(partial, Long.MIN_VALUE, Long.MAX_VALUE, UNKNOWN, 10L, UNKNOWN, UNKNOWN, 4L);
}
public void testIgnoreFieldsRecordOut() throws Exception {
final NetworkStatsHistory full = new NetworkStatsHistory(MINUTE_IN_MILLIS, 0, FIELD_ALL);
final NetworkStatsHistory partial = new NetworkStatsHistory(
MINUTE_IN_MILLIS, 0, FIELD_RX_PACKETS | FIELD_OPERATIONS);
partial.recordData(0, MINUTE_IN_MILLIS,
new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
full.recordEntireHistory(partial);
assertValues(full, Long.MIN_VALUE, Long.MAX_VALUE, 0L, 10L, 0L, 0L, 4L);
}
public void testSerialize() throws Exception {
final NetworkStatsHistory before = new NetworkStatsHistory(MINUTE_IN_MILLIS, 40, FIELD_ALL);
before.recordData(0, MINUTE_IN_MILLIS * 4,
new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
before.recordData(DAY_IN_MILLIS, DAY_IN_MILLIS + MINUTE_IN_MILLIS,
new NetworkStats.Entry(10L, 20L, 30L, 40L, 50L));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
before.writeToStream(new DataOutputStream(out));
out.close();
final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
final NetworkStatsHistory after = new NetworkStatsHistory(new DataInputStream(in));
// must have identical totals before and after
assertValues(before, Long.MIN_VALUE, Long.MAX_VALUE, 1034L, 30L, 2078L, 60L, 54L);
assertValues(after, Long.MIN_VALUE, Long.MAX_VALUE, 1034L, 30L, 2078L, 60L, 54L);
}
public void testVarLong() throws Exception {
assertEquals(0L, performVarLong(0L));
assertEquals(-1L, performVarLong(-1L));
assertEquals(1024L, performVarLong(1024L));
assertEquals(-1024L, performVarLong(-1024L));
assertEquals(40 * MB_IN_BYTES, performVarLong(40 * MB_IN_BYTES));
assertEquals(512 * GB_IN_BYTES, performVarLong(512 * GB_IN_BYTES));
assertEquals(Long.MIN_VALUE, performVarLong(Long.MIN_VALUE));
assertEquals(Long.MAX_VALUE, performVarLong(Long.MAX_VALUE));
assertEquals(Long.MIN_VALUE + 40, performVarLong(Long.MIN_VALUE + 40));
assertEquals(Long.MAX_VALUE - 40, performVarLong(Long.MAX_VALUE - 40));
}
private static long performVarLong(long before) throws Exception {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
writeVarLong(new DataOutputStream(out), before);
final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
return readVarLong(new DataInputStream(in));
}
private static void assertConsistent(NetworkStatsHistory stats) { private static void assertConsistent(NetworkStatsHistory stats) {
// verify timestamps are monotonic // verify timestamps are monotonic
long lastStart = Long.MIN_VALUE; long lastStart = Long.MIN_VALUE;
@@ -330,4 +441,23 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
assertEquals("unexpected txBytes", txBytes, entry.txBytes); assertEquals("unexpected txBytes", txBytes, entry.txBytes);
} }
private static void assertValues(NetworkStatsHistory stats, int index, long rxBytes,
long rxPackets, long txBytes, long txPackets, long operations) {
final NetworkStatsHistory.Entry entry = stats.getValues(index, null);
assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
assertEquals("unexpected txBytes", txBytes, entry.txBytes);
assertEquals("unexpected txPackets", txPackets, entry.txPackets);
assertEquals("unexpected operations", operations, entry.operations);
}
private static void assertValues(NetworkStatsHistory stats, long start, long end, long rxBytes,
long rxPackets, long txBytes, long txPackets, long operations) {
final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null);
assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
assertEquals("unexpected txBytes", txBytes, entry.txBytes);
assertEquals("unexpected txPackets", txPackets, entry.txPackets);
assertEquals("unexpected operations", operations, entry.operations);
}
} }

View File

@@ -25,6 +25,7 @@ import static android.net.ConnectivityManager.TYPE_WIMAX;
import static android.net.NetworkStats.IFACE_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;
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;
@@ -302,7 +303,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// verify service recorded history // verify service recorded history
history = mService.getHistoryForNetwork(sTemplateWifi); history = mService.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0);
assertEquals(HOUR_IN_MILLIS, history.getBucketDuration()); assertEquals(HOUR_IN_MILLIS, history.getBucketDuration());
assertEquals(2, history.size()); assertEquals(2, history.size());
@@ -319,7 +320,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// verify identical stats, but spread across 4 buckets now // verify identical stats, but spread across 4 buckets now
history = mService.getHistoryForNetwork(sTemplateWifi); history = mService.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0);
assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration()); assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration());
assertEquals(4, history.size()); assertEquals(4, history.size());
@@ -631,14 +632,15 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
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); final NetworkStatsHistory history = mService.getHistoryForNetwork(template, FIELD_ALL);
assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes, assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes,
txPackets, operations); txPackets, operations);
} }
private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets, private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets,
long txBytes, long txPackets, int operations) { long txBytes, long txPackets, int operations) {
final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE); final NetworkStatsHistory history = mService.getHistoryForUid(
template, uid, TAG_NONE, FIELD_ALL);
assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes, assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes,
txPackets, operations); txPackets, operations);
} }