From 188480b216491a79e96355e7ca3af3512fc81df9 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 12 Jul 2011 13:57:00 -0700 Subject: [PATCH] Hide NetworkStatsHistory internals. Instead of exposing internal storage details, offer getValues() accessor which populates values into a recycled structure. Change-Id: I5228d7099a8f61b2018a435a813435a67dae49b4 --- core/java/android/net/NetworkStats.java | 117 +++++++++--------- .../java/android/net/NetworkStatsHistory.java | 87 ++++++++----- .../server/net/NetworkStatsService.java | 83 +++++++------ 3 files changed, 164 insertions(+), 123 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index a4c66e4f64..fbff7d89fc 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -43,31 +43,19 @@ 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; + private final long elapsedRealtime; + private int size; + private String[] iface; + private int[] uid; + private int[] tag; + private long[] rxBytes; + private long[] rxPackets; + private long[] txBytes; + private long[] txPackets; public static class Entry { public String iface; @@ -77,6 +65,20 @@ public class NetworkStats implements Parcelable { public long rxPackets; public long txBytes; public long txPackets; + + public Entry() { + } + + public Entry(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes, + long txPackets) { + this.iface = iface; + this.uid = uid; + this.tag = tag; + this.rxBytes = rxBytes; + this.rxPackets = rxPackets; + this.txBytes = txBytes; + this.txPackets = txPackets; + } } public NetworkStats(long elapsedRealtime, int initialSize) { @@ -85,9 +87,9 @@ public class NetworkStats implements Parcelable { this.iface = new String[initialSize]; this.uid = new int[initialSize]; this.tag = new int[initialSize]; - this.rx = new long[initialSize]; + this.rxBytes = new long[initialSize]; this.rxPackets = new long[initialSize]; - this.tx = new long[initialSize]; + this.txBytes = new long[initialSize]; this.txPackets = new long[initialSize]; } @@ -97,23 +99,15 @@ public class NetworkStats implements Parcelable { iface = parcel.createStringArray(); uid = parcel.createIntArray(); tag = parcel.createIntArray(); - rx = parcel.createLongArray(); + rxBytes = parcel.createLongArray(); rxPackets = parcel.createLongArray(); - tx = parcel.createLongArray(); + txBytes = 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); + public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets, + long txBytes, long txPackets) { + return addValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets)); } /** @@ -126,18 +120,18 @@ public class NetworkStats implements Parcelable { iface = Arrays.copyOf(iface, newLength); uid = Arrays.copyOf(uid, newLength); tag = Arrays.copyOf(tag, newLength); - rx = Arrays.copyOf(rx, newLength); + rxBytes = Arrays.copyOf(rxBytes, newLength); rxPackets = Arrays.copyOf(rxPackets, newLength); - tx = Arrays.copyOf(tx, newLength); + txBytes = Arrays.copyOf(txBytes, newLength); txPackets = Arrays.copyOf(txPackets, newLength); } iface[size] = entry.iface; uid[size] = entry.uid; tag[size] = entry.tag; - rx[size] = entry.rxBytes; + rxBytes[size] = entry.rxBytes; rxPackets[size] = entry.rxPackets; - tx[size] = entry.txBytes; + txBytes[size] = entry.txBytes; txPackets[size] = entry.txPackets; size++; @@ -152,9 +146,9 @@ public class NetworkStats implements Parcelable { entry.iface = iface[i]; entry.uid = uid[i]; entry.tag = tag[i]; - entry.rxBytes = rx[i]; + entry.rxBytes = rxBytes[i]; entry.rxPackets = rxPackets[i]; - entry.txBytes = tx[i]; + entry.txBytes = txBytes[i]; entry.txPackets = txPackets[i]; return entry; } @@ -167,20 +161,31 @@ public class NetworkStats implements Parcelable { return size; } + // @VisibleForTesting + public int internalSize() { + return iface.length; + } + + public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets, + long txBytes, long txPackets) { + return combineValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets)); + } + /** * 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); + public NetworkStats combineValues(Entry entry) { + final int i = findIndex(entry.iface, entry.uid, entry.tag); if (i == -1) { // only create new entry when positive contribution - addEntry(iface, uid, tag, rx, tx); + addValues(entry); } else { - this.rx[i] += rx; - this.tx[i] += tx; + rxBytes[i] += entry.rxBytes; + rxPackets[i] += entry.rxPackets; + txBytes[i] += entry.txBytes; + txPackets[i] += entry.txPackets; } return this; } @@ -280,15 +285,15 @@ public class NetworkStats implements Parcelable { final int j = value.findIndex(entry.iface, entry.uid, entry.tag); if (j == -1) { // newly appearing row, return entire value - entry.rxBytes = rx[i]; + entry.rxBytes = rxBytes[i]; entry.rxPackets = rxPackets[i]; - entry.txBytes = tx[i]; + entry.txBytes = txBytes[i]; entry.txPackets = txPackets[i]; } else { // existing row, subtract remote value - entry.rxBytes = rx[i] - value.rx[j]; + entry.rxBytes = rxBytes[i] - value.rxBytes[j]; entry.rxPackets = rxPackets[i] - value.rxPackets[j]; - entry.txBytes = tx[i] - value.tx[j]; + entry.txBytes = txBytes[i] - value.txBytes[j]; entry.txPackets = txPackets[i] - value.txPackets[j]; if (enforceMonotonic && (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 @@ -321,9 +326,9 @@ public class NetworkStats implements Parcelable { pw.print(" iface="); pw.print(iface[i]); pw.print(" uid="); pw.print(uid[i]); pw.print(" tag="); pw.print(tag[i]); - pw.print(" rxBytes="); pw.print(rx[i]); + pw.print(" rxBytes="); pw.print(rxBytes[i]); pw.print(" rxPackets="); pw.print(rxPackets[i]); - pw.print(" txBytes="); pw.print(tx[i]); + pw.print(" txBytes="); pw.print(txBytes[i]); pw.print(" txPackets="); pw.println(txPackets[i]); } } @@ -347,9 +352,9 @@ public class NetworkStats implements Parcelable { dest.writeStringArray(iface); dest.writeIntArray(uid); dest.writeIntArray(tag); - dest.writeLongArray(rx); + dest.writeLongArray(rxBytes); dest.writeLongArray(rxPackets); - dest.writeLongArray(tx); + dest.writeLongArray(txBytes); dest.writeLongArray(txPackets); } diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index dd2945ca18..b0930b2ae2 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -43,13 +43,20 @@ public class NetworkStatsHistory implements Parcelable { private static final int VERSION_INIT = 1; // TODO: teach about varint encoding to use less disk space + // TODO: extend to record rxPackets/txPackets - public final long bucketDuration; + private final long bucketDuration; + private int bucketCount; + private long[] bucketStart; + private long[] rxBytes; + private long[] txBytes; - public int bucketCount; - public long[] bucketStart; - public long[] rx; - public long[] tx; + public static class Entry { + public long bucketStart; + public long bucketDuration; + public long rxBytes; + public long txBytes; + } public NetworkStatsHistory(long bucketDuration) { this(bucketDuration, 10); @@ -58,16 +65,16 @@ public class NetworkStatsHistory implements Parcelable { public NetworkStatsHistory(long bucketDuration, int initialSize) { this.bucketDuration = bucketDuration; bucketStart = new long[initialSize]; - rx = new long[initialSize]; - tx = new long[initialSize]; + rxBytes = new long[initialSize]; + txBytes = new long[initialSize]; bucketCount = 0; } public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); - rx = in.createLongArray(); - tx = in.createLongArray(); + rxBytes = in.createLongArray(); + txBytes = in.createLongArray(); bucketCount = bucketStart.length; } @@ -75,8 +82,8 @@ public class NetworkStatsHistory implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeLong(bucketDuration); writeLongArray(out, bucketStart, bucketCount); - writeLongArray(out, rx, bucketCount); - writeLongArray(out, tx, bucketCount); + writeLongArray(out, rxBytes, bucketCount); + writeLongArray(out, txBytes, bucketCount); } public NetworkStatsHistory(DataInputStream in) throws IOException { @@ -85,8 +92,8 @@ public class NetworkStatsHistory implements Parcelable { case VERSION_INIT: { bucketDuration = in.readLong(); bucketStart = readLongArray(in); - rx = readLongArray(in); - tx = readLongArray(in); + rxBytes = readLongArray(in); + txBytes = readLongArray(in); bucketCount = bucketStart.length; break; } @@ -100,8 +107,8 @@ public class NetworkStatsHistory implements Parcelable { out.writeInt(VERSION_INIT); out.writeLong(bucketDuration); writeLongArray(out, bucketStart, bucketCount); - writeLongArray(out, rx, bucketCount); - writeLongArray(out, tx, bucketCount); + writeLongArray(out, rxBytes, bucketCount); + writeLongArray(out, txBytes, bucketCount); } /** {@inheritDoc} */ @@ -109,6 +116,26 @@ public class NetworkStatsHistory implements Parcelable { return 0; } + public int size() { + return bucketCount; + } + + public long getBucketDuration() { + return bucketDuration; + } + + /** + * Return specific stats entry. + */ + public Entry getValues(int i, Entry recycle) { + final Entry entry = recycle != null ? recycle : new Entry(); + entry.bucketStart = bucketStart[i]; + entry.bucketDuration = bucketDuration; + entry.rxBytes = rxBytes[i]; + entry.txBytes = txBytes[i]; + return entry; + } + /** * Record that data traffic occurred in the given time range. Will * distribute across internal buckets, creating new buckets as needed. @@ -135,8 +162,8 @@ public class NetworkStatsHistory implements Parcelable { final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); if (overlap > 0) { - this.rx[i] += rx * overlap / duration; - this.tx[i] += tx * overlap / duration; + this.rxBytes[i] += rx * overlap / duration; + this.txBytes[i] += tx * overlap / duration; } } } @@ -149,7 +176,7 @@ public class NetworkStatsHistory implements Parcelable { for (int i = 0; i < input.bucketCount; i++) { final long start = input.bucketStart[i]; final long end = start + input.bucketDuration; - recordData(start, end, input.rx[i], input.tx[i]); + recordData(start, end, input.rxBytes[i], input.txBytes[i]); } } @@ -179,8 +206,8 @@ public class NetworkStatsHistory implements Parcelable { if (bucketCount >= bucketStart.length) { final int newLength = Math.max(bucketStart.length, 10) * 3 / 2; bucketStart = Arrays.copyOf(bucketStart, newLength); - rx = Arrays.copyOf(rx, newLength); - tx = Arrays.copyOf(tx, newLength); + rxBytes = Arrays.copyOf(rxBytes, newLength); + txBytes = Arrays.copyOf(txBytes, newLength); } // create gap when inserting bucket in middle @@ -189,13 +216,13 @@ public class NetworkStatsHistory implements Parcelable { final int length = bucketCount - index; System.arraycopy(bucketStart, index, bucketStart, dstPos, length); - System.arraycopy(rx, index, rx, dstPos, length); - System.arraycopy(tx, index, tx, dstPos, length); + System.arraycopy(rxBytes, index, rxBytes, dstPos, length); + System.arraycopy(txBytes, index, txBytes, dstPos, length); } bucketStart[index] = start; - rx[index] = 0; - tx[index] = 0; + rxBytes[index] = 0; + txBytes[index] = 0; bucketCount++; } @@ -216,8 +243,8 @@ public class NetworkStatsHistory implements Parcelable { if (i > 0) { final int length = bucketStart.length; bucketStart = Arrays.copyOfRange(bucketStart, i, length); - rx = Arrays.copyOfRange(rx, i, length); - tx = Arrays.copyOfRange(tx, i, length); + rxBytes = Arrays.copyOfRange(rxBytes, i, length); + txBytes = Arrays.copyOfRange(txBytes, i, length); bucketCount -= i; } } @@ -241,8 +268,8 @@ public class NetworkStatsHistory implements Parcelable { final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); if (overlap > 0) { - rx += this.rx[i] * overlap / bucketDuration; - tx += this.tx[i] * overlap / bucketDuration; + rx += this.rxBytes[i] * overlap / bucketDuration; + tx += this.txBytes[i] * overlap / bucketDuration; } } @@ -292,8 +319,8 @@ public class NetworkStatsHistory implements Parcelable { for (int i = start; i < bucketCount; i++) { pw.print(prefix); pw.print(" bucketStart="); pw.print(bucketStart[i]); - pw.print(" rx="); pw.print(rx[i]); - pw.print(" tx="); pw.println(tx[i]); + pw.print(" rxBytes="); pw.print(rxBytes[i]); + pw.print(" txBytes="); pw.println(txBytes[i]); } } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index b6834f6634..872438c5e5 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -313,22 +313,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); synchronized (mStatsLock) { - long rx = 0; - long tx = 0; - long[] networkTotal = new long[2]; + final NetworkStats stats = new NetworkStats(end - start, 1); + final NetworkStats.Entry entry = new NetworkStats.Entry(); + long[] total = new long[2]; // combine total from all interfaces that match template for (NetworkIdentitySet ident : mNetworkStats.keySet()) { if (templateMatches(template, ident)) { final NetworkStatsHistory history = mNetworkStats.get(ident); - networkTotal = history.getTotalData(start, end, networkTotal); - rx += networkTotal[0]; - tx += networkTotal[1]; + total = history.getTotalData(start, end, total); + + entry.iface = IFACE_ALL; + entry.uid = UID_ALL; + entry.tag = TAG_NONE; + entry.rxBytes = total[0]; + entry.txBytes = total[1]; + + stats.combineValues(entry); } } - final NetworkStats stats = new NetworkStats(end - start, 1); - stats.addEntry(IFACE_ALL, UID_ALL, TAG_NONE, rx, tx); return stats; } } @@ -342,6 +346,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { ensureUidStatsLoadedLocked(); final NetworkStats stats = new NetworkStats(end - start, 24); + final NetworkStats.Entry entry = new NetworkStats.Entry(); long[] total = new long[2]; for (NetworkIdentitySet ident : mUidStats.keySet()) { @@ -357,10 +362,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (tag == TAG_NONE || includeTags) { final NetworkStatsHistory history = uidStats.valueAt(i); total = history.getTotalData(start, end, total); - final long rx = total[0]; - final long tx = total[1]; - if (rx > 0 || tx > 0) { - stats.combineEntry(IFACE_ALL, uid, tag, rx, tx); + + entry.iface = IFACE_ALL; + entry.uid = uid; + entry.tag = tag; + entry.rxBytes = total[0]; + entry.txBytes = total[1]; + + if (entry.rxBytes > 0 || entry.txBytes > 0) { + stats.combineValues(entry); } } } @@ -512,10 +522,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats persistDelta = computeStatsDelta( mLastPersistNetworkSnapshot, networkSnapshot); final long persistThreshold = mSettings.getPersistThreshold(); + + NetworkStats.Entry entry = null; for (String iface : persistDelta.getUniqueIfaces()) { final int index = persistDelta.findIndex(iface, UID_ALL, TAG_NONE); - if (forcePersist || persistDelta.rx[index] > persistThreshold - || persistDelta.tx[index] > persistThreshold) { + entry = persistDelta.getValues(index, entry); + if (forcePersist || entry.rxBytes > persistThreshold + || entry.txBytes > persistThreshold) { writeNetworkStatsLocked(); if (mUidStatsLoaded) { writeUidStatsLocked(); @@ -538,20 +551,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HashSet unknownIface = Sets.newHashSet(); final NetworkStats delta = computeStatsDelta(mLastNetworkSnapshot, networkSnapshot); - final long timeStart = currentTime - delta.elapsedRealtime; - for (int i = 0; i < delta.size; i++) { - final String iface = delta.iface[i]; - final NetworkIdentitySet ident = mActiveIfaces.get(iface); + 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(iface); + unknownIface.add(entry.iface); continue; } - final long rx = delta.rx[i]; - final long tx = delta.tx[i]; - final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident); - history.recordData(timeStart, currentTime, rx, tx); + history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes); } // trim any history beyond max @@ -574,22 +586,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { ensureUidStatsLoadedLocked(); final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot); - final long timeStart = currentTime - delta.elapsedRealtime; + final long timeStart = currentTime - delta.getElapsedRealtime(); - for (int i = 0; i < delta.size; i++) { - final String iface = delta.iface[i]; - final NetworkIdentitySet ident = mActiveIfaces.get(iface); + 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) { continue; } - final int uid = delta.uid[i]; - final int tag = delta.tag[i]; - final long rx = delta.rx[i]; - final long tx = delta.tx[i]; - - final NetworkStatsHistory history = findOrCreateUidStatsLocked(ident, uid, tag); - history.recordData(timeStart, currentTime, rx, tx); + final NetworkStatsHistory history = findOrCreateUidStatsLocked( + ident, entry.uid, entry.tag); + history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes); } // trim any history beyond max @@ -651,7 +660,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsHistory updated = null; if (existing == null) { updated = new NetworkStatsHistory(bucketDuration, 10); - } else if (existing.bucketDuration != bucketDuration) { + } else if (existing.getBucketDuration() != bucketDuration) { updated = new NetworkStatsHistory( bucketDuration, estimateResizeBuckets(existing, bucketDuration)); updated.recordEntireHistory(existing); @@ -683,7 +692,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsHistory updated = null; if (existing == null) { updated = new NetworkStatsHistory(bucketDuration, 10); - } else if (existing.bucketDuration != bucketDuration) { + } else if (existing.getBucketDuration() != bucketDuration) { updated = new NetworkStatsHistory( bucketDuration, estimateResizeBuckets(existing, bucketDuration)); updated.recordEntireHistory(existing); @@ -1003,7 +1012,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private static int estimateResizeBuckets(NetworkStatsHistory existing, long newBucketDuration) { - return (int) (existing.bucketCount * existing.bucketDuration / newBucketDuration); + return (int) (existing.size() * existing.getBucketDuration() / newBucketDuration); } // @VisibleForTesting