NetworkStats.java revision 3359aca7655a7d18615c1ada6cbabeff403947d1
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
19163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull;
20163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
219a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.Parcel;
229a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.Parcelable;
239a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.SystemClock;
2461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.util.SparseBooleanArray;
259a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
26a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport com.android.internal.util.Objects;
27a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
289a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.CharArrayWriter;
299a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.PrintWriter;
304a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkeyimport java.util.Arrays;
3175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.HashSet;
329a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
339a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey/**
3475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collection of active network statistics. Can contain summary details across
3575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * all interfaces, or details with per-UID granularity. Internally stores data
3675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * as a large table, closely matching {@code /proc/} data format. This structure
3775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * optimizes for rapid in-memory comparison, but consider using
3875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * {@link NetworkStatsHistory} when persisting.
399a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey *
409a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * @hide
419a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey */
429a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeypublic class NetworkStats implements Parcelable {
4347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey    private static final String TAG = "NetworkStats";
4447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey
4575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /** {@link #iface} value when interface details unavailable. */
469a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public static final String IFACE_ALL = null;
4775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /** {@link #uid} value when UID details unavailable. */
4875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public static final int UID_ALL = -1;
49b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /** {@link #set} value when all sets combined. */
50b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public static final int SET_ALL = -1;
51b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /** {@link #set} value where background data is accounted. */
52b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public static final int SET_DEFAULT = 0;
53b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /** {@link #set} value where foreground data is accounted. */
54b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public static final int SET_FOREGROUND = 1;
55b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /** {@link #tag} value for total data across all tags. */
561b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public static final int TAG_NONE = 0;
57eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
58163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    // TODO: move fields to "mVariable" notation
59163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
609a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    /**
619a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey     * {@link SystemClock#elapsedRealtime()} timestamp when this data was
629a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey     * generated.
639a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey     */
64d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private final long elapsedRealtime;
65d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private int size;
66d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private String[] iface;
67d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private int[] uid;
68b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private int[] set;
69d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private int[] tag;
70d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] rxBytes;
71d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] rxPackets;
72d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] txBytes;
73d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] txPackets;
7463d27a9233fed934340231f438493746084a681dJeff Sharkey    private long[] operations;
75fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
76fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    public static class Entry {
77fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public String iface;
78fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public int uid;
79b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public int set;
80fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public int tag;
81fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public long rxBytes;
82fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public long rxPackets;
83fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public long txBytes;
84fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        public long txPackets;
8563d27a9233fed934340231f438493746084a681dJeff Sharkey        public long operations;
86d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
87d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        public Entry() {
88b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
8963d27a9233fed934340231f438493746084a681dJeff Sharkey        }
9063d27a9233fed934340231f438493746084a681dJeff Sharkey
9163d27a9233fed934340231f438493746084a681dJeff Sharkey        public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
92b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets,
93b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    operations);
94d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        }
95d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
96b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
97b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                long txBytes, long txPackets, long operations) {
98d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.iface = iface;
99d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.uid = uid;
100b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this.set = set;
101d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.tag = tag;
102d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.rxBytes = rxBytes;
103d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.rxPackets = rxPackets;
104d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.txBytes = txBytes;
105d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            this.txPackets = txPackets;
106a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            this.operations = operations;
107d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        }
108b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
109b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        @Override
110b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        public String toString() {
111b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            final StringBuilder builder = new StringBuilder();
112b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append("iface=").append(iface);
113b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" uid=").append(uid);
114b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" set=").append(setToString(set));
115b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" tag=").append(tagToString(tag));
116b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" rxBytes=").append(rxBytes);
117b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" rxPackets=").append(rxPackets);
118b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" txBytes=").append(txBytes);
119b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" txPackets=").append(txPackets);
120b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            builder.append(" operations=").append(operations);
121b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            return builder.toString();
122b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        }
123fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    }
1249a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
1254a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    public NetworkStats(long elapsedRealtime, int initialSize) {
1269a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        this.elapsedRealtime = elapsedRealtime;
1274a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        this.size = 0;
1284a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        this.iface = new String[initialSize];
1294a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        this.uid = new int[initialSize];
130b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        this.set = new int[initialSize];
1311b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        this.tag = new int[initialSize];
132d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        this.rxBytes = new long[initialSize];
133fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        this.rxPackets = new long[initialSize];
134d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        this.txBytes = new long[initialSize];
135fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        this.txPackets = new long[initialSize];
13663d27a9233fed934340231f438493746084a681dJeff Sharkey        this.operations = new long[initialSize];
1379a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
1389a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
1399a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public NetworkStats(Parcel parcel) {
1409a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        elapsedRealtime = parcel.readLong();
1414a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        size = parcel.readInt();
1429a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        iface = parcel.createStringArray();
1439a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        uid = parcel.createIntArray();
144b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        set = parcel.createIntArray();
1451b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        tag = parcel.createIntArray();
146d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        rxBytes = parcel.createLongArray();
147fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        rxPackets = parcel.createLongArray();
148d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        txBytes = parcel.createLongArray();
149fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        txPackets = parcel.createLongArray();
15063d27a9233fed934340231f438493746084a681dJeff Sharkey        operations = parcel.createLongArray();
151a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
152a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
153a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /** {@inheritDoc} */
154a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public void writeToParcel(Parcel dest, int flags) {
155a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeLong(elapsedRealtime);
156a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeInt(size);
157a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeStringArray(iface);
158a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeIntArray(uid);
159b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        dest.writeIntArray(set);
160a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeIntArray(tag);
161a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeLongArray(rxBytes);
162a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeLongArray(rxPackets);
163a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeLongArray(txBytes);
164a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dest.writeLongArray(txPackets);
16563d27a9233fed934340231f438493746084a681dJeff Sharkey        dest.writeLongArray(operations);
1669a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
1679a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
168b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    // @VisibleForTesting
169b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public NetworkStats addIfaceValues(
170b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
171b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        return addValues(
172b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
173a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
174a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
175b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    // @VisibleForTesting
176b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public NetworkStats addValues(String iface, int uid, int set, int tag, long rxBytes,
177b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            long rxPackets, long txBytes, long txPackets, long operations) {
178b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        return addValues(new Entry(
179b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
180fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    }
181fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
182fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    /**
183fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey     * Add new stats entry, copying from given {@link Entry}. The {@link Entry}
184fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey     * object can be recycled across multiple calls.
185fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey     */
186fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    public NetworkStats addValues(Entry entry) {
1874a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        if (size >= this.iface.length) {
188fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            final int newLength = Math.max(iface.length, 10) * 3 / 2;
189fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            iface = Arrays.copyOf(iface, newLength);
190fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            uid = Arrays.copyOf(uid, newLength);
191b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            set = Arrays.copyOf(set, newLength);
192fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            tag = Arrays.copyOf(tag, newLength);
193d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            rxBytes = Arrays.copyOf(rxBytes, newLength);
194fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            rxPackets = Arrays.copyOf(rxPackets, newLength);
195d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            txBytes = Arrays.copyOf(txBytes, newLength);
196fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            txPackets = Arrays.copyOf(txPackets, newLength);
197a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            operations = Arrays.copyOf(operations, newLength);
1989a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        }
1999a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
200fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        iface[size] = entry.iface;
201fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        uid[size] = entry.uid;
202b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        set[size] = entry.set;
203fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        tag[size] = entry.tag;
204d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        rxBytes[size] = entry.rxBytes;
205fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        rxPackets[size] = entry.rxPackets;
206d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        txBytes[size] = entry.txBytes;
207fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        txPackets[size] = entry.txPackets;
208a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        operations[size] = entry.operations;
2094a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        size++;
2109a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
2114a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        return this;
2129a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
2139a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
2141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
215fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey     * Return specific stats entry.
216fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey     */
217fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    public Entry getValues(int i, Entry recycle) {
218fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        final Entry entry = recycle != null ? recycle : new Entry();
219fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        entry.iface = iface[i];
220fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        entry.uid = uid[i];
221b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        entry.set = set[i];
222fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        entry.tag = tag[i];
223d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        entry.rxBytes = rxBytes[i];
224fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        entry.rxPackets = rxPackets[i];
225d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        entry.txBytes = txBytes[i];
226fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        entry.txPackets = txPackets[i];
227a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        entry.operations = operations[i];
228fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        return entry;
229fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    }
230fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
231fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    public long getElapsedRealtime() {
232fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        return elapsedRealtime;
233fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    }
234fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
2351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
2361059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Return age of this {@link NetworkStats} object with respect to
2371059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * {@link SystemClock#elapsedRealtime()}.
2381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
2391059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public long getElapsedRealtimeAge() {
2401059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return SystemClock.elapsedRealtime() - elapsedRealtime;
2411059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
2421059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
243fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    public int size() {
244fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        return size;
245fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    }
246fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
247d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    // @VisibleForTesting
248d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    public int internalSize() {
249d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        return iface.length;
250d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    }
251d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
252b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    @Deprecated
253d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
25463d27a9233fed934340231f438493746084a681dJeff Sharkey            long txBytes, long txPackets, long operations) {
255a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        return combineValues(
256b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                iface, uid, SET_DEFAULT, tag, rxBytes, rxPackets, txBytes, txPackets, operations);
257b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
258b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
259b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public NetworkStats combineValues(String iface, int uid, int set, int tag, long rxBytes,
260b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            long rxPackets, long txBytes, long txPackets, long operations) {
261b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        return combineValues(new Entry(
262b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
263d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    }
264d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
265fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey    /**
2661b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     * Combine given values with an existing row, or create a new row if
267b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     * {@link #findIndex(String, int, int, int)} is unable to find match. Can
268b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     * also be used to subtract values from existing rows.
2691b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
270d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    public NetworkStats combineValues(Entry entry) {
271b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag);
2721b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        if (i == -1) {
2731b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            // only create new entry when positive contribution
274d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            addValues(entry);
2751b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        } else {
276d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            rxBytes[i] += entry.rxBytes;
277d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            rxPackets[i] += entry.rxPackets;
278d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            txBytes[i] += entry.txBytes;
279d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            txPackets[i] += entry.txPackets;
280a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            operations[i] += entry.operations;
2811b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
2821b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return this;
283eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    }
284eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
2859a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    /**
286905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     * Combine all values from another {@link NetworkStats} into this object.
287905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     */
288905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    public void combineAllValues(NetworkStats another) {
289905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        NetworkStats.Entry entry = null;
290905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        for (int i = 0; i < another.size; i++) {
291905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry = another.getValues(i, entry);
292905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            combineValues(entry);
293905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        }
294905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
295905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
296905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    /**
2979a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey     * Find first stats index that matches the requested parameters.
2989a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey     */
299b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public int findIndex(String iface, int uid, int set, int tag) {
3004a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        for (int i = 0; i < size; i++) {
301163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
302163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                    && Objects.equal(iface, this.iface[i])) {
303163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                return i;
304163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            }
305163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        }
306163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        return -1;
307163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    }
308163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
309163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    /**
310163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     * Find first stats index that matches the requested parameters, starting
311163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     * search around the hinted index as an optimization.
312163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     */
313163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    // @VisibleForTesting
314163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    public int findIndexHinted(String iface, int uid, int set, int tag, int hintIndex) {
315163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        for (int offset = 0; offset < size; offset++) {
316163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            final int halfOffset = offset / 2;
317163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
318163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            // search outwards from hint index, alternating forward and backward
319163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            final int i;
320163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            if (offset % 2 == 0) {
321163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                i = (hintIndex + halfOffset) % size;
322163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            } else {
323163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                i = (size + hintIndex - halfOffset - 1) % size;
324163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            }
325163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
326163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
327163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                    && Objects.equal(iface, this.iface[i])) {
3289a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey                return i;
3299a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey            }
3309a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        }
3319a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        return -1;
3329a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
3339a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
334eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    /**
335a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * Splice in {@link #operations} from the given {@link NetworkStats} based
336a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface},
337a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * since operation counts are at data layer.
338a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     */
339a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public void spliceOperationsFrom(NetworkStats stats) {
340a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        for (int i = 0; i < size; i++) {
341b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int j = stats.findIndex(IFACE_ALL, uid[i], set[i], tag[i]);
342a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            if (j == -1) {
343a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                operations[i] = 0;
344a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            } else {
345a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                operations[i] = stats.operations[j];
346a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            }
347a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
348a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
349a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
350a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /**
35175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Return list of unique interfaces known by this data structure.
35275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
35361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    public String[] getUniqueIfaces() {
35475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final HashSet<String> ifaces = new HashSet<String>();
35575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        for (String iface : this.iface) {
35675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            if (iface != IFACE_ALL) {
35775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                ifaces.add(iface);
35875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
35975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
36075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        return ifaces.toArray(new String[ifaces.size()]);
36175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
36275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
36375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
36461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     * Return list of unique UIDs known by this data structure.
36561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
36661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    public int[] getUniqueUids() {
36761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final SparseBooleanArray uids = new SparseBooleanArray();
36861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (int uid : this.uid) {
36961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            uids.put(uid, true);
37061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
37161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
37261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final int size = uids.size();
37361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final int[] result = new int[size];
37461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (int i = 0; i < size; i++) {
37561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            result[i] = uids.keyAt(i);
37661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
37761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        return result;
37861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
37961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
38061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
3818e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Return total bytes represented by this snapshot object, usually used when
3828e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
3838e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
3848e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    public long getTotalBytes() {
38507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        final Entry entry = getTotal(null);
38607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        return entry.rxBytes + entry.txBytes;
38707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    }
38807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
38907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    /**
39007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey     * Return total of all fields represented by this snapshot object.
39107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey     */
39207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    public Entry getTotal(Entry recycle) {
3931059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return getTotal(recycle, null, UID_ALL);
3941059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
3951059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
3961059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
3971059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Return total of all fields represented by this snapshot object matching
3981059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * the requested {@link #uid}.
3991059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
4001059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public Entry getTotal(Entry recycle, int limitUid) {
4011059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return getTotal(recycle, null, limitUid);
4021059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
4031059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
4041059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
4051059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Return total of all fields represented by this snapshot object matching
4061059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * the requested {@link #iface}.
4071059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
4081059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public Entry getTotal(Entry recycle, HashSet<String> limitIface) {
4091059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return getTotal(recycle, limitIface, UID_ALL);
4101059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
4111059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
4121059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
4131059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Return total of all fields represented by this snapshot object matching
4141059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * the requested {@link #iface} and {@link #uid}.
4151059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     *
4161059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * @param limitIface Set of {@link #iface} to include in total; or {@code
4171059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     *            null} to include all ifaces.
4181059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
4191059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private Entry getTotal(Entry recycle, HashSet<String> limitIface, int limitUid) {
42007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        final Entry entry = recycle != null ? recycle : new Entry();
42107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
42207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.iface = IFACE_ALL;
4231059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        entry.uid = limitUid;
42407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.set = SET_ALL;
42507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.tag = TAG_NONE;
42607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.rxBytes = 0;
42707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.rxPackets = 0;
42807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.txBytes = 0;
42907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        entry.txPackets = 0;
4301059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        entry.operations = 0;
43107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
4328e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        for (int i = 0; i < size; i++) {
4331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            final boolean matchesUid = (limitUid == UID_ALL) || (limitUid == uid[i]);
4341059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            final boolean matchesIface = (limitIface == null) || (limitIface.contains(iface[i]));
4351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
4361059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            if (matchesUid && matchesIface) {
4371059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                // skip specific tags, since already counted in TAG_NONE
4381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                if (tag[i] != TAG_NONE) continue;
4391059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
4401059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.rxBytes += rxBytes[i];
4411059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.rxPackets += rxPackets[i];
4421059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.txBytes += txBytes[i];
4431059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.txPackets += txPackets[i];
4441059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.operations += operations[i];
4451059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            }
4468e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
44707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        return entry;
4488e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
4498e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
4508e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
451eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey     * Subtract the given {@link NetworkStats}, effectively leaving the delta
452eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey     * between two snapshots in time. Assumes that statistics rows collect over
453eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey     * time, and that none of them have disappeared.
454eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey     */
455163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    public NetworkStats subtract(NetworkStats value) throws NonMonotonicException {
45675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final long deltaRealtime = this.elapsedRealtime - value.elapsedRealtime;
457163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        if (deltaRealtime < 0) {
4583359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey            throw new NonMonotonicException(this, value);
45975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
460eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
46175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // result will have our rows, and elapsed time between snapshots
462fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        final Entry entry = new Entry();
4634a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        final NetworkStats result = new NetworkStats(deltaRealtime, size);
4644a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        for (int i = 0; i < size; i++) {
465fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            entry.iface = iface[i];
466fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            entry.uid = uid[i];
467b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            entry.set = set[i];
468fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            entry.tag = tag[i];
469eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
470eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey            // find remote row that matches, and subtract
471163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            final int j = value.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, i);
472eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey            if (j == -1) {
473eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey                // newly appearing row, return entire value
474d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                entry.rxBytes = rxBytes[i];
475fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey                entry.rxPackets = rxPackets[i];
476d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                entry.txBytes = txBytes[i];
477fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey                entry.txPackets = txPackets[i];
478a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                entry.operations = operations[i];
479eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey            } else {
480eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey                // existing row, subtract remote value
481d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                entry.rxBytes = rxBytes[i] - value.rxBytes[j];
482fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey                entry.rxPackets = rxPackets[i] - value.rxPackets[j];
483d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                entry.txBytes = txBytes[i] - value.txBytes[j];
484fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey                entry.txPackets = txPackets[i] - value.txPackets[j];
485a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                entry.operations = operations[i] - value.operations[j];
486163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
487163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
488163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                        || entry.txPackets < 0 || entry.operations < 0) {
489163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                    throw new NonMonotonicException(this, i, value, j);
4903f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                }
491eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey            }
492fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey
493fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            result.addValues(entry);
494eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey        }
495eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
4964a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        return result;
4979a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
4989a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
499905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    /**
500905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     * Return total statistics grouped by {@link #iface}; doesn't mutate the
501905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     * original structure.
502905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     */
503905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    public NetworkStats groupedByIface() {
504905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
505905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
506905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final Entry entry = new Entry();
507905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        entry.uid = UID_ALL;
508905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        entry.set = SET_ALL;
509905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        entry.tag = TAG_NONE;
510905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        entry.operations = 0L;
511905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
512905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        for (int i = 0; i < size; i++) {
513905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            // skip specific tags, since already counted in TAG_NONE
514905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            if (tag[i] != TAG_NONE) continue;
515905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
516905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.iface = iface[i];
517905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.rxBytes = rxBytes[i];
518905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.rxPackets = rxPackets[i];
519905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.txBytes = txBytes[i];
520905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.txPackets = txPackets[i];
521905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            stats.combineValues(entry);
522905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        }
523905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
524905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return stats;
525905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
526905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
5271059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
5281059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Return total statistics grouped by {@link #uid}; doesn't mutate the
5291059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * original structure.
5301059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
5311059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public NetworkStats groupedByUid() {
5321059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
5331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
5341059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final Entry entry = new Entry();
5351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        entry.iface = IFACE_ALL;
5361059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        entry.set = SET_ALL;
5371059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        entry.tag = TAG_NONE;
5381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
5391059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        for (int i = 0; i < size; i++) {
5401059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            // skip specific tags, since already counted in TAG_NONE
5411059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            if (tag[i] != TAG_NONE) continue;
5421059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
5431059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.uid = uid[i];
5441059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.rxBytes = rxBytes[i];
5451059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.rxPackets = rxPackets[i];
5461059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.txBytes = txBytes[i];
5471059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.txPackets = txPackets[i];
5481059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.operations = operations[i];
5491059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            stats.combineValues(entry);
5501059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
5511059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
5521059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return stats;
5531059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
5541059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
555163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    /**
556163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     * Return all rows except those attributed to the requested UID; doesn't
557163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     * mutate the original structure.
558163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey     */
559163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    public NetworkStats withoutUid(int uid) {
560163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
561163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
562163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        Entry entry = new Entry();
563163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        for (int i = 0; i < size; i++) {
564163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            entry = getValues(i, entry);
565163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            if (entry.uid != uid) {
566163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                stats.addValues(entry);
567163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            }
568163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        }
569163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
570163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        return stats;
571163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    }
572163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
5739a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public void dump(String prefix, PrintWriter pw) {
5749a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        pw.print(prefix);
5759a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
576fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey        for (int i = 0; i < size; i++) {
5779a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey            pw.print(prefix);
5783359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey            pw.print("  ["); pw.print(i); pw.print("]");
5793359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey            pw.print(" iface="); pw.print(iface[i]);
5809a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey            pw.print(" uid="); pw.print(uid[i]);
581b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            pw.print(" set="); pw.print(setToString(set[i]));
582b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            pw.print(" tag="); pw.print(tagToString(tag[i]));
583d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            pw.print(" rxBytes="); pw.print(rxBytes[i]);
584fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey            pw.print(" rxPackets="); pw.print(rxPackets[i]);
585d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            pw.print(" txBytes="); pw.print(txBytes[i]);
586a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            pw.print(" txPackets="); pw.print(txPackets[i]);
587a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            pw.print(" operations="); pw.println(operations[i]);
5889a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        }
5899a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
5909a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
591b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /**
592b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     * Return text description of {@link #set} value.
593b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     */
594b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public static String setToString(int set) {
595b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        switch (set) {
596b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            case SET_ALL:
597b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                return "ALL";
598b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            case SET_DEFAULT:
599b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                return "DEFAULT";
600b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            case SET_FOREGROUND:
601b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                return "FOREGROUND";
602b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            default:
603b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                return "UNKNOWN";
604b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
605b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
606b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
607b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /**
608b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     * Return text description of {@link #tag} value.
609b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     */
610b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public static String tagToString(int tag) {
611b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        return "0x" + Integer.toHexString(tag);
612b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
613b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
6149a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    @Override
6159a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public String toString() {
6169a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        final CharArrayWriter writer = new CharArrayWriter();
6179a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        dump("", new PrintWriter(writer));
6189a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        return writer.toString();
6199a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    }
6209a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
6219a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    /** {@inheritDoc} */
622eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    public int describeContents() {
623eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey        return 0;
624eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    }
625eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
6269a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
6279a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        public NetworkStats createFromParcel(Parcel in) {
6289a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey            return new NetworkStats(in);
6299a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        }
6309a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
6319a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        public NetworkStats[] newArray(int size) {
6329a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey            return new NetworkStats[size];
6339a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey        }
6349a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    };
635163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
636163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    public static class NonMonotonicException extends Exception {
637163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        public final NetworkStats left;
638163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        public final NetworkStats right;
639163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        public final int leftIndex;
640163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        public final int rightIndex;
641163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
6423359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey        public NonMonotonicException(NetworkStats left, NetworkStats right) {
6433359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey            this(left, -1, right, -1);
6443359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey        }
6453359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey
646163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        public NonMonotonicException(
647163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                NetworkStats left, int leftIndex, NetworkStats right, int rightIndex) {
648163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            this.left = checkNotNull(left, "missing left");
649163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            this.right = checkNotNull(right, "missing right");
650163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            this.leftIndex = leftIndex;
651163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            this.rightIndex = rightIndex;
652163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        }
653163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    }
6549a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey}
655