NetworkStats.java revision 905b5891d2aa802f447ac2ce5d77b6c5ba06277a
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; 2247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport android.util.Log; 2361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.util.SparseBooleanArray; 249a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 25a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport com.android.internal.util.Objects; 26a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 279a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.CharArrayWriter; 289a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.PrintWriter; 294a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkeyimport java.util.Arrays; 3075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.HashSet; 319a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 329a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey/** 3375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collection of active network statistics. Can contain summary details across 3475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * all interfaces, or details with per-UID granularity. Internally stores data 3575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * as a large table, closely matching {@code /proc/} data format. This structure 3675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * optimizes for rapid in-memory comparison, but consider using 3775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * {@link NetworkStatsHistory} when persisting. 389a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * 399a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * @hide 409a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey */ 419a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeypublic class NetworkStats implements Parcelable { 4247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey private static final String TAG = "NetworkStats"; 4347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey 4475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** {@link #iface} value when interface details unavailable. */ 459a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public static final String IFACE_ALL = null; 4675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** {@link #uid} value when UID details unavailable. */ 4775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public static final int UID_ALL = -1; 48b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey /** {@link #set} value when all sets combined. */ 49b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public static final int SET_ALL = -1; 50b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey /** {@link #set} value where background data is accounted. */ 51b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public static final int SET_DEFAULT = 0; 52b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey /** {@link #set} value where foreground data is accounted. */ 53b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public static final int SET_FOREGROUND = 1; 54b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey /** {@link #tag} value for total data across all tags. */ 551b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey public static final int TAG_NONE = 0; 56eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 579a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey /** 589a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * {@link SystemClock#elapsedRealtime()} timestamp when this data was 599a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * generated. 609a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey */ 61d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private final long elapsedRealtime; 62d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private int size; 63d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private String[] iface; 64d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private int[] uid; 65b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey private int[] set; 66d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private int[] tag; 67d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private long[] rxBytes; 68d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private long[] rxPackets; 69d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private long[] txBytes; 70d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private long[] txPackets; 7163d27a9233fed934340231f438493746084a681dJeff Sharkey private long[] operations; 72fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 73fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public static class Entry { 74fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public String iface; 75fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public int uid; 76b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public int set; 77fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public int tag; 78fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public long rxBytes; 79fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public long rxPackets; 80fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public long txBytes; 81fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public long txPackets; 8263d27a9233fed934340231f438493746084a681dJeff Sharkey public long operations; 83d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 84d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public Entry() { 85b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); 8663d27a9233fed934340231f438493746084a681dJeff Sharkey } 8763d27a9233fed934340231f438493746084a681dJeff Sharkey 8863d27a9233fed934340231f438493746084a681dJeff Sharkey public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { 89b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 90b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey operations); 91d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 92d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 93b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets, 94b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey long txBytes, long txPackets, long operations) { 95d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey this.iface = iface; 96d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey this.uid = uid; 97b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey this.set = set; 98d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey this.tag = tag; 99d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey this.rxBytes = rxBytes; 100d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey this.rxPackets = rxPackets; 101d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey this.txBytes = txBytes; 102d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey this.txPackets = txPackets; 103a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey this.operations = operations; 104d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 105b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey 106b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey @Override 107b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey public String toString() { 108b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey final StringBuilder builder = new StringBuilder(); 109b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey builder.append("iface=").append(iface); 110b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey builder.append(" uid=").append(uid); 111b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey builder.append(" set=").append(setToString(set)); 112b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey builder.append(" tag=").append(tagToString(tag)); 113b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey builder.append(" rxBytes=").append(rxBytes); 114b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey builder.append(" rxPackets=").append(rxPackets); 115b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey builder.append(" txBytes=").append(txBytes); 116b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey builder.append(" txPackets=").append(txPackets); 117b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey builder.append(" operations=").append(operations); 118b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey return builder.toString(); 119b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey } 120fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } 1219a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 1224a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey public NetworkStats(long elapsedRealtime, int initialSize) { 1239a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey this.elapsedRealtime = elapsedRealtime; 1244a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey this.size = 0; 1254a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey this.iface = new String[initialSize]; 1264a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey this.uid = new int[initialSize]; 127b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey this.set = new int[initialSize]; 1281b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey this.tag = new int[initialSize]; 129d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey this.rxBytes = new long[initialSize]; 130fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey this.rxPackets = new long[initialSize]; 131d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey this.txBytes = new long[initialSize]; 132fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey this.txPackets = new long[initialSize]; 13363d27a9233fed934340231f438493746084a681dJeff Sharkey this.operations = new long[initialSize]; 1349a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 1359a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 1369a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public NetworkStats(Parcel parcel) { 1379a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey elapsedRealtime = parcel.readLong(); 1384a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey size = parcel.readInt(); 1399a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey iface = parcel.createStringArray(); 1409a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey uid = parcel.createIntArray(); 141b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey set = parcel.createIntArray(); 1421b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey tag = parcel.createIntArray(); 143d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey rxBytes = parcel.createLongArray(); 144fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey rxPackets = parcel.createLongArray(); 145d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey txBytes = parcel.createLongArray(); 146fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey txPackets = parcel.createLongArray(); 14763d27a9233fed934340231f438493746084a681dJeff Sharkey operations = parcel.createLongArray(); 148a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 149a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 150a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey /** {@inheritDoc} */ 151a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public void writeToParcel(Parcel dest, int flags) { 152a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey dest.writeLong(elapsedRealtime); 153a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey dest.writeInt(size); 154a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey dest.writeStringArray(iface); 155a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey dest.writeIntArray(uid); 156b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey dest.writeIntArray(set); 157a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey dest.writeIntArray(tag); 158a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey dest.writeLongArray(rxBytes); 159a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey dest.writeLongArray(rxPackets); 160a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey dest.writeLongArray(txBytes); 161a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey dest.writeLongArray(txPackets); 16263d27a9233fed934340231f438493746084a681dJeff Sharkey dest.writeLongArray(operations); 1639a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 1649a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 165b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey // @VisibleForTesting 166b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public NetworkStats addIfaceValues( 167b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) { 168b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey return addValues( 169b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L); 170a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 171a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 172b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey // @VisibleForTesting 173b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public NetworkStats addValues(String iface, int uid, int set, int tag, long rxBytes, 174b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey long rxPackets, long txBytes, long txPackets, long operations) { 175b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey return addValues(new Entry( 176b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations)); 177fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } 178fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 179fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey /** 180fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey * Add new stats entry, copying from given {@link Entry}. The {@link Entry} 181fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey * object can be recycled across multiple calls. 182fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey */ 183fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public NetworkStats addValues(Entry entry) { 1844a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey if (size >= this.iface.length) { 185fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final int newLength = Math.max(iface.length, 10) * 3 / 2; 186fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey iface = Arrays.copyOf(iface, newLength); 187fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey uid = Arrays.copyOf(uid, newLength); 188b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey set = Arrays.copyOf(set, newLength); 189fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey tag = Arrays.copyOf(tag, newLength); 190d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey rxBytes = Arrays.copyOf(rxBytes, newLength); 191fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey rxPackets = Arrays.copyOf(rxPackets, newLength); 192d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey txBytes = Arrays.copyOf(txBytes, newLength); 193fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey txPackets = Arrays.copyOf(txPackets, newLength); 194a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey operations = Arrays.copyOf(operations, newLength); 1959a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 1969a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 197fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey iface[size] = entry.iface; 198fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey uid[size] = entry.uid; 199b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey set[size] = entry.set; 200fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey tag[size] = entry.tag; 201d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey rxBytes[size] = entry.rxBytes; 202fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey rxPackets[size] = entry.rxPackets; 203d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey txBytes[size] = entry.txBytes; 204fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey txPackets[size] = entry.txPackets; 205a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey operations[size] = entry.operations; 2064a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey size++; 2079a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 2084a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey return this; 2099a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 2109a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 2111b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey /** 212fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey * Return specific stats entry. 213fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey */ 214fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public Entry getValues(int i, Entry recycle) { 215fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final Entry entry = recycle != null ? recycle : new Entry(); 216fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.iface = iface[i]; 217fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.uid = uid[i]; 218b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey entry.set = set[i]; 219fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.tag = tag[i]; 220d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry.rxBytes = rxBytes[i]; 221fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxPackets = rxPackets[i]; 222d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry.txBytes = txBytes[i]; 223fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txPackets = txPackets[i]; 224a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey entry.operations = operations[i]; 225fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey return entry; 226fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } 227fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 228fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public long getElapsedRealtime() { 229fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey return elapsedRealtime; 230fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } 231fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 232fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public int size() { 233fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey return size; 234fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } 235fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 236d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey // @VisibleForTesting 237d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public int internalSize() { 238d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey return iface.length; 239d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 240d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 241b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey @Deprecated 242d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets, 24363d27a9233fed934340231f438493746084a681dJeff Sharkey long txBytes, long txPackets, long operations) { 244a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey return combineValues( 245b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey iface, uid, SET_DEFAULT, tag, rxBytes, rxPackets, txBytes, txPackets, operations); 246b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 247b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 248b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public NetworkStats combineValues(String iface, int uid, int set, int tag, long rxBytes, 249b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey long rxPackets, long txBytes, long txPackets, long operations) { 250b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey return combineValues(new Entry( 251b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations)); 252d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 253d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 254fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey /** 2551b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * Combine given values with an existing row, or create a new row if 256b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey * {@link #findIndex(String, int, int, int)} is unable to find match. Can 257b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey * also be used to subtract values from existing rows. 2581b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey */ 259d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public NetworkStats combineValues(Entry entry) { 260b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag); 2611b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (i == -1) { 2621b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey // only create new entry when positive contribution 263d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey addValues(entry); 2641b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } else { 265d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey rxBytes[i] += entry.rxBytes; 266d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey rxPackets[i] += entry.rxPackets; 267d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey txBytes[i] += entry.txBytes; 268d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey txPackets[i] += entry.txPackets; 269a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey operations[i] += entry.operations; 2701b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 2711b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey return this; 272eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 273eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 2749a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey /** 275905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey * Combine all values from another {@link NetworkStats} into this object. 276905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey */ 277905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey public void combineAllValues(NetworkStats another) { 278905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey NetworkStats.Entry entry = null; 279905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey for (int i = 0; i < another.size; i++) { 280905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry = another.getValues(i, entry); 281905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey combineValues(entry); 282905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey } 283905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey } 284905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey 285905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey /** 2869a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * Find first stats index that matches the requested parameters. 2879a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey */ 288b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public int findIndex(String iface, int uid, int set, int tag) { 2894a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey for (int i = 0; i < size; i++) { 290b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey if (Objects.equal(iface, this.iface[i]) && uid == this.uid[i] && set == this.set[i] 291b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey && tag == this.tag[i]) { 2929a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey return i; 2939a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 2949a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 2959a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey return -1; 2969a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 2979a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 298eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey /** 299a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * Splice in {@link #operations} from the given {@link NetworkStats} based 300a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface}, 301a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * since operation counts are at data layer. 302a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey */ 303a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public void spliceOperationsFrom(NetworkStats stats) { 304a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey for (int i = 0; i < size; i++) { 305b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey final int j = stats.findIndex(IFACE_ALL, uid[i], set[i], tag[i]); 306a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey if (j == -1) { 307a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey operations[i] = 0; 308a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } else { 309a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey operations[i] = stats.operations[j]; 310a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 311a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 312a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 313a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 314a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey /** 31575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Return list of unique interfaces known by this data structure. 31675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 31761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey public String[] getUniqueIfaces() { 31875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final HashSet<String> ifaces = new HashSet<String>(); 31975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (String iface : this.iface) { 32075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (iface != IFACE_ALL) { 32175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey ifaces.add(iface); 32275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 32375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 32475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return ifaces.toArray(new String[ifaces.size()]); 32575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 32675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 32775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 32861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey * Return list of unique UIDs known by this data structure. 32961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey */ 33061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey public int[] getUniqueUids() { 33161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey final SparseBooleanArray uids = new SparseBooleanArray(); 33261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey for (int uid : this.uid) { 33361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey uids.put(uid, true); 33461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 33561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 33661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey final int size = uids.size(); 33761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey final int[] result = new int[size]; 33861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey for (int i = 0; i < size; i++) { 33961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey result[i] = uids.keyAt(i); 34061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 34161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey return result; 34261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 34361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 34461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey /** 3458e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey * Return total bytes represented by this snapshot object, usually used when 3468e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey * checking if a {@link #subtract(NetworkStats)} delta passes a threshold. 3478e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey */ 3488e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey public long getTotalBytes() { 34907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey final Entry entry = getTotal(null); 35007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey return entry.rxBytes + entry.txBytes; 35107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey } 35207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey 35307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey /** 35407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey * Return total of all fields represented by this snapshot object. 35507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey */ 35607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey public Entry getTotal(Entry recycle) { 35707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey final Entry entry = recycle != null ? recycle : new Entry(); 35807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey 35907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.iface = IFACE_ALL; 36007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.uid = UID_ALL; 36107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.set = SET_ALL; 36207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.tag = TAG_NONE; 36307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.rxBytes = 0; 36407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.rxPackets = 0; 36507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.txBytes = 0; 36607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.txPackets = 0; 36707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey 3688e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey for (int i = 0; i < size; i++) { 3698e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey // skip specific tags, since already counted in TAG_NONE 3708e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey if (tag[i] != TAG_NONE) continue; 3718e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey 37207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.rxBytes += rxBytes[i]; 37307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.rxPackets += rxPackets[i]; 37407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.txBytes += txBytes[i]; 37507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.txPackets += txPackets[i]; 37607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey entry.operations += operations[i]; 3778e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey } 37807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey return entry; 3798e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey } 3808e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey 3818e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey /** 382eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey * Subtract the given {@link NetworkStats}, effectively leaving the delta 383eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey * between two snapshots in time. Assumes that statistics rows collect over 384eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey * time, and that none of them have disappeared. 38575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 3863f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * @throws IllegalArgumentException when given {@link NetworkStats} is 3873f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * non-monotonic. 3883f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey */ 3893f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey public NetworkStats subtract(NetworkStats value) { 3903f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey return subtract(value, true, false); 3913f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey } 3923f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey 3933f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey /** 3943f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * Subtract the given {@link NetworkStats}, effectively leaving the delta 3953f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * between two snapshots in time. Assumes that statistics rows collect over 3963f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * time, and that none of them have disappeared. 3973f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * <p> 3983f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * Instead of throwing when counters are non-monotonic, this variant clamps 3993f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * results to never be negative. 4003f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey */ 4013f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey public NetworkStats subtractClamped(NetworkStats value) { 4023f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey return subtract(value, false, true); 4033f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey } 4043f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey 4053f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey /** 4063f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * Subtract the given {@link NetworkStats}, effectively leaving the delta 4073f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * between two snapshots in time. Assumes that statistics rows collect over 4083f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * time, and that none of them have disappeared. 4093f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * 41075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * @param enforceMonotonic Validate that incoming value is strictly 41175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * monotonic compared to this object. 4123f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * @param clampNegative Instead of throwing like {@code enforceMonotonic}, 4133f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey * clamp resulting counters at 0 to prevent negative values. 414eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey */ 4153f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey private NetworkStats subtract( 4163f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey NetworkStats value, boolean enforceMonotonic, boolean clampNegative) { 41775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long deltaRealtime = this.elapsedRealtime - value.elapsedRealtime; 41875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (enforceMonotonic && deltaRealtime < 0) { 41975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey throw new IllegalArgumentException("found non-monotonic realtime"); 42075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 421eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 42275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // result will have our rows, and elapsed time between snapshots 423fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final Entry entry = new Entry(); 4244a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey final NetworkStats result = new NetworkStats(deltaRealtime, size); 4254a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey for (int i = 0; i < size; i++) { 426fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.iface = iface[i]; 427fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.uid = uid[i]; 428b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey entry.set = set[i]; 429fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.tag = tag[i]; 430eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 431eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey // find remote row that matches, and subtract 432b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey final int j = value.findIndex(entry.iface, entry.uid, entry.set, entry.tag); 433eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey if (j == -1) { 434eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey // newly appearing row, return entire value 435d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry.rxBytes = rxBytes[i]; 436fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxPackets = rxPackets[i]; 437d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry.txBytes = txBytes[i]; 438fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txPackets = txPackets[i]; 439a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey entry.operations = operations[i]; 440eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } else { 441eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey // existing row, subtract remote value 442d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry.rxBytes = rxBytes[i] - value.rxBytes[j]; 443fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxPackets = rxPackets[i] - value.rxPackets[j]; 444d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry.txBytes = txBytes[i] - value.txBytes[j]; 445fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txPackets = txPackets[i] - value.txPackets[j]; 446a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey entry.operations = operations[i] - value.operations[j]; 447fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey if (enforceMonotonic 448fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey && (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 449a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey || entry.txPackets < 0 || entry.operations < 0)) { 45047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey Log.v(TAG, "lhs=" + this); 45147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey Log.v(TAG, "rhs=" + value); 45247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey throw new IllegalArgumentException( 45347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey "found non-monotonic values at lhs[" + i + "] - rhs[" + j + "]"); 45475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 4553f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey if (clampNegative) { 456fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxBytes = Math.max(0, entry.rxBytes); 457fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxPackets = Math.max(0, entry.rxPackets); 458fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txBytes = Math.max(0, entry.txBytes); 459fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txPackets = Math.max(0, entry.txPackets); 460a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey entry.operations = Math.max(0, entry.operations); 4613f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey } 462eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 463fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 464fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey result.addValues(entry); 465eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 466eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 4674a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey return result; 4689a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 4699a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 470905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey /** 471905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey * Return total statistics grouped by {@link #iface}; doesn't mutate the 472905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey * original structure. 473905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey */ 474905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey public NetworkStats groupedByIface() { 475905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey final NetworkStats stats = new NetworkStats(elapsedRealtime, 10); 476905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey 477905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey final Entry entry = new Entry(); 478905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.uid = UID_ALL; 479905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.set = SET_ALL; 480905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.tag = TAG_NONE; 481905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.operations = 0L; 482905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey 483905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey for (int i = 0; i < size; i++) { 484905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey // skip specific tags, since already counted in TAG_NONE 485905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey if (tag[i] != TAG_NONE) continue; 486905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey 487905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.iface = iface[i]; 488905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.rxBytes = rxBytes[i]; 489905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.rxPackets = rxPackets[i]; 490905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.txBytes = txBytes[i]; 491905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.txPackets = txPackets[i]; 492905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey stats.combineValues(entry); 493905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey } 494905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey 495905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey return stats; 496905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey } 497905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey 4989a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public void dump(String prefix, PrintWriter pw) { 4999a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey pw.print(prefix); 5009a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime); 501fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey for (int i = 0; i < size; i++) { 5029a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey pw.print(prefix); 5039a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey pw.print(" iface="); pw.print(iface[i]); 5049a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey pw.print(" uid="); pw.print(uid[i]); 505b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey pw.print(" set="); pw.print(setToString(set[i])); 506b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey pw.print(" tag="); pw.print(tagToString(tag[i])); 507d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey pw.print(" rxBytes="); pw.print(rxBytes[i]); 508fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey pw.print(" rxPackets="); pw.print(rxPackets[i]); 509d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey pw.print(" txBytes="); pw.print(txBytes[i]); 510a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey pw.print(" txPackets="); pw.print(txPackets[i]); 511a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey pw.print(" operations="); pw.println(operations[i]); 5129a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 5139a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 5149a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 515b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey /** 516b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey * Return text description of {@link #set} value. 517b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey */ 518b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public static String setToString(int set) { 519b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey switch (set) { 520b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey case SET_ALL: 521b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey return "ALL"; 522b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey case SET_DEFAULT: 523b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey return "DEFAULT"; 524b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey case SET_FOREGROUND: 525b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey return "FOREGROUND"; 526b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey default: 527b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey return "UNKNOWN"; 528b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 529b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 530b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 531b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey /** 532b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey * Return text description of {@link #tag} value. 533b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey */ 534b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public static String tagToString(int tag) { 535b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey return "0x" + Integer.toHexString(tag); 536b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 537b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 5389a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey @Override 5399a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public String toString() { 5409a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey final CharArrayWriter writer = new CharArrayWriter(); 5419a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey dump("", new PrintWriter(writer)); 5429a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey return writer.toString(); 5439a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 5449a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 5459a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey /** {@inheritDoc} */ 546eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey public int describeContents() { 547eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey return 0; 548eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 549eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 5509a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() { 5519a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public NetworkStats createFromParcel(Parcel in) { 5529a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey return new NetworkStats(in); 5539a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 5549a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 5559a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public NetworkStats[] newArray(int size) { 5569a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey return new NetworkStats[size]; 5579a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 5589a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey }; 5599a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey} 560