FileDocCategorySizeDatePackage
NetworkStats.javaAPI DocAndroid 5.1 API27360Thu Mar 12 22:22:10 GMT 2015android.net

NetworkStats

public class NetworkStats extends Object implements android.os.Parcelable
Collection of active network statistics. Can contain summary details across all interfaces, or details with per-UID granularity. Internally stores data as a large table, closely matching {@code /proc/} data format. This structure optimizes for rapid in-memory comparison, but consider using {@link NetworkStatsHistory} when persisting.
hide

Fields Summary
public static final String
IFACE_ALL
{@link #iface} value when interface details unavailable.
public static final int
UID_ALL
{@link #uid} value when UID details unavailable.
public static final int
TAG_ALL
{@link #tag} value matching any tag.
public static final int
SET_ALL
{@link #set} value when all sets combined.
public static final int
SET_DEFAULT
{@link #set} value where background data is accounted.
public static final int
SET_FOREGROUND
{@link #set} value where foreground data is accounted.
public static final int
TAG_NONE
{@link #tag} value for total data across all tags.
private long
elapsedRealtime
{@link SystemClock#elapsedRealtime()} timestamp when this data was generated.
private int
size
private int
capacity
private String[]
iface
private int[]
uid
private int[]
set
private int[]
tag
private long[]
rxBytes
private long[]
rxPackets
private long[]
txBytes
private long[]
txPackets
private long[]
operations
public static final Creator
CREATOR
Constructors Summary
public NetworkStats(long elapsedRealtime, int initialSize)

        this.elapsedRealtime = elapsedRealtime;
        this.size = 0;
        if (initialSize >= 0) {
            this.capacity = initialSize;
            this.iface = new String[initialSize];
            this.uid = new int[initialSize];
            this.set = new int[initialSize];
            this.tag = new int[initialSize];
            this.rxBytes = new long[initialSize];
            this.rxPackets = new long[initialSize];
            this.txBytes = new long[initialSize];
            this.txPackets = new long[initialSize];
            this.operations = new long[initialSize];
        } else {
            // Special case for use by NetworkStatsFactory to start out *really* empty.
            this.capacity = 0;
            this.iface = EmptyArray.STRING;
            this.uid = EmptyArray.INT;
            this.set = EmptyArray.INT;
            this.tag = EmptyArray.INT;
            this.rxBytes = EmptyArray.LONG;
            this.rxPackets = EmptyArray.LONG;
            this.txBytes = EmptyArray.LONG;
            this.txPackets = EmptyArray.LONG;
            this.operations = EmptyArray.LONG;
        }
    
public NetworkStats(android.os.Parcel parcel)

        elapsedRealtime = parcel.readLong();
        size = parcel.readInt();
        capacity = parcel.readInt();
        iface = parcel.createStringArray();
        uid = parcel.createIntArray();
        set = parcel.createIntArray();
        tag = parcel.createIntArray();
        rxBytes = parcel.createLongArray();
        rxPackets = parcel.createLongArray();
        txBytes = parcel.createLongArray();
        txPackets = parcel.createLongArray();
        operations = parcel.createLongArray();
    
Methods Summary
public android.net.NetworkStatsaddIfaceValues(java.lang.String iface, long rxBytes, long rxPackets, long txBytes, long txPackets)

        return addValues(
                iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
    
public android.net.NetworkStatsaddValues(java.lang.String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations)

        return addValues(new Entry(
                iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
    
public android.net.NetworkStatsaddValues(android.net.NetworkStats$Entry entry)
Add new stats entry, copying from given {@link Entry}. The {@link Entry} object can be recycled across multiple calls.

        if (size >= capacity) {
            final int newLength = Math.max(size, 10) * 3 / 2;
            iface = Arrays.copyOf(iface, newLength);
            uid = Arrays.copyOf(uid, newLength);
            set = Arrays.copyOf(set, newLength);
            tag = Arrays.copyOf(tag, newLength);
            rxBytes = Arrays.copyOf(rxBytes, newLength);
            rxPackets = Arrays.copyOf(rxPackets, newLength);
            txBytes = Arrays.copyOf(txBytes, newLength);
            txPackets = Arrays.copyOf(txPackets, newLength);
            operations = Arrays.copyOf(operations, newLength);
            capacity = newLength;
        }

        iface[size] = entry.iface;
        uid[size] = entry.uid;
        set[size] = entry.set;
        tag[size] = entry.tag;
        rxBytes[size] = entry.rxBytes;
        rxPackets[size] = entry.rxPackets;
        txBytes[size] = entry.txBytes;
        txPackets[size] = entry.txPackets;
        operations[size] = entry.operations;
        size++;

        return this;
    
public android.net.NetworkStatsclone()

        final NetworkStats clone = new NetworkStats(elapsedRealtime, size);
        NetworkStats.Entry entry = null;
        for (int i = 0; i < size; i++) {
            entry = getValues(i, entry);
            clone.addValues(entry);
        }
        return clone;
    
public voidcombineAllValues(android.net.NetworkStats another)
Combine all values from another {@link NetworkStats} into this object.

        NetworkStats.Entry entry = null;
        for (int i = 0; i < another.size; i++) {
            entry = another.getValues(i, entry);
            combineValues(entry);
        }
    
public android.net.NetworkStatscombineValues(java.lang.String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations)

        return combineValues(
                iface, uid, SET_DEFAULT, tag, rxBytes, rxPackets, txBytes, txPackets, operations);
    
public android.net.NetworkStatscombineValues(java.lang.String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations)

        return combineValues(new Entry(
                iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
    
public android.net.NetworkStatscombineValues(android.net.NetworkStats$Entry entry)
Combine given values with an existing row, or create a new row if {@link #findIndex(String, int, int, int)} is unable to find match. Can also be used to subtract values from existing rows.

        final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag);
        if (i == -1) {
            // only create new entry when positive contribution
            addValues(entry);
        } else {
            rxBytes[i] += entry.rxBytes;
            rxPackets[i] += entry.rxPackets;
            txBytes[i] += entry.txBytes;
            txPackets[i] += entry.txPackets;
            operations[i] += entry.operations;
        }
        return this;
    
public intdescribeContents()

        return 0;
    
public voiddump(java.lang.String prefix, java.io.PrintWriter pw)

        pw.print(prefix);
        pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
        for (int i = 0; i < size; i++) {
            pw.print(prefix);
            pw.print("  ["); pw.print(i); pw.print("]");
            pw.print(" iface="); pw.print(iface[i]);
            pw.print(" uid="); pw.print(uid[i]);
            pw.print(" set="); pw.print(setToString(set[i]));
            pw.print(" tag="); pw.print(tagToString(tag[i]));
            pw.print(" rxBytes="); pw.print(rxBytes[i]);
            pw.print(" rxPackets="); pw.print(rxPackets[i]);
            pw.print(" txBytes="); pw.print(txBytes[i]);
            pw.print(" txPackets="); pw.print(txPackets[i]);
            pw.print(" operations="); pw.println(operations[i]);
        }
    
public intfindIndex(java.lang.String iface, int uid, int set, int tag)
Find first stats index that matches the requested parameters.

        for (int i = 0; i < size; i++) {
            if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
                    && Objects.equals(iface, this.iface[i])) {
                return i;
            }
        }
        return -1;
    
public intfindIndexHinted(java.lang.String iface, int uid, int set, int tag, int hintIndex)
Find first stats index that matches the requested parameters, starting search around the hinted index as an optimization.

        for (int offset = 0; offset < size; offset++) {
            final int halfOffset = offset / 2;

            // search outwards from hint index, alternating forward and backward
            final int i;
            if (offset % 2 == 0) {
                i = (hintIndex + halfOffset) % size;
            } else {
                i = (size + hintIndex - halfOffset - 1) % size;
            }

            if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
                    && Objects.equals(iface, this.iface[i])) {
                return i;
            }
        }
        return -1;
    
public longgetElapsedRealtime()

        return elapsedRealtime;
    
public longgetElapsedRealtimeAge()
Return age of this {@link NetworkStats} object with respect to {@link SystemClock#elapsedRealtime()}.

        return SystemClock.elapsedRealtime() - elapsedRealtime;
    
public android.net.NetworkStats$EntrygetTotal(android.net.NetworkStats$Entry recycle)
Return total of all fields represented by this snapshot object.

        return getTotal(recycle, null, UID_ALL, false);
    
public android.net.NetworkStats$EntrygetTotal(android.net.NetworkStats$Entry recycle, int limitUid)
Return total of all fields represented by this snapshot object matching the requested {@link #uid}.

        return getTotal(recycle, null, limitUid, false);
    
public android.net.NetworkStats$EntrygetTotal(android.net.NetworkStats$Entry recycle, java.util.HashSet limitIface)
Return total of all fields represented by this snapshot object matching the requested {@link #iface}.

        return getTotal(recycle, limitIface, UID_ALL, false);
    
private android.net.NetworkStats$EntrygetTotal(android.net.NetworkStats$Entry recycle, java.util.HashSet limitIface, int limitUid, boolean includeTags)
Return total of all fields represented by this snapshot object matching the requested {@link #iface} and {@link #uid}.

param
limitIface Set of {@link #iface} to include in total; or {@code null} to include all ifaces.

        final Entry entry = recycle != null ? recycle : new Entry();

        entry.iface = IFACE_ALL;
        entry.uid = limitUid;
        entry.set = SET_ALL;
        entry.tag = TAG_NONE;
        entry.rxBytes = 0;
        entry.rxPackets = 0;
        entry.txBytes = 0;
        entry.txPackets = 0;
        entry.operations = 0;

        for (int i = 0; i < size; i++) {
            final boolean matchesUid = (limitUid == UID_ALL) || (limitUid == uid[i]);
            final boolean matchesIface = (limitIface == null) || (limitIface.contains(iface[i]));

            if (matchesUid && matchesIface) {
                // skip specific tags, since already counted in TAG_NONE
                if (tag[i] != TAG_NONE && !includeTags) continue;

                entry.rxBytes += rxBytes[i];
                entry.rxPackets += rxPackets[i];
                entry.txBytes += txBytes[i];
                entry.txPackets += txPackets[i];
                entry.operations += operations[i];
            }
        }
        return entry;
    
public longgetTotalBytes()
Return total bytes represented by this snapshot object, usually used when checking if a {@link #subtract(NetworkStats)} delta passes a threshold.

        final Entry entry = getTotal(null);
        return entry.rxBytes + entry.txBytes;
    
public android.net.NetworkStats$EntrygetTotalIncludingTags(android.net.NetworkStats$Entry recycle)

        return getTotal(recycle, null, UID_ALL, true);
    
public longgetTotalPackets()
Fast path for battery stats.

        long total = 0;
        for (int i = size-1; i >= 0; i--) {
            total += rxPackets[i] + txPackets[i];
        }
        return total;
    
public java.lang.String[]getUniqueIfaces()
Return list of unique interfaces known by this data structure.

        final HashSet<String> ifaces = new HashSet<String>();
        for (String iface : this.iface) {
            if (iface != IFACE_ALL) {
                ifaces.add(iface);
            }
        }
        return ifaces.toArray(new String[ifaces.size()]);
    
public int[]getUniqueUids()
Return list of unique UIDs known by this data structure.

        final SparseBooleanArray uids = new SparseBooleanArray();
        for (int uid : this.uid) {
            uids.put(uid, true);
        }

        final int size = uids.size();
        final int[] result = new int[size];
        for (int i = 0; i < size; i++) {
            result[i] = uids.keyAt(i);
        }
        return result;
    
public android.net.NetworkStats$EntrygetValues(int i, android.net.NetworkStats$Entry recycle)
Return specific stats entry.

        final Entry entry = recycle != null ? recycle : new Entry();
        entry.iface = iface[i];
        entry.uid = uid[i];
        entry.set = set[i];
        entry.tag = tag[i];
        entry.rxBytes = rxBytes[i];
        entry.rxPackets = rxPackets[i];
        entry.txBytes = txBytes[i];
        entry.txPackets = txPackets[i];
        entry.operations = operations[i];
        return entry;
    
public android.net.NetworkStatsgroupedByIface()
Return total statistics grouped by {@link #iface}; doesn't mutate the original structure.

        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);

        final Entry entry = new Entry();
        entry.uid = UID_ALL;
        entry.set = SET_ALL;
        entry.tag = TAG_NONE;
        entry.operations = 0L;

        for (int i = 0; i < size; i++) {
            // skip specific tags, since already counted in TAG_NONE
            if (tag[i] != TAG_NONE) continue;

            entry.iface = iface[i];
            entry.rxBytes = rxBytes[i];
            entry.rxPackets = rxPackets[i];
            entry.txBytes = txBytes[i];
            entry.txPackets = txPackets[i];
            stats.combineValues(entry);
        }

        return stats;
    
public android.net.NetworkStatsgroupedByUid()
Return total statistics grouped by {@link #uid}; doesn't mutate the original structure.

        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);

        final Entry entry = new Entry();
        entry.iface = IFACE_ALL;
        entry.set = SET_ALL;
        entry.tag = TAG_NONE;

        for (int i = 0; i < size; i++) {
            // skip specific tags, since already counted in TAG_NONE
            if (tag[i] != TAG_NONE) continue;

            entry.uid = uid[i];
            entry.rxBytes = rxBytes[i];
            entry.rxPackets = rxPackets[i];
            entry.txBytes = txBytes[i];
            entry.txPackets = txPackets[i];
            entry.operations = operations[i];
            stats.combineValues(entry);
        }

        return stats;
    
public intinternalSize()

        return capacity;
    
public voidsetElapsedRealtime(long time)

        elapsedRealtime = time;
    
public static java.lang.StringsetToCheckinString(int set)
Return text description of {@link #set} value.

        switch (set) {
            case SET_ALL:
                return "all";
            case SET_DEFAULT:
                return "def";
            case SET_FOREGROUND:
                return "fg";
            default:
                return "unk";
        }
    
public static java.lang.StringsetToString(int set)
Return text description of {@link #set} value.

        switch (set) {
            case SET_ALL:
                return "ALL";
            case SET_DEFAULT:
                return "DEFAULT";
            case SET_FOREGROUND:
                return "FOREGROUND";
            default:
                return "UNKNOWN";
        }
    
public intsize()

        return size;
    
public voidspliceOperationsFrom(android.net.NetworkStats stats)
Splice in {@link #operations} from the given {@link NetworkStats} based on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface}, since operation counts are at data layer.

        for (int i = 0; i < size; i++) {
            final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i]);
            if (j == -1) {
                operations[i] = 0;
            } else {
                operations[i] = stats.operations[j];
            }
        }
    
public android.net.NetworkStatssubtract(android.net.NetworkStats right)
Subtract the given {@link NetworkStats}, effectively leaving the delta between two snapshots in time. Assumes that statistics rows collect over time, and that none of them have disappeared.

        return subtract(this, right, null, null);
    
public static android.net.NetworkStatssubtract(android.net.NetworkStats left, android.net.NetworkStats right, android.net.NetworkStats$NonMonotonicObserver observer, C cookie)
Subtract the two given {@link NetworkStats} objects, returning the delta between two snapshots in time. Assumes that statistics rows collect over time, and that none of them have disappeared.

If counters have rolled backwards, they are clamped to {@code 0} and reported to the given {@link NonMonotonicObserver}.

        return subtract(left, right, observer, cookie, null);
    
public static android.net.NetworkStatssubtract(android.net.NetworkStats left, android.net.NetworkStats right, android.net.NetworkStats$NonMonotonicObserver observer, C cookie, android.net.NetworkStats recycle)
Subtract the two given {@link NetworkStats} objects, returning the delta between two snapshots in time. Assumes that statistics rows collect over time, and that none of them have disappeared.

If counters have rolled backwards, they are clamped to {@code 0} and reported to the given {@link NonMonotonicObserver}.

If recycle is supplied, this NetworkStats object will be reused (and returned) as the result if it is large enough to contain the data.

        long deltaRealtime = left.elapsedRealtime - right.elapsedRealtime;
        if (deltaRealtime < 0) {
            if (observer != null) {
                observer.foundNonMonotonic(left, -1, right, -1, cookie);
            }
            deltaRealtime = 0;
        }

        // result will have our rows, and elapsed time between snapshots
        final Entry entry = new Entry();
        final NetworkStats result;
        if (recycle != null && recycle.capacity >= left.size) {
            result = recycle;
            result.size = 0;
            result.elapsedRealtime = deltaRealtime;
        } else {
            result = new NetworkStats(deltaRealtime, left.size);
        }
        for (int i = 0; i < left.size; i++) {
            entry.iface = left.iface[i];
            entry.uid = left.uid[i];
            entry.set = left.set[i];
            entry.tag = left.tag[i];

            // find remote row that matches, and subtract
            final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, i);
            if (j == -1) {
                // newly appearing row, return entire value
                entry.rxBytes = left.rxBytes[i];
                entry.rxPackets = left.rxPackets[i];
                entry.txBytes = left.txBytes[i];
                entry.txPackets = left.txPackets[i];
                entry.operations = left.operations[i];
            } else {
                // existing row, subtract remote value
                entry.rxBytes = left.rxBytes[i] - right.rxBytes[j];
                entry.rxPackets = left.rxPackets[i] - right.rxPackets[j];
                entry.txBytes = left.txBytes[i] - right.txBytes[j];
                entry.txPackets = left.txPackets[i] - right.txPackets[j];
                entry.operations = left.operations[i] - right.operations[j];

                if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
                        || entry.txPackets < 0 || entry.operations < 0) {
                    if (observer != null) {
                        observer.foundNonMonotonic(left, i, right, j, cookie);
                    }
                    entry.rxBytes = Math.max(entry.rxBytes, 0);
                    entry.rxPackets = Math.max(entry.rxPackets, 0);
                    entry.txBytes = Math.max(entry.txBytes, 0);
                    entry.txPackets = Math.max(entry.txPackets, 0);
                    entry.operations = Math.max(entry.operations, 0);
                }
            }

            result.addValues(entry);
        }

        return result;
    
public static java.lang.StringtagToString(int tag)
Return text description of {@link #tag} value.

        return "0x" + Integer.toHexString(tag);
    
public java.lang.StringtoString()

        final CharArrayWriter writer = new CharArrayWriter();
        dump("", new PrintWriter(writer));
        return writer.toString();
    
public android.net.NetworkStatswithoutUids(int[] uids)
Return all rows except those attributed to the requested UID; doesn't mutate the original structure.

        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);

        Entry entry = new Entry();
        for (int i = 0; i < size; i++) {
            entry = getValues(i, entry);
            if (!ArrayUtils.contains(uids, entry.uid)) {
                stats.addValues(entry);
            }
        }

        return stats;
    
public voidwriteToParcel(android.os.Parcel dest, int flags)

        dest.writeLong(elapsedRealtime);
        dest.writeInt(size);
        dest.writeInt(capacity);
        dest.writeStringArray(iface);
        dest.writeIntArray(uid);
        dest.writeIntArray(set);
        dest.writeIntArray(tag);
        dest.writeLongArray(rxBytes);
        dest.writeLongArray(rxPackets);
        dest.writeLongArray(txBytes);
        dest.writeLongArray(txPackets);
        dest.writeLongArray(operations);