NetworkStatsCollectionpublic class NetworkStatsCollection extends Object implements FileRotator.ReaderCollection of {@link NetworkStatsHistory}, stored based on combined key of
{@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself. |
Fields Summary |
---|
private static final int | FILE_MAGICFile header magic number: "ANET" | private static final int | VERSION_NETWORK_INIT | private static final int | VERSION_UID_INIT | private static final int | VERSION_UID_WITH_IDENT | private static final int | VERSION_UID_WITH_TAG | private static final int | VERSION_UID_WITH_SET | private static final int | VERSION_UNIFIED_INIT | private android.util.ArrayMap | mStats | private final long | mBucketDuration | private long | mStartMillis | private long | mEndMillis | private long | mTotalBytes | private boolean | mDirty |
Constructors Summary |
---|
public NetworkStatsCollection(long bucketDuration)
mBucketDuration = bucketDuration;
reset();
|
Methods Summary |
---|
public void | clearDirty()
mDirty = false;
| public void | dump(com.android.internal.util.IndentingPrintWriter pw)
final ArrayList<Key> keys = Lists.newArrayList();
keys.addAll(mStats.keySet());
Collections.sort(keys);
for (Key key : keys) {
pw.print("ident="); pw.print(key.ident.toString());
pw.print(" uid="); pw.print(key.uid);
pw.print(" set="); pw.print(NetworkStats.setToString(key.set));
pw.print(" tag="); pw.println(NetworkStats.tagToString(key.tag));
final NetworkStatsHistory history = mStats.get(key);
pw.increaseIndent();
history.dump(pw, true);
pw.decreaseIndent();
}
| public void | dumpCheckin(java.io.PrintWriter pw, long start, long end)
dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell");
dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi");
dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateEthernet(), "eth");
dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateBluetooth(), "bt");
| private void | dumpCheckin(java.io.PrintWriter pw, long start, long end, android.net.NetworkTemplate groupTemplate, java.lang.String groupPrefix)Dump all contained stats that match requested parameters, but group
together all matching {@link NetworkTemplate} under a single prefix.
final ArrayMap<Key, NetworkStatsHistory> grouped = new ArrayMap<>();
// Walk through all history, grouping by matching network templates
for (int i = 0; i < mStats.size(); i++) {
final Key key = mStats.keyAt(i);
final NetworkStatsHistory value = mStats.valueAt(i);
if (!templateMatches(groupTemplate, key.ident)) continue;
final Key groupKey = new Key(null, key.uid, key.set, key.tag);
NetworkStatsHistory groupHistory = grouped.get(groupKey);
if (groupHistory == null) {
groupHistory = new NetworkStatsHistory(value.getBucketDuration());
grouped.put(groupKey, groupHistory);
}
groupHistory.recordHistory(value, start, end);
}
for (int i = 0; i < grouped.size(); i++) {
final Key key = grouped.keyAt(i);
final NetworkStatsHistory value = grouped.valueAt(i);
if (value.size() == 0) continue;
pw.print("c,");
pw.print(groupPrefix); pw.print(',");
pw.print(key.uid); pw.print(',");
pw.print(NetworkStats.setToCheckinString(key.set)); pw.print(',");
pw.print(key.tag);
pw.println();
value.dumpCheckin(pw);
}
| private int | estimateBuckets()
return (int) (Math.min(mEndMillis - mStartMillis, WEEK_IN_MILLIS * 5)
/ mBucketDuration);
| private android.net.NetworkStatsHistory | findOrCreateHistory(NetworkIdentitySet ident, int uid, int set, int tag)
final Key key = new Key(ident, uid, set, tag);
final NetworkStatsHistory existing = mStats.get(key);
// update when no existing, or when bucket duration changed
NetworkStatsHistory updated = null;
if (existing == null) {
updated = new NetworkStatsHistory(mBucketDuration, 10);
} else if (existing.getBucketDuration() != mBucketDuration) {
updated = new NetworkStatsHistory(existing, mBucketDuration);
}
if (updated != null) {
mStats.put(key, updated);
return updated;
} else {
return existing;
}
| public long | getEndMillis()
return mEndMillis;
| public long | getFirstAtomicBucketMillis()Return first atomic bucket in this collection, which is more conservative
than {@link #mStartMillis}.
if (mStartMillis == Long.MAX_VALUE) {
return Long.MAX_VALUE;
} else {
return mStartMillis + mBucketDuration;
}
| public android.net.NetworkStatsHistory | getHistory(android.net.NetworkTemplate template, int uid, int set, int tag, int fields)Combine all {@link NetworkStatsHistory} in this collection which match
the requested parameters.
return getHistory(template, uid, set, tag, fields, Long.MIN_VALUE, Long.MAX_VALUE);
| public android.net.NetworkStatsHistory | getHistory(android.net.NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end)Combine all {@link NetworkStatsHistory} in this collection which match
the requested parameters.
final NetworkStatsHistory combined = new NetworkStatsHistory(
mBucketDuration, estimateBuckets(), fields);
for (int i = 0; i < mStats.size(); i++) {
final Key key = mStats.keyAt(i);
final boolean setMatches = set == SET_ALL || key.set == set;
if (key.uid == uid && setMatches && key.tag == tag
&& templateMatches(template, key.ident)) {
final NetworkStatsHistory value = mStats.valueAt(i);
combined.recordHistory(value, start, end);
}
}
return combined;
| public long | getStartMillis()
return mStartMillis;
| public android.net.NetworkStats | getSummary(android.net.NetworkTemplate template, long start, long end)Summarize all {@link NetworkStatsHistory} in this collection which match
the requested parameters.
final long now = System.currentTimeMillis();
final NetworkStats stats = new NetworkStats(end - start, 24);
final NetworkStats.Entry entry = new NetworkStats.Entry();
NetworkStatsHistory.Entry historyEntry = null;
// shortcut when we know stats will be empty
if (start == end) return stats;
for (int i = 0; i < mStats.size(); i++) {
final Key key = mStats.keyAt(i);
if (templateMatches(template, key.ident)) {
final NetworkStatsHistory value = mStats.valueAt(i);
historyEntry = value.getValues(start, end, now, historyEntry);
entry.iface = IFACE_ALL;
entry.uid = key.uid;
entry.set = key.set;
entry.tag = key.tag;
entry.rxBytes = historyEntry.rxBytes;
entry.rxPackets = historyEntry.rxPackets;
entry.txBytes = historyEntry.txBytes;
entry.txPackets = historyEntry.txPackets;
entry.operations = historyEntry.operations;
if (!entry.isEmpty()) {
stats.combineValues(entry);
}
}
}
return stats;
| public long | getTotalBytes()
return mTotalBytes;
| public boolean | isDirty()
return mDirty;
| public boolean | isEmpty()
return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE;
| private void | noteRecordedHistory(long startMillis, long endMillis, long totalBytes)
if (startMillis < mStartMillis) mStartMillis = startMillis;
if (endMillis > mEndMillis) mEndMillis = endMillis;
mTotalBytes += totalBytes;
mDirty = true;
| public void | read(java.io.InputStream in)
read(new DataInputStream(in));
| public void | read(java.io.DataInputStream in)
// verify file magic header intact
final int magic = in.readInt();
if (magic != FILE_MAGIC) {
throw new ProtocolException("unexpected magic: " + magic);
}
final int version = in.readInt();
switch (version) {
case VERSION_UNIFIED_INIT: {
// uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
final int identSize = in.readInt();
for (int i = 0; i < identSize; i++) {
final NetworkIdentitySet ident = new NetworkIdentitySet(in);
final int size = in.readInt();
for (int j = 0; j < size; j++) {
final int uid = in.readInt();
final int set = in.readInt();
final int tag = in.readInt();
final Key key = new Key(ident, uid, set, tag);
final NetworkStatsHistory history = new NetworkStatsHistory(in);
recordHistory(key, history);
}
}
break;
}
default: {
throw new ProtocolException("unexpected version: " + version);
}
}
| public void | readLegacyNetwork(java.io.File file)
final AtomicFile inputFile = new AtomicFile(file);
DataInputStream in = null;
try {
in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
// verify file magic header intact
final int magic = in.readInt();
if (magic != FILE_MAGIC) {
throw new ProtocolException("unexpected magic: " + magic);
}
final int version = in.readInt();
switch (version) {
case VERSION_NETWORK_INIT: {
// network := size *(NetworkIdentitySet NetworkStatsHistory)
final int size = in.readInt();
for (int i = 0; i < size; i++) {
final NetworkIdentitySet ident = new NetworkIdentitySet(in);
final NetworkStatsHistory history = new NetworkStatsHistory(in);
final Key key = new Key(ident, UID_ALL, SET_ALL, TAG_NONE);
recordHistory(key, history);
}
break;
}
default: {
throw new ProtocolException("unexpected version: " + version);
}
}
} catch (FileNotFoundException e) {
// missing stats is okay, probably first boot
} finally {
IoUtils.closeQuietly(in);
}
| public void | readLegacyUid(java.io.File file, boolean onlyTags)
final AtomicFile inputFile = new AtomicFile(file);
DataInputStream in = null;
try {
in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
// verify file magic header intact
final int magic = in.readInt();
if (magic != FILE_MAGIC) {
throw new ProtocolException("unexpected magic: " + magic);
}
final int version = in.readInt();
switch (version) {
case VERSION_UID_INIT: {
// uid := size *(UID NetworkStatsHistory)
// drop this data version, since we don't have a good
// mapping into NetworkIdentitySet.
break;
}
case VERSION_UID_WITH_IDENT: {
// uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
// drop this data version, since this version only existed
// for a short time.
break;
}
case VERSION_UID_WITH_TAG:
case VERSION_UID_WITH_SET: {
// uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
final int identSize = in.readInt();
for (int i = 0; i < identSize; i++) {
final NetworkIdentitySet ident = new NetworkIdentitySet(in);
final int size = in.readInt();
for (int j = 0; j < size; j++) {
final int uid = in.readInt();
final int set = (version >= VERSION_UID_WITH_SET) ? in.readInt()
: SET_DEFAULT;
final int tag = in.readInt();
final Key key = new Key(ident, uid, set, tag);
final NetworkStatsHistory history = new NetworkStatsHistory(in);
if ((tag == TAG_NONE) != onlyTags) {
recordHistory(key, history);
}
}
}
break;
}
default: {
throw new ProtocolException("unexpected version: " + version);
}
}
} catch (FileNotFoundException e) {
// missing stats is okay, probably first boot
} finally {
IoUtils.closeQuietly(in);
}
| public void | recordCollection(com.android.server.net.NetworkStatsCollection another)Record all {@link NetworkStatsHistory} contained in the given collection
into this collection.
for (int i = 0; i < another.mStats.size(); i++) {
final Key key = another.mStats.keyAt(i);
final NetworkStatsHistory value = another.mStats.valueAt(i);
recordHistory(key, value);
}
| public void | recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start, long end, NetworkStats.Entry entry)Record given {@link android.net.NetworkStats.Entry} into this collection.
final NetworkStatsHistory history = findOrCreateHistory(ident, uid, set, tag);
history.recordData(start, end, entry);
noteRecordedHistory(history.getStart(), history.getEnd(), entry.rxBytes + entry.txBytes);
| private void | recordHistory(com.android.server.net.NetworkStatsCollection$Key key, android.net.NetworkStatsHistory history)Record given {@link NetworkStatsHistory} into this collection.
if (history.size() == 0) return;
noteRecordedHistory(history.getStart(), history.getEnd(), history.getTotalBytes());
NetworkStatsHistory target = mStats.get(key);
if (target == null) {
target = new NetworkStatsHistory(history.getBucketDuration());
mStats.put(key, target);
}
target.recordEntireHistory(history);
| public void | removeUids(int[] uids)Remove any {@link NetworkStatsHistory} attributed to the requested UID,
moving any {@link NetworkStats#TAG_NONE} series to
{@link TrafficStats#UID_REMOVED}.
final ArrayList<Key> knownKeys = Lists.newArrayList();
knownKeys.addAll(mStats.keySet());
// migrate all UID stats into special "removed" bucket
for (Key key : knownKeys) {
if (ArrayUtils.contains(uids, key.uid)) {
// only migrate combined TAG_NONE history
if (key.tag == TAG_NONE) {
final NetworkStatsHistory uidHistory = mStats.get(key);
final NetworkStatsHistory removedHistory = findOrCreateHistory(
key.ident, UID_REMOVED, SET_DEFAULT, TAG_NONE);
removedHistory.recordEntireHistory(uidHistory);
}
mStats.remove(key);
mDirty = true;
}
}
| public void | reset()
mStats.clear();
mStartMillis = Long.MAX_VALUE;
mEndMillis = Long.MIN_VALUE;
mTotalBytes = 0;
mDirty = false;
| private static boolean | templateMatches(android.net.NetworkTemplate template, NetworkIdentitySet identSet)Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
in the given {@link NetworkIdentitySet}.
for (NetworkIdentity ident : identSet) {
if (template.matches(ident)) {
return true;
}
}
return false;
| public void | write(java.io.DataOutputStream out)
// cluster key lists grouped by ident
final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = Maps.newHashMap();
for (Key key : mStats.keySet()) {
ArrayList<Key> keys = keysByIdent.get(key.ident);
if (keys == null) {
keys = Lists.newArrayList();
keysByIdent.put(key.ident, keys);
}
keys.add(key);
}
out.writeInt(FILE_MAGIC);
out.writeInt(VERSION_UNIFIED_INIT);
out.writeInt(keysByIdent.size());
for (NetworkIdentitySet ident : keysByIdent.keySet()) {
final ArrayList<Key> keys = keysByIdent.get(ident);
ident.writeToStream(out);
out.writeInt(keys.size());
for (Key key : keys) {
final NetworkStatsHistory history = mStats.get(key);
out.writeInt(key.uid);
out.writeInt(key.set);
out.writeInt(key.tag);
history.writeToStream(out);
}
}
out.flush();
|
|