diff options
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/net/NetworkStatsHistory.java | 40 | ||||
| -rw-r--r-- | core/java/android/net/TrafficStats.java | 12 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java | 58 | ||||
| -rw-r--r-- | services/java/com/android/server/NetworkManagementService.java | 12 | ||||
| -rw-r--r-- | services/java/com/android/server/ThrottleService.java | 5 |
6 files changed, 90 insertions, 38 deletions
diff --git a/api/current.txt b/api/current.txt index cd85eea7db6e..d25ff13af63a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11662,6 +11662,7 @@ package android.net { method public static long getUidUdpRxPackets(int); method public static long getUidUdpTxBytes(int); method public static long getUidUdpTxPackets(int); + method public static void incrementOperationCount(int); method public static void incrementOperationCount(int, int); method public static void setThreadStatsTag(int); method public static deprecated void setThreadStatsTag(java.lang.String); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index b4f15acff1c9..b19949e39d5b 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -53,18 +53,21 @@ import java.util.Random; public class NetworkStatsHistory implements Parcelable { private static final int VERSION_INIT = 1; private static final int VERSION_ADD_PACKETS = 2; + private static final int VERSION_ADD_ACTIVE = 3; - public static final int FIELD_RX_BYTES = 0x01; - public static final int FIELD_RX_PACKETS = 0x02; - public static final int FIELD_TX_BYTES = 0x04; - public static final int FIELD_TX_PACKETS = 0x08; - public static final int FIELD_OPERATIONS = 0x10; + public static final int FIELD_ACTIVE_TIME = 0x01; + public static final int FIELD_RX_BYTES = 0x02; + public static final int FIELD_RX_PACKETS = 0x04; + public static final int FIELD_TX_BYTES = 0x08; + public static final int FIELD_TX_PACKETS = 0x10; + public static final int FIELD_OPERATIONS = 0x20; public static final int FIELD_ALL = 0xFFFFFFFF; private long bucketDuration; private int bucketCount; private long[] bucketStart; + private long[] activeTime; private long[] rxBytes; private long[] rxPackets; private long[] txBytes; @@ -74,8 +77,9 @@ public class NetworkStatsHistory implements Parcelable { public static class Entry { public static final long UNKNOWN = -1; - public long bucketStart; public long bucketDuration; + public long bucketStart; + public long activeTime; public long rxBytes; public long rxPackets; public long txBytes; @@ -94,6 +98,7 @@ public class NetworkStatsHistory implements Parcelable { public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) { this.bucketDuration = bucketDuration; bucketStart = new long[initialSize]; + if ((fields & FIELD_ACTIVE_TIME) != 0) activeTime = new long[initialSize]; if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize]; if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize]; if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize]; @@ -105,6 +110,7 @@ public class NetworkStatsHistory implements Parcelable { public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); + activeTime = readLongArray(in); rxBytes = readLongArray(in); rxPackets = readLongArray(in); txBytes = readLongArray(in); @@ -117,6 +123,7 @@ public class NetworkStatsHistory implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeLong(bucketDuration); writeLongArray(out, bucketStart, bucketCount); + writeLongArray(out, activeTime, bucketCount); writeLongArray(out, rxBytes, bucketCount); writeLongArray(out, rxPackets, bucketCount); writeLongArray(out, txBytes, bucketCount); @@ -138,9 +145,12 @@ public class NetworkStatsHistory implements Parcelable { bucketCount = bucketStart.length; break; } - case VERSION_ADD_PACKETS: { + case VERSION_ADD_PACKETS: + case VERSION_ADD_ACTIVE: { bucketDuration = in.readLong(); bucketStart = readVarLongArray(in); + activeTime = (version >= VERSION_ADD_ACTIVE) ? readVarLongArray(in) + : new long[bucketStart.length]; rxBytes = readVarLongArray(in); rxPackets = readVarLongArray(in); txBytes = readVarLongArray(in); @@ -156,9 +166,10 @@ public class NetworkStatsHistory implements Parcelable { } public void writeToStream(DataOutputStream out) throws IOException { - out.writeInt(VERSION_ADD_PACKETS); + out.writeInt(VERSION_ADD_ACTIVE); out.writeLong(bucketDuration); writeVarLongArray(out, bucketStart, bucketCount); + writeVarLongArray(out, activeTime, bucketCount); writeVarLongArray(out, rxBytes, bucketCount); writeVarLongArray(out, rxPackets, bucketCount); writeVarLongArray(out, txBytes, bucketCount); @@ -202,6 +213,7 @@ public class NetworkStatsHistory implements Parcelable { final Entry entry = recycle != null ? recycle : new Entry(); entry.bucketStart = bucketStart[i]; entry.bucketDuration = bucketDuration; + entry.activeTime = getLong(activeTime, i, UNKNOWN); entry.rxBytes = getLong(rxBytes, i, UNKNOWN); entry.rxPackets = getLong(rxPackets, i, UNKNOWN); entry.txBytes = getLong(txBytes, i, UNKNOWN); @@ -252,8 +264,9 @@ public class NetworkStatsHistory implements Parcelable { final long fracRxPackets = entry.rxPackets * overlap / duration; final long fracTxBytes = entry.txBytes * overlap / duration; final long fracTxPackets = entry.txPackets * overlap / duration; - final int fracOperations = (int) (entry.operations * overlap / duration); + final long fracOperations = entry.operations * overlap / duration; + addLong(activeTime, i, overlap); addLong(rxBytes, i, fracRxBytes); entry.rxBytes -= fracRxBytes; addLong(rxPackets, i, fracRxPackets); entry.rxPackets -= fracRxPackets; addLong(txBytes, i, fracTxBytes); entry.txBytes -= fracTxBytes; @@ -311,6 +324,7 @@ public class NetworkStatsHistory implements Parcelable { if (bucketCount >= bucketStart.length) { final int newLength = Math.max(bucketStart.length, 10) * 3 / 2; bucketStart = Arrays.copyOf(bucketStart, newLength); + if (activeTime != null) activeTime = Arrays.copyOf(activeTime, newLength); if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength); if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength); if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength); @@ -324,6 +338,7 @@ public class NetworkStatsHistory implements Parcelable { final int length = bucketCount - index; System.arraycopy(bucketStart, index, bucketStart, dstPos, length); + if (activeTime != null) System.arraycopy(activeTime, index, activeTime, dstPos, length); if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length); if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length); if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length); @@ -332,6 +347,7 @@ public class NetworkStatsHistory implements Parcelable { } bucketStart[index] = start; + setLong(activeTime, index, 0L); setLong(rxBytes, index, 0L); setLong(rxPackets, index, 0L); setLong(txBytes, index, 0L); @@ -357,6 +373,7 @@ public class NetworkStatsHistory implements Parcelable { if (i > 0) { final int length = bucketStart.length; bucketStart = Arrays.copyOfRange(bucketStart, i, length); + if (activeTime != null) activeTime = Arrays.copyOfRange(activeTime, i, length); if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length); if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length); if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length); @@ -380,8 +397,9 @@ public class NetworkStatsHistory implements Parcelable { */ public Entry getValues(long start, long end, long now, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); - entry.bucketStart = start; entry.bucketDuration = end - start; + entry.bucketStart = start; + entry.activeTime = activeTime != null ? 0 : UNKNOWN; entry.rxBytes = rxBytes != null ? 0 : UNKNOWN; entry.rxPackets = rxPackets != null ? 0 : UNKNOWN; entry.txBytes = txBytes != null ? 0 : UNKNOWN; @@ -404,6 +422,7 @@ public class NetworkStatsHistory implements Parcelable { if (overlap <= 0) continue; // integer math each time is faster than floating point + if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketDuration; if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration; if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration; if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration; @@ -463,6 +482,7 @@ public class NetworkStatsHistory implements Parcelable { for (int i = start; i < bucketCount; i++) { pw.print(prefix); pw.print(" bucketStart="); pw.print(bucketStart[i]); + if (activeTime != null) pw.print(" activeTime="); pw.print(activeTime[i]); if (rxBytes != null) pw.print(" rxBytes="); pw.print(rxBytes[i]); if (rxPackets != null) pw.print(" rxPackets="); pw.print(rxPackets[i]); if (txBytes != null) pw.print(" txBytes="); pw.print(txBytes[i]); diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index c2c5c183d337..ec3b1e147781 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -198,6 +198,18 @@ public class TrafficStats { } /** + * Increment count of network operations performed under the accounting tag + * currently active on the calling thread. This can be used to derive + * bytes-per-operation. + * + * @param operationCount Number of operations to increment count by. + */ + public static void incrementOperationCount(int operationCount) { + final int tag = getThreadStatsTag(); + incrementOperationCount(tag, operationCount); + } + + /** * Increment count of network operations performed under the given * accounting tag. This can be used to derive bytes-per-operation. * diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java index 4db4ea52d527..b888d9a22316 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java @@ -99,7 +99,7 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); assertEquals(1, stats.size()); - assertValues(stats, 0, 1024L, 10L, 2048L, 20L, 2L); + assertValues(stats, 0, SECOND_IN_MILLIS, 1024L, 10L, 2048L, 20L, 2L); } public void testRecordEqualBuckets() throws Exception { @@ -112,8 +112,8 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { new NetworkStats.Entry(1024L, 10L, 128L, 2L, 2L)); assertEquals(2, stats.size()); - assertValues(stats, 0, 512L, 5L, 64L, 1L, 1L); - assertValues(stats, 1, 512L, 5L, 64L, 1L, 1L); + assertValues(stats, 0, HOUR_IN_MILLIS / 2, 512L, 5L, 64L, 1L, 1L); + assertValues(stats, 1, HOUR_IN_MILLIS / 2, 512L, 5L, 64L, 1L, 1L); } public void testRecordTouchingBuckets() throws Exception { @@ -129,11 +129,11 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { assertEquals(3, stats.size()); // first bucket should have (1/20 of value) - assertValues(stats, 0, 50L, 100L, 250L, 500L, 5L); + assertValues(stats, 0, MINUTE_IN_MILLIS, 50L, 100L, 250L, 500L, 5L); // second bucket should have (15/20 of value) - assertValues(stats, 1, 750L, 1500L, 3750L, 7500L, 75L); + assertValues(stats, 1, 15 * MINUTE_IN_MILLIS, 750L, 1500L, 3750L, 7500L, 75L); // final bucket should have (4/20 of value) - assertValues(stats, 2, 200L, 400L, 1000L, 2000L, 20L); + assertValues(stats, 2, 4 * MINUTE_IN_MILLIS, 200L, 400L, 1000L, 2000L, 20L); } public void testRecordGapBuckets() throws Exception { @@ -150,8 +150,8 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { // we should have two buckets, far apart from each other assertEquals(2, stats.size()); - assertValues(stats, 0, 128L, 2L, 256L, 4L, 1L); - assertValues(stats, 1, 64L, 1L, 512L, 8L, 2L); + assertValues(stats, 0, SECOND_IN_MILLIS, 128L, 2L, 256L, 4L, 1L); + assertValues(stats, 1, SECOND_IN_MILLIS, 64L, 1L, 512L, 8L, 2L); // now record something in middle, spread across two buckets final long middleStart = TEST_START + DAY_IN_MILLIS; @@ -161,10 +161,10 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { // now should have four buckets, with new record in middle two buckets assertEquals(4, stats.size()); - assertValues(stats, 0, 128L, 2L, 256L, 4L, 1L); - assertValues(stats, 1, 1024L, 2L, 1024L, 2L, 1L); - assertValues(stats, 2, 1024L, 2L, 1024L, 2L, 1L); - assertValues(stats, 3, 64L, 1L, 512L, 8L, 2L); + assertValues(stats, 0, SECOND_IN_MILLIS, 128L, 2L, 256L, 4L, 1L); + assertValues(stats, 1, HOUR_IN_MILLIS, 1024L, 2L, 1024L, 2L, 1L); + assertValues(stats, 2, HOUR_IN_MILLIS, 1024L, 2L, 1024L, 2L, 1L); + assertValues(stats, 3, SECOND_IN_MILLIS, 64L, 1L, 512L, 8L, 2L); } public void testRecordOverlapBuckets() throws Exception { @@ -180,8 +180,8 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { // should have two buckets, with some data mixed together assertEquals(2, stats.size()); - assertValues(stats, 0, 768L, 7L, 768L, 7L, 6L); - assertValues(stats, 1, 512L, 5L, 512L, 5L, 5L); + assertValues(stats, 0, SECOND_IN_MILLIS + (HOUR_IN_MILLIS / 2), 768L, 7L, 768L, 7L, 6L); + assertValues(stats, 1, (HOUR_IN_MILLIS / 2), 512L, 5L, 512L, 5L, 5L); } public void testRecordEntireGapIdentical() throws Exception { @@ -345,11 +345,10 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { history.recordData(0, MINUTE_IN_MILLIS, new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L)); - history.recordData(0, MINUTE_IN_MILLIS * 2, + history.recordData(0, 2 * MINUTE_IN_MILLIS, new NetworkStats.Entry(2L, 2L, 2L, 2L, 2L)); - assertValues( - history, Long.MIN_VALUE, Long.MAX_VALUE, 1026L, UNKNOWN, 2050L, UNKNOWN, UNKNOWN); + assertFullValues(history, UNKNOWN, 1026L, UNKNOWN, 2050L, UNKNOWN, UNKNOWN); } public void testIgnoreFieldsRecordIn() throws Exception { @@ -361,7 +360,7 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L)); partial.recordEntireHistory(full); - assertValues(partial, Long.MIN_VALUE, Long.MAX_VALUE, UNKNOWN, 10L, UNKNOWN, UNKNOWN, 4L); + assertFullValues(partial, UNKNOWN, UNKNOWN, 10L, UNKNOWN, UNKNOWN, 4L); } public void testIgnoreFieldsRecordOut() throws Exception { @@ -373,12 +372,12 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L)); full.recordEntireHistory(partial); - assertValues(full, Long.MIN_VALUE, Long.MAX_VALUE, 0L, 10L, 0L, 0L, 4L); + assertFullValues(full, MINUTE_IN_MILLIS, 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, + before.recordData(0, 4 * MINUTE_IN_MILLIS, 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)); @@ -391,8 +390,8 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { 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); + assertFullValues(before, 5 * MINUTE_IN_MILLIS, 1034L, 30L, 2078L, 60L, 54L); + assertFullValues(after, 5 * MINUTE_IN_MILLIS, 1034L, 30L, 2078L, 60L, 54L); } public void testVarLong() throws Exception { @@ -441,9 +440,10 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { assertEquals("unexpected txBytes", txBytes, entry.txBytes); } - private static void assertValues(NetworkStatsHistory stats, int index, long rxBytes, - long rxPackets, long txBytes, long txPackets, long operations) { + private static void assertValues(NetworkStatsHistory stats, int index, long activeTime, + long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { final NetworkStatsHistory.Entry entry = stats.getValues(index, null); + assertEquals("unexpected activeTime", activeTime, entry.activeTime); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); assertEquals("unexpected txBytes", txBytes, entry.txBytes); @@ -451,9 +451,17 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { assertEquals("unexpected operations", operations, entry.operations); } - private static void assertValues(NetworkStatsHistory stats, long start, long end, long rxBytes, + private static void assertFullValues(NetworkStatsHistory stats, long activeTime, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + assertValues(stats, Long.MIN_VALUE, Long.MAX_VALUE, activeTime, rxBytes, rxPackets, txBytes, + txPackets, operations); + } + + private static void assertValues(NetworkStatsHistory stats, long start, long end, + long activeTime, long rxBytes, long rxPackets, long txBytes, long txPackets, + long operations) { final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); + assertEquals("unexpected activeTime", activeTime, entry.activeTime); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); assertEquals("unexpected txBytes", txBytes, entry.txBytes); diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index c679dcf9ac7d..e72d09fe0098 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -1063,8 +1063,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub Slog.w(TAG, "problem parsing stats row '" + line + "': " + e); } } + } catch (NullPointerException e) { + throw new IllegalStateException("problem parsing stats: " + e); + } catch (NumberFormatException e) { + throw new IllegalStateException("problem parsing stats: " + e); } catch (IOException e) { - Slog.w(TAG, "problem parsing stats: " + e); + throw new IllegalStateException("problem parsing stats: " + e); } finally { IoUtils.closeQuietly(reader); } @@ -1345,8 +1349,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub Slog.w(TAG, "problem parsing stats row '" + line + "': " + e); } } + } catch (NullPointerException e) { + throw new IllegalStateException("problem parsing stats: " + e); + } catch (NumberFormatException e) { + throw new IllegalStateException("problem parsing stats: " + e); } catch (IOException e) { - Slog.w(TAG, "problem parsing stats: " + e); + throw new IllegalStateException("problem parsing stats: " + e); } finally { IoUtils.closeQuietly(reader); } diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java index 24b6ac3c3774..215514785425 100644 --- a/services/java/com/android/server/ThrottleService.java +++ b/services/java/com/android/server/ThrottleService.java @@ -532,9 +532,12 @@ public class ThrottleService extends IThrottleManager.Stub { mLastRead = 0; mLastWrite = 0; } + } catch (IllegalStateException e) { + Slog.e(TAG, "problem during onPollAlarm: " + e); } catch (RemoteException e) { - Slog.e(TAG, "got remoteException in onPollAlarm:" + e); + Slog.e(TAG, "problem during onPollAlarm: " + e); } + // don't count this data if we're roaming. boolean roaming = "true".equals( SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING)); |