NetworkStats.java revision 63abc37356728c0575d6a62a203102ae6d97953b
19a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey/*
29a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project
39a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey *
49a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
59a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * you may not use this file except in compliance with the License.
69a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * You may obtain a copy of the License at
79a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey *
89a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
99a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey *
109a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
119a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
129a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * See the License for the specific language governing permissions and
149a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * limitations under the License.
159a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey */
169a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
179a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeypackage android.net;
189a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
199a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.Parcel;
209a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.Parcelable;
219a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.SystemClock;
2261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.util.SparseBooleanArray;
239a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
24a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport com.android.internal.util.Objects;
25a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
269a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.CharArrayWriter;
279a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.PrintWriter;
284a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkeyimport java.util.Arrays;
2975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.HashSet;
309a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
319a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey/**
3275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collection of active network statistics. Can contain summary details across
3375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * all interfaces, or details with per-UID granularity. Internally stores data
3475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * as a large table, closely matching {@code /proc/} data format. This structure
3575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * optimizes for rapid in-memory comparison, but consider using
3675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * {@link NetworkStatsHistory} when persisting.
379a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey *
389a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * @hide
399a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey */
409a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeypublic class NetworkStats implements Parcelable {
4175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /** {@link #iface} value when interface details unavailable. */
429a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public static final String IFACE_ALL = null;
4375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /** {@link #uid} value when UID details unavailable. */
4475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public static final int UID_ALL = -1;
45b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /** {@link #set} value when all sets combined. */
46b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public static final int SET_ALL = -1;
47b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /** {@link #set} value where background data is accounted. */
48b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public static final int SET_DEFAULT = 0;
49b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /** {@link #set} value where foreground data is accounted. */
50b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public static final int SET_FOREGROUND = 1;
51b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /** {@link #tag} value for total data across all tags. */
521b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public static final int TAG_NONE = 0;
53eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
54163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    // TODO: move fields to "mVariable" notation
55163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
569a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    /**
579a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey     * {@link SystemClock#elapsedRealtime()} timestamp when this data was
589a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey     * generated.
599a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey     */
60d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private final long elapsedRealtime;
61d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private int size;
62d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private String[] iface;
63d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private int[] uid;
64b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private int[] set;
65d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private int[] tag;
66d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] rxBytes;
67d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] rxPackets;
68d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] txBytes;
69d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] txPackets;
7063d27a9233fed934340231f438493746084a681dJeff Sharkey    private long[] operations;
71fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
72fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    public static class Entry {
73fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public String iface;
74fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public int uid;
75b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public int set;
76fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public int tag;
77fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public long rxBytes;
78fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public long rxPackets;
79fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public long txBytes;
80fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public long txPackets;
8163d27a9233fed934340231f438493746084a681dJeff Sharkey        public long operations;
82d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
83d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        public Entry() {
84b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
8563d27a9233fed934340231f438493746084a681dJeff Sharkey        }
8663d27a9233fed934340231f438493746084a681dJeff Sharkey
8763d27a9233fed934340231f438493746084a681dJeff Sharkey        public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
88b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets,
89b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    operations);
90d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        }
91d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
92b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
93b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                long txBytes, long txPackets, long operations) {
94d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.iface = iface;
95d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.uid = uid;
96b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this.set = set;
97d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.tag = tag;
98d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.rxBytes = rxBytes;
99d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.rxPackets = rxPackets;
100d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.txBytes = txBytes;
101d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.txPackets = txPackets;
102a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            this.operations = operations;
103d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        }
104b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
10563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public boolean isNegative() {
10663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return rxBytes < 0 || rxPackets < 0 || txBytes < 0 || txPackets < 0 || operations < 0;
10763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        }
10863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
10963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public boolean isEmpty() {
11063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return rxBytes == 0 && rxPackets == 0 && txBytes == 0 && txPackets == 0
11163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    && operations == 0;
11263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        }
11363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
114b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        @Override
115b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        public String toString() {
116b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            final StringBuilder builder = new StringBuilder();
117b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append("iface=").append(iface);
118b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" uid=").append(uid);
119b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" set=").append(setToString(set));
120b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" tag=").append(tagToString(tag));
121b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" rxBytes=").append(rxBytes);
122b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" rxPackets=").append(rxPackets);
123b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" txBytes=").append(txBytes);
124b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" txPackets=").append(txPackets);
125b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" operations=").append(operations);
126b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            return builder.toString();
127b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        }
128fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    }
1299a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
1304a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    public NetworkStats(long elapsedRealtime, int initialSize) {
1319a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        this.elapsedRealtime = elapsedRealtime;
1324a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        this.size = 0;
1334a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        this.iface = new String[initialSize];
1344a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        this.uid = new int[initialSize];
135b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        this.set = new int[initialSize];
1361b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        this.tag = new int[initialSize];
137d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        this.rxBytes = new long[initialSize];
138fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        this.rxPackets = new long[initialSize];
139d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        this.txBytes = new long[initialSize];
140fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        this.txPackets = new long[initialSize];
14163d27a9233fed934340231f438493746084a681dJeff Sharkey        this.operations = new long[initialSize];
1429a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
1439a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
1449a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public NetworkStats(Parcel parcel) {
1459a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        elapsedRealtime = parcel.readLong();
1464a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        size = parcel.readInt();
1479a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        iface = parcel.createStringArray();
1489a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        uid = parcel.createIntArray();
149b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        set = parcel.createIntArray();
1501b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        tag = parcel.createIntArray();
151d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        rxBytes = parcel.createLongArray();
152fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        rxPackets = parcel.createLongArray();
153d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        txBytes = parcel.createLongArray();
154fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        txPackets = parcel.createLongArray();
15563d27a9233fed934340231f438493746084a681dJeff Sharkey        operations = parcel.createLongArray();
156a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
157a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
158a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /** {@inheritDoc} */
159a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public void writeToParcel(Parcel dest, int flags) {
160a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeLong(elapsedRealtime);
161a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeInt(size);
162a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeStringArray(iface);
163a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeIntArray(uid);
164b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        dest.writeIntArray(set);
165a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeIntArray(tag);
166a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeLongArray(rxBytes);
167a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeLongArray(rxPackets);
168a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeLongArray(txBytes);
169a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeLongArray(txPackets);
17063d27a9233fed934340231f438493746084a681dJeff Sharkey        dest.writeLongArray(operations);
1719a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
1729a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
1734abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey    @Override
1744abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey    public NetworkStats clone() {
1754abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey        final NetworkStats clone = new NetworkStats(elapsedRealtime, size);
1764abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey        NetworkStats.Entry entry = null;
1774abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey        for (int i = 0; i < size; i++) {
1784abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey            entry = getValues(i, entry);
1794abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey            clone.addValues(entry);
1804abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey        }
1814abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey        return clone;
1824abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey    }
1834abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey
184b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    // @VisibleForTesting
185b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public NetworkStats addIfaceValues(
186b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
187b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        return addValues(
188b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
189a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
190a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
191b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    // @VisibleForTesting
192b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public NetworkStats addValues(String iface, int uid, int set, int tag, long rxBytes,
193b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            long rxPackets, long txBytes, long txPackets, long operations) {
194b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        return addValues(new Entry(
195b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
196fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    }
197fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
198fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    /**
199fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey     * Add new stats entry, copying from given {@link Entry}. The {@link Entry}
200fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey     * object can be recycled across multiple calls.
201fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey     */
202fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    public NetworkStats addValues(Entry entry) {
2034a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        if (size >= this.iface.length) {
204fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            final int newLength = Math.max(iface.length, 10) * 3 / 2;
205fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            iface = Arrays.copyOf(iface, newLength);
206fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            uid = Arrays.copyOf(uid, newLength);
207b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            set = Arrays.copyOf(set, newLength);
208fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            tag = Arrays.copyOf(tag, newLength);
209d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            rxBytes = Arrays.copyOf(rxBytes, newLength);
210fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            rxPackets = Arrays.copyOf(rxPackets, newLength);
211d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            txBytes = Arrays.copyOf(txBytes, newLength);
212fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            txPackets = Arrays.copyOf(txPackets, newLength);
213a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            operations = Arrays.copyOf(operations, newLength);
2149a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        }
2159a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
216fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        iface[size] = entry.iface;
217fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        uid[size] = entry.uid;
218b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        set[size] = entry.set;
219fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        tag[size] = entry.tag;
220d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        rxBytes[size] = entry.rxBytes;
221fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        rxPackets[size] = entry.rxPackets;
222d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        txBytes[size] = entry.txBytes;
223fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        txPackets[size] = entry.txPackets;
224a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        operations[size] = entry.operations;
2254a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        size++;
2269a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
2274a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        return this;
2289a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
2299a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
2301b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
231fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey     * Return specific stats entry.
232fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey     */
233fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    public Entry getValues(int i, Entry recycle) {
234fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        final Entry entry = recycle != null ? recycle : new Entry();
235fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        entry.iface = iface[i];
236fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        entry.uid = uid[i];
237b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        entry.set = set[i];
238fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        entry.tag = tag[i];
239d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        entry.rxBytes = rxBytes[i];
240fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        entry.rxPackets = rxPackets[i];
241d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        entry.txBytes = txBytes[i];
242fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        entry.txPackets = txPackets[i];
243a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        entry.operations = operations[i];
244fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        return entry;
245fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    }
246fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
247fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    public long getElapsedRealtime() {
248fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        return elapsedRealtime;
249fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    }
250fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
2511059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
2521059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Return age of this {@link NetworkStats} object with respect to
2531059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * {@link SystemClock#elapsedRealtime()}.
2541059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
2551059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public long getElapsedRealtimeAge() {
2561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return SystemClock.elapsedRealtime() - elapsedRealtime;
2571059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
2581059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
259fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    public int size() {
260fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        return size;
261fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    }
262fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
263d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    // @VisibleForTesting
264d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    public int internalSize() {
265d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        return iface.length;
266d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    }
267d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
268b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    @Deprecated
269d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
27063d27a9233fed934340231f438493746084a681dJeff Sharkey            long txBytes, long txPackets, long operations) {
271a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        return combineValues(
272b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                iface, uid, SET_DEFAULT, tag, rxBytes, rxPackets, txBytes, txPackets, operations);
273b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
274b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
275b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public NetworkStats combineValues(String iface, int uid, int set, int tag, long rxBytes,
276b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            long rxPackets, long txBytes, long txPackets, long operations) {
277b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        return combineValues(new Entry(
278b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
279d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    }
280d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
281fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    /**
2821b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     * Combine given values with an existing row, or create a new row if
283b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     * {@link #findIndex(String, int, int, int)} is unable to find match. Can
284b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     * also be used to subtract values from existing rows.
2851b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
286d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    public NetworkStats combineValues(Entry entry) {
287b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag);
2881b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        if (i == -1) {
2891b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            // only create new entry when positive contribution
290d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            addValues(entry);
2911b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        } else {
292d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            rxBytes[i] += entry.rxBytes;
293d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            rxPackets[i] += entry.rxPackets;
294d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            txBytes[i] += entry.txBytes;
295d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            txPackets[i] += entry.txPackets;
296a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            operations[i] += entry.operations;
2971b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
2981b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return this;
299eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    }
300eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
3019a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    /**
302905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     * Combine all values from another {@link NetworkStats} into this object.
303905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     */
304905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    public void combineAllValues(NetworkStats another) {
305905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        NetworkStats.Entry entry = null;
306905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        for (int i = 0; i < another.size; i++) {
307905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry = another.getValues(i, entry);
308905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            combineValues(entry);
309905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        }
310905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
311905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
312905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    /**
3139a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey     * Find first stats index that matches the requested parameters.
3149a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey     */
315b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public int findIndex(String iface, int uid, int set, int tag) {
3164a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        for (int i = 0; i < size; i++) {
317163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
318163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                    && Objects.equal(iface, this.iface[i])) {
319163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                return i;
320163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            }
321163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        }
322163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        return -1;
323163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    }
324163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
325163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    /**
326163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     * Find first stats index that matches the requested parameters, starting
327163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     * search around the hinted index as an optimization.
328163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     */
329163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    // @VisibleForTesting
330163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    public int findIndexHinted(String iface, int uid, int set, int tag, int hintIndex) {
331163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        for (int offset = 0; offset < size; offset++) {
332163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            final int halfOffset = offset / 2;
333163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
334163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            // search outwards from hint index, alternating forward and backward
335163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            final int i;
336163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            if (offset % 2 == 0) {
337163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                i = (hintIndex + halfOffset) % size;
338163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            } else {
339163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                i = (size + hintIndex - halfOffset - 1) % size;
340163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            }
341163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
342163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
343163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                    && Objects.equal(iface, this.iface[i])) {
3449a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey                return i;
3459a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey            }
3469a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        }
3479a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        return -1;
3489a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
3499a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
350eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    /**
351a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * Splice in {@link #operations} from the given {@link NetworkStats} based
352a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface},
353a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * since operation counts are at data layer.
354a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     */
35563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    @Deprecated
356a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public void spliceOperationsFrom(NetworkStats stats) {
357a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        for (int i = 0; i < size; i++) {
358b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int j = stats.findIndex(IFACE_ALL, uid[i], set[i], tag[i]);
359a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            if (j == -1) {
360a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                operations[i] = 0;
361a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            } else {
362a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                operations[i] = stats.operations[j];
363a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            }
364a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
365a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
366a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
367a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /**
36875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Return list of unique interfaces known by this data structure.
36975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
37061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    public String[] getUniqueIfaces() {
37175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final HashSet<String> ifaces = new HashSet<String>();
37275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        for (String iface : this.iface) {
37375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            if (iface != IFACE_ALL) {
37475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                ifaces.add(iface);
37575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
37675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
37775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        return ifaces.toArray(new String[ifaces.size()]);
37875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
37975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
38075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
38161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     * Return list of unique UIDs known by this data structure.
38261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
38361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    public int[] getUniqueUids() {
38461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final SparseBooleanArray uids = new SparseBooleanArray();
38561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (int uid : this.uid) {
38661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            uids.put(uid, true);
38761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
38861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
38961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final int size = uids.size();
39061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final int[] result = new int[size];
39161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (int i = 0; i < size; i++) {
39261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            result[i] = uids.keyAt(i);
39361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
39461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        return result;
39561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
39661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
39761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
3988e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Return total bytes represented by this snapshot object, usually used when
3998e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
4008e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
4018e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    public long getTotalBytes() {
40207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        final Entry entry = getTotal(null);
40307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        return entry.rxBytes + entry.txBytes;
40407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    }
40507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
40607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    /**
40707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey     * Return total of all fields represented by this snapshot object.
40807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey     */
40907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    public Entry getTotal(Entry recycle) {
41063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return getTotal(recycle, null, UID_ALL, false);
4111059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
4121059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
4131059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
4141059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Return total of all fields represented by this snapshot object matching
4151059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * the requested {@link #uid}.
4161059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
4171059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public Entry getTotal(Entry recycle, int limitUid) {
41863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return getTotal(recycle, null, limitUid, false);
4191059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
4201059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
4211059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
4221059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Return total of all fields represented by this snapshot object matching
4231059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * the requested {@link #iface}.
4241059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
4251059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public Entry getTotal(Entry recycle, HashSet<String> limitIface) {
42663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return getTotal(recycle, limitIface, UID_ALL, false);
42763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    }
42863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
42963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    public Entry getTotalIncludingTags(Entry recycle) {
43063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return getTotal(recycle, null, UID_ALL, true);
4311059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
4321059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
4331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
4341059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Return total of all fields represented by this snapshot object matching
4351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * the requested {@link #iface} and {@link #uid}.
4361059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     *
4371059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * @param limitIface Set of {@link #iface} to include in total; or {@code
4381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     *            null} to include all ifaces.
4391059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
44063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private Entry getTotal(
44163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            Entry recycle, HashSet<String> limitIface, int limitUid, boolean includeTags) {
44207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        final Entry entry = recycle != null ? recycle : new Entry();
44307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
44407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.iface = IFACE_ALL;
4451059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        entry.uid = limitUid;
44607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.set = SET_ALL;
44707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.tag = TAG_NONE;
44807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.rxBytes = 0;
44907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.rxPackets = 0;
45007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.txBytes = 0;
45107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.txPackets = 0;
4521059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        entry.operations = 0;
45307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
4548e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        for (int i = 0; i < size; i++) {
4551059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            final boolean matchesUid = (limitUid == UID_ALL) || (limitUid == uid[i]);
4561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            final boolean matchesIface = (limitIface == null) || (limitIface.contains(iface[i]));
4571059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
4581059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            if (matchesUid && matchesIface) {
4591059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                // skip specific tags, since already counted in TAG_NONE
46063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                if (tag[i] != TAG_NONE && !includeTags) continue;
4611059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
4621059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.rxBytes += rxBytes[i];
4631059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.rxPackets += rxPackets[i];
4641059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.txBytes += txBytes[i];
4651059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.txPackets += txPackets[i];
4661059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.operations += operations[i];
4671059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            }
4688e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
46907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        return entry;
4708e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
4718e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
4728e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
473eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey     * Subtract the given {@link NetworkStats}, effectively leaving the delta
474eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey     * between two snapshots in time. Assumes that statistics rows collect over
475eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey     * time, and that none of them have disappeared.
476eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey     */
4775a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey    public NetworkStats subtract(NetworkStats right) {
47863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return subtract(this, right, null, null);
479d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey    }
480d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey
481d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey    /**
4825a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey     * Subtract the two given {@link NetworkStats} objects, returning the delta
483d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey     * between two snapshots in time. Assumes that statistics rows collect over
484d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey     * time, and that none of them have disappeared.
4855a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey     * <p>
4865a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey     * If counters have rolled backwards, they are clamped to {@code 0} and
4875a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey     * reported to the given {@link NonMonotonicObserver}.
488d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey     */
48963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    public static <C> NetworkStats subtract(
49063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            NetworkStats left, NetworkStats right, NonMonotonicObserver<C> observer, C cookie) {
4915a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey        long deltaRealtime = left.elapsedRealtime - right.elapsedRealtime;
492163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        if (deltaRealtime < 0) {
4935a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey            if (observer != null) {
49463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                observer.foundNonMonotonic(left, -1, right, -1, cookie);
4955a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey            }
4965a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey            deltaRealtime = 0;
49775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
498eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
49975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // result will have our rows, and elapsed time between snapshots
500fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        final Entry entry = new Entry();
5015a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey        final NetworkStats result = new NetworkStats(deltaRealtime, left.size);
5025a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey        for (int i = 0; i < left.size; i++) {
5035a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey            entry.iface = left.iface[i];
5045a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey            entry.uid = left.uid[i];
5055a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey            entry.set = left.set[i];
5065a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey            entry.tag = left.tag[i];
507eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
508eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey            // find remote row that matches, and subtract
5095a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey            final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, i);
510eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey            if (j == -1) {
511eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey                // newly appearing row, return entire value
5125a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                entry.rxBytes = left.rxBytes[i];
5135a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                entry.rxPackets = left.rxPackets[i];
5145a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                entry.txBytes = left.txBytes[i];
5155a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                entry.txPackets = left.txPackets[i];
5165a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                entry.operations = left.operations[i];
517eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey            } else {
518eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey                // existing row, subtract remote value
5195a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                entry.rxBytes = left.rxBytes[i] - right.rxBytes[j];
5205a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                entry.rxPackets = left.rxPackets[i] - right.rxPackets[j];
5215a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                entry.txBytes = left.txBytes[i] - right.txBytes[j];
5225a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                entry.txPackets = left.txPackets[i] - right.txPackets[j];
5235a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                entry.operations = left.operations[i] - right.operations[j];
524163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
525163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
526163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                        || entry.txPackets < 0 || entry.operations < 0) {
5275a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                    if (observer != null) {
52863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                        observer.foundNonMonotonic(left, i, right, j, cookie);
529d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey                    }
5305a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                    entry.rxBytes = Math.max(entry.rxBytes, 0);
5315a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                    entry.rxPackets = Math.max(entry.rxPackets, 0);
5325a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                    entry.txBytes = Math.max(entry.txBytes, 0);
5335a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                    entry.txPackets = Math.max(entry.txPackets, 0);
5345a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey                    entry.operations = Math.max(entry.operations, 0);
5353f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                }
536eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey            }
537fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
538fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            result.addValues(entry);
539eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey        }
540eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
5414a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        return result;
5429a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
5439a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
544905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    /**
545905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     * Return total statistics grouped by {@link #iface}; doesn't mutate the
546905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     * original structure.
547905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     */
548905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    public NetworkStats groupedByIface() {
549905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
550905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
551905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final Entry entry = new Entry();
552905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        entry.uid = UID_ALL;
553905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        entry.set = SET_ALL;
554905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        entry.tag = TAG_NONE;
555905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        entry.operations = 0L;
556905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
557905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        for (int i = 0; i < size; i++) {
558905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            // skip specific tags, since already counted in TAG_NONE
559905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            if (tag[i] != TAG_NONE) continue;
560905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
561905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.iface = iface[i];
562905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.rxBytes = rxBytes[i];
563905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.rxPackets = rxPackets[i];
564905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.txBytes = txBytes[i];
565905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.txPackets = txPackets[i];
566905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            stats.combineValues(entry);
567905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        }
568905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
569905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return stats;
570905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
571905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
5721059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
5731059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Return total statistics grouped by {@link #uid}; doesn't mutate the
5741059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * original structure.
5751059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
5761059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public NetworkStats groupedByUid() {
5771059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
5781059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
5791059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final Entry entry = new Entry();
5801059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        entry.iface = IFACE_ALL;
5811059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        entry.set = SET_ALL;
5821059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        entry.tag = TAG_NONE;
5831059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
5841059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        for (int i = 0; i < size; i++) {
5851059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            // skip specific tags, since already counted in TAG_NONE
5861059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            if (tag[i] != TAG_NONE) continue;
5871059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
5881059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.uid = uid[i];
5891059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.rxBytes = rxBytes[i];
5901059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.rxPackets = rxPackets[i];
5911059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.txBytes = txBytes[i];
5921059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.txPackets = txPackets[i];
5931059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.operations = operations[i];
5941059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            stats.combineValues(entry);
5951059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
5961059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
5971059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return stats;
5981059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
5991059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
600163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    /**
601163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     * Return all rows except those attributed to the requested UID; doesn't
602163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     * mutate the original structure.
603163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     */
604163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    public NetworkStats withoutUid(int uid) {
605163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
606163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
607163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        Entry entry = new Entry();
608163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        for (int i = 0; i < size; i++) {
609163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            entry = getValues(i, entry);
610163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            if (entry.uid != uid) {
611163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                stats.addValues(entry);
612163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            }
613163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        }
614163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
615163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        return stats;
616163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    }
617163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
6189a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public void dump(String prefix, PrintWriter pw) {
6199a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        pw.print(prefix);
6209a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
621fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        for (int i = 0; i < size; i++) {
6229a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey            pw.print(prefix);
6233359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey            pw.print("  ["); pw.print(i); pw.print("]");
6243359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey            pw.print(" iface="); pw.print(iface[i]);
6259a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey            pw.print(" uid="); pw.print(uid[i]);
626b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            pw.print(" set="); pw.print(setToString(set[i]));
627b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            pw.print(" tag="); pw.print(tagToString(tag[i]));
628d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            pw.print(" rxBytes="); pw.print(rxBytes[i]);
629fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            pw.print(" rxPackets="); pw.print(rxPackets[i]);
630d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            pw.print(" txBytes="); pw.print(txBytes[i]);
631a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            pw.print(" txPackets="); pw.print(txPackets[i]);
632a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            pw.print(" operations="); pw.println(operations[i]);
6339a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        }
6349a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
6359a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
636b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /**
637b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     * Return text description of {@link #set} value.
638b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     */
639b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public static String setToString(int set) {
640b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        switch (set) {
641b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            case SET_ALL:
642b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                return "ALL";
643b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            case SET_DEFAULT:
644b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                return "DEFAULT";
645b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            case SET_FOREGROUND:
646b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                return "FOREGROUND";
647b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            default:
648b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                return "UNKNOWN";
649b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
650b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
651b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
652b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /**
653b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     * Return text description of {@link #tag} value.
654b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     */
655b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public static String tagToString(int tag) {
656b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        return "0x" + Integer.toHexString(tag);
657b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
658b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
6599a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    @Override
6609a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public String toString() {
6619a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        final CharArrayWriter writer = new CharArrayWriter();
6629a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        dump("", new PrintWriter(writer));
6639a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        return writer.toString();
6649a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
6659a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
6669a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    /** {@inheritDoc} */
667eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    public int describeContents() {
668eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey        return 0;
669eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    }
670eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
6719a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
6729a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        public NetworkStats createFromParcel(Parcel in) {
6739a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey            return new NetworkStats(in);
6749a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        }
6759a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
6769a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        public NetworkStats[] newArray(int size) {
6779a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey            return new NetworkStats[size];
6789a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        }
6799a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    };
680163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
68163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    public interface NonMonotonicObserver<C> {
6825a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey        public void foundNonMonotonic(
68363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, C cookie);
684163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    }
6859a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey}
686