175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/* 275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project 375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * you may not use this file except in compliance with the License. 675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * You may obtain a copy of the License at 775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 1075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 1175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 1275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * See the License for the specific language governing permissions and 1475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * limitations under the License. 1575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 1675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 1775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypackage android.net; 1875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 19a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static android.net.NetworkStats.IFACE_ALL; 20b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_DEFAULT; 21a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static android.net.NetworkStats.TAG_NONE; 22a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static android.net.NetworkStats.UID_ALL; 2363d27a9233fed934340231f438493746084a681dJeff Sharkeyimport static android.net.NetworkStatsHistory.DataStreamUtils.readFullLongArray; 2463d27a9233fed934340231f438493746084a681dJeff Sharkeyimport static android.net.NetworkStatsHistory.DataStreamUtils.readVarLongArray; 2563d27a9233fed934340231f438493746084a681dJeff Sharkeyimport static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLongArray; 2663d27a9233fed934340231f438493746084a681dJeff Sharkeyimport static android.net.NetworkStatsHistory.Entry.UNKNOWN; 27a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; 28a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; 2955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkeyimport static android.text.format.DateUtils.SECOND_IN_MILLIS; 30f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey 3163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static com.android.internal.util.ArrayUtils.total; 32a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 3375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Parcel; 3475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Parcelable; 35da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onukiimport android.service.NetworkStatsHistoryBucketProto; 36da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onukiimport android.service.NetworkStatsHistoryProto; 3769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkeyimport android.util.MathUtils; 38da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onukiimport android.util.proto.ProtoOutputStream; 3975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 4063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 4163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 4275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.CharArrayWriter; 4375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.DataInputStream; 4475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.DataOutputStream; 4575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.IOException; 4655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkeyimport java.io.PrintWriter; 4761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.net.ProtocolException; 4875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.Arrays; 4961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.util.Random; 5075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 5175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/** 5275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collection of historical network statistics, recorded into equally-sized 5375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * "buckets" in time. Internally it stores data in {@code long} series for more 5475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * efficient persistence. 5575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * <p> 5675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Each bucket is defined by a {@link #bucketStart} timestamp, and lasts for 5775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * {@link #bucketDuration}. Internally assumes that {@link #bucketStart} is 5875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * sorted at all times. 5975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 6075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * @hide 6175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 6275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypublic class NetworkStatsHistory implements Parcelable { 631b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey private static final int VERSION_INIT = 1; 6463d27a9233fed934340231f438493746084a681dJeff Sharkey private static final int VERSION_ADD_PACKETS = 2; 65558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey private static final int VERSION_ADD_ACTIVE = 3; 6675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 67558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_ACTIVE_TIME = 0x01; 68558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_RX_BYTES = 0x02; 69558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_RX_PACKETS = 0x04; 70558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_TX_BYTES = 0x08; 71558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_TX_PACKETS = 0x10; 72558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_OPERATIONS = 0x20; 73d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 7463d27a9233fed934340231f438493746084a681dJeff Sharkey public static final int FIELD_ALL = 0xFFFFFFFF; 7563d27a9233fed934340231f438493746084a681dJeff Sharkey 7663d27a9233fed934340231f438493746084a681dJeff Sharkey private long bucketDuration; 77d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private int bucketCount; 78d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private long[] bucketStart; 79558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey private long[] activeTime; 80d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private long[] rxBytes; 81a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey private long[] rxPackets; 82d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private long[] txBytes; 83a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey private long[] txPackets; 8463d27a9233fed934340231f438493746084a681dJeff Sharkey private long[] operations; 8563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private long totalBytes; 86d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 87d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public static class Entry { 8863d27a9233fed934340231f438493746084a681dJeff Sharkey public static final long UNKNOWN = -1; 8963d27a9233fed934340231f438493746084a681dJeff Sharkey 90d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public long bucketDuration; 91558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public long bucketStart; 92558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public long activeTime; 93d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public long rxBytes; 94a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public long rxPackets; 95d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public long txBytes; 96a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public long txPackets; 9763d27a9233fed934340231f438493746084a681dJeff Sharkey public long operations; 98d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 9975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 100d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public NetworkStatsHistory(long bucketDuration) { 10163d27a9233fed934340231f438493746084a681dJeff Sharkey this(bucketDuration, 10, FIELD_ALL); 1024a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey } 1034a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey 1044a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey public NetworkStatsHistory(long bucketDuration, int initialSize) { 10563d27a9233fed934340231f438493746084a681dJeff Sharkey this(bucketDuration, initialSize, FIELD_ALL); 10663d27a9233fed934340231f438493746084a681dJeff Sharkey } 10763d27a9233fed934340231f438493746084a681dJeff Sharkey 10863d27a9233fed934340231f438493746084a681dJeff Sharkey public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) { 10975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey this.bucketDuration = bucketDuration; 1104a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey bucketStart = new long[initialSize]; 111558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey if ((fields & FIELD_ACTIVE_TIME) != 0) activeTime = new long[initialSize]; 11263d27a9233fed934340231f438493746084a681dJeff Sharkey if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize]; 11363d27a9233fed934340231f438493746084a681dJeff Sharkey if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize]; 11463d27a9233fed934340231f438493746084a681dJeff Sharkey if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize]; 11563d27a9233fed934340231f438493746084a681dJeff Sharkey if ((fields & FIELD_TX_PACKETS) != 0) txPackets = new long[initialSize]; 11663d27a9233fed934340231f438493746084a681dJeff Sharkey if ((fields & FIELD_OPERATIONS) != 0) operations = new long[initialSize]; 1174a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey bucketCount = 0; 11863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey totalBytes = 0; 11963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 12063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 12163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStatsHistory(NetworkStatsHistory existing, long bucketDuration) { 12263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey this(bucketDuration, existing.estimateResizeBuckets(bucketDuration)); 12363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey recordEntireHistory(existing); 12475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 12575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 12675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory(Parcel in) { 12775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketDuration = in.readLong(); 12875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = readLongArray(in); 129558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey activeTime = readLongArray(in); 130a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey rxBytes = readLongArray(in); 131a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey rxPackets = readLongArray(in); 132a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey txBytes = readLongArray(in); 133a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey txPackets = readLongArray(in); 13463d27a9233fed934340231f438493746084a681dJeff Sharkey operations = readLongArray(in); 13575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount = bucketStart.length; 13663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey totalBytes = in.readLong(); 13775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 13875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 139bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 14075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void writeToParcel(Parcel out, int flags) { 14175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(bucketDuration); 14275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, bucketStart, bucketCount); 143558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey writeLongArray(out, activeTime, bucketCount); 144d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey writeLongArray(out, rxBytes, bucketCount); 145a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey writeLongArray(out, rxPackets, bucketCount); 146d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey writeLongArray(out, txBytes, bucketCount); 147a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey writeLongArray(out, txPackets, bucketCount); 14863d27a9233fed934340231f438493746084a681dJeff Sharkey writeLongArray(out, operations, bucketCount); 14963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeLong(totalBytes); 15075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 15175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 15275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory(DataInputStream in) throws IOException { 15375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int version = in.readInt(); 15461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey switch (version) { 1551b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey case VERSION_INIT: { 15661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey bucketDuration = in.readLong(); 15763d27a9233fed934340231f438493746084a681dJeff Sharkey bucketStart = readFullLongArray(in); 15863d27a9233fed934340231f438493746084a681dJeff Sharkey rxBytes = readFullLongArray(in); 159a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey rxPackets = new long[bucketStart.length]; 16063d27a9233fed934340231f438493746084a681dJeff Sharkey txBytes = readFullLongArray(in); 161a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey txPackets = new long[bucketStart.length]; 16263d27a9233fed934340231f438493746084a681dJeff Sharkey operations = new long[bucketStart.length]; 16363d27a9233fed934340231f438493746084a681dJeff Sharkey bucketCount = bucketStart.length; 16463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey totalBytes = total(rxBytes) + total(txBytes); 16563d27a9233fed934340231f438493746084a681dJeff Sharkey break; 16663d27a9233fed934340231f438493746084a681dJeff Sharkey } 167558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey case VERSION_ADD_PACKETS: 168558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey case VERSION_ADD_ACTIVE: { 16963d27a9233fed934340231f438493746084a681dJeff Sharkey bucketDuration = in.readLong(); 17063d27a9233fed934340231f438493746084a681dJeff Sharkey bucketStart = readVarLongArray(in); 171558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey activeTime = (version >= VERSION_ADD_ACTIVE) ? readVarLongArray(in) 172558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey : new long[bucketStart.length]; 17363d27a9233fed934340231f438493746084a681dJeff Sharkey rxBytes = readVarLongArray(in); 17463d27a9233fed934340231f438493746084a681dJeff Sharkey rxPackets = readVarLongArray(in); 17563d27a9233fed934340231f438493746084a681dJeff Sharkey txBytes = readVarLongArray(in); 17663d27a9233fed934340231f438493746084a681dJeff Sharkey txPackets = readVarLongArray(in); 17763d27a9233fed934340231f438493746084a681dJeff Sharkey operations = readVarLongArray(in); 17861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey bucketCount = bucketStart.length; 17963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey totalBytes = total(rxBytes) + total(txBytes); 18061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey break; 18161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 18261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey default: { 18361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey throw new ProtocolException("unexpected version: " + version); 18461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 18561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 186b0a579f83369ca2daa885222a35f1cd3c054ab11Jeff Sharkey 187b0a579f83369ca2daa885222a35f1cd3c054ab11Jeff Sharkey if (bucketStart.length != bucketCount || rxBytes.length != bucketCount 188b0a579f83369ca2daa885222a35f1cd3c054ab11Jeff Sharkey || rxPackets.length != bucketCount || txBytes.length != bucketCount 189b0a579f83369ca2daa885222a35f1cd3c054ab11Jeff Sharkey || txPackets.length != bucketCount || operations.length != bucketCount) { 190b0a579f83369ca2daa885222a35f1cd3c054ab11Jeff Sharkey throw new ProtocolException("Mismatched history lengths"); 191b0a579f83369ca2daa885222a35f1cd3c054ab11Jeff Sharkey } 19275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 19375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 19475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void writeToStream(DataOutputStream out) throws IOException { 195558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey out.writeInt(VERSION_ADD_ACTIVE); 19675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(bucketDuration); 19763d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, bucketStart, bucketCount); 198558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey writeVarLongArray(out, activeTime, bucketCount); 19963d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, rxBytes, bucketCount); 20063d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, rxPackets, bucketCount); 20163d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, txBytes, bucketCount); 20263d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, txPackets, bucketCount); 20363d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, operations, bucketCount); 20475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 20575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 206bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 20775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public int describeContents() { 20875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return 0; 20975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 21075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 211d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public int size() { 212d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey return bucketCount; 213d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 214d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 215d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public long getBucketDuration() { 216d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey return bucketDuration; 217d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 218d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 219434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey public long getStart() { 220434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey if (bucketCount > 0) { 221434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return bucketStart[0]; 222434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } else { 223434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return Long.MAX_VALUE; 224434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } 225434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } 226434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey 227434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey public long getEnd() { 228434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey if (bucketCount > 0) { 229434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return bucketStart[bucketCount - 1] + bucketDuration; 230434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } else { 231434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return Long.MIN_VALUE; 232434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } 233434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } 234434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey 235d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey /** 23663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Return total bytes represented by this history. 23763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 23863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public long getTotalBytes() { 23963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return totalBytes; 24063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 24163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 24263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 24369b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey * Return index of bucket that contains or is immediately before the 24469b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey * requested time. 24569b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey */ 24669b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey public int getIndexBefore(long time) { 24769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); 24869b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey if (index < 0) { 24969b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey index = (~index) - 1; 25069b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } else { 25169b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey index -= 1; 25269b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } 25369b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey return MathUtils.constrain(index, 0, bucketCount - 1); 25469b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } 25569b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey 25669b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey /** 25769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey * Return index of bucket that contains or is immediately after the 25869b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey * requested time. 25969b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey */ 26069b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey public int getIndexAfter(long time) { 26169b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); 26269b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey if (index < 0) { 26369b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey index = ~index; 26469b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } else { 26569b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey index += 1; 26669b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } 26769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey return MathUtils.constrain(index, 0, bucketCount - 1); 26869b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } 26969b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey 27069b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey /** 271d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey * Return specific stats entry. 272d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey */ 273d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public Entry getValues(int i, Entry recycle) { 274d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey final Entry entry = recycle != null ? recycle : new Entry(); 275d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry.bucketStart = bucketStart[i]; 276d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry.bucketDuration = bucketDuration; 277558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey entry.activeTime = getLong(activeTime, i, UNKNOWN); 27863d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxBytes = getLong(rxBytes, i, UNKNOWN); 27963d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxPackets = getLong(rxPackets, i, UNKNOWN); 28063d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txBytes = getLong(txBytes, i, UNKNOWN); 28163d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txPackets = getLong(txPackets, i, UNKNOWN); 28263d27a9233fed934340231f438493746084a681dJeff Sharkey entry.operations = getLong(operations, i, UNKNOWN); 283d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey return entry; 284d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 285d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 286f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey public void setValues(int i, Entry entry) { 287f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey // Unwind old values 288f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey if (rxBytes != null) totalBytes -= rxBytes[i]; 289f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey if (txBytes != null) totalBytes -= txBytes[i]; 290f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey 291f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey bucketStart[i] = entry.bucketStart; 292f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey setLong(activeTime, i, entry.activeTime); 293f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey setLong(rxBytes, i, entry.rxBytes); 294f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey setLong(rxPackets, i, entry.rxPackets); 295f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey setLong(txBytes, i, entry.txBytes); 296f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey setLong(txPackets, i, entry.txPackets); 297f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey setLong(operations, i, entry.operations); 298f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey 299f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey // Apply new values 300f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey if (rxBytes != null) totalBytes += rxBytes[i]; 301f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey if (txBytes != null) totalBytes += txBytes[i]; 302f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey } 303f4de294297de47d8c594956b2d8607e314e71836Jeff Sharkey 30475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 30575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Record that data traffic occurred in the given time range. Will 30675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * distribute across internal buckets, creating new buckets as needed. 30775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 308a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey @Deprecated 309a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public void recordData(long start, long end, long rxBytes, long txBytes) { 310b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey recordData(start, end, new NetworkStats.Entry( 311b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0L)); 312a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 313a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 314a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey /** 315a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * Record that data traffic occurred in the given time range. Will 316a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * distribute across internal buckets, creating new buckets as needed. 317a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey */ 318a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public void recordData(long start, long end, NetworkStats.Entry entry) { 31963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long rxBytes = entry.rxBytes; 32063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long rxPackets = entry.rxPackets; 32163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long txBytes = entry.txBytes; 32263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long txPackets = entry.txPackets; 32363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long operations = entry.operations; 32463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 32563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (entry.isNegative()) { 326a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey throw new IllegalArgumentException("tried recording negative data"); 3271b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 32863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (entry.isEmpty()) { 329367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey return; 330367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey } 3311b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 33275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create any buckets needed by this range 33375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey ensureBuckets(start, end); 33475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 33575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // distribute data usage into buckets 336a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey long duration = end - start; 33769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey final int startIndex = getIndexAfter(end); 33869b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey for (int i = startIndex; i >= 0; i--) { 33975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curStart = bucketStart[i]; 34075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curEnd = curStart + bucketDuration; 34175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 34275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket is older than record; we're finished 34375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curEnd < start) break; 34475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket is newer than record; keep looking 34575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curStart > end) continue; 34675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 34775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); 348a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey if (overlap <= 0) continue; 349a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 350a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey // integer math each time is faster than floating point 35163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long fracRxBytes = rxBytes * overlap / duration; 35263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long fracRxPackets = rxPackets * overlap / duration; 35363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long fracTxBytes = txBytes * overlap / duration; 35463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long fracTxPackets = txPackets * overlap / duration; 35563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long fracOperations = operations * overlap / duration; 356a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 357558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey addLong(activeTime, i, overlap); 35863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey addLong(this.rxBytes, i, fracRxBytes); rxBytes -= fracRxBytes; 35963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey addLong(this.rxPackets, i, fracRxPackets); rxPackets -= fracRxPackets; 36063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey addLong(this.txBytes, i, fracTxBytes); txBytes -= fracTxBytes; 36163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey addLong(this.txPackets, i, fracTxPackets); txPackets -= fracTxPackets; 36263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey addLong(this.operations, i, fracOperations); operations -= fracOperations; 363a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 364a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey duration -= overlap; 36575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 36663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 36763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey totalBytes += entry.rxBytes + entry.txBytes; 36875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 36975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 37075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 37119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey * Record an entire {@link NetworkStatsHistory} into this history. Usually 37219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey * for combining together stats for external reporting. 37319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey */ 37419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey public void recordEntireHistory(NetworkStatsHistory input) { 37570c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey recordHistory(input, Long.MIN_VALUE, Long.MAX_VALUE); 37670c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey } 37770c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey 37870c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey /** 37970c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * Record given {@link NetworkStatsHistory} into this history, copying only 38070c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * buckets that atomically occur in the inclusive time range. Doesn't 38170c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey * interpolate across partial buckets. 38270c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey */ 38370c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey public void recordHistory(NetworkStatsHistory input, long start, long end) { 384a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final NetworkStats.Entry entry = new NetworkStats.Entry( 385b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); 38619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey for (int i = 0; i < input.bucketCount; i++) { 38770c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey final long bucketStart = input.bucketStart[i]; 38870c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey final long bucketEnd = bucketStart + input.bucketDuration; 38970c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey 39070c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey // skip when bucket is outside requested range 39170c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey if (bucketStart < start || bucketEnd > end) continue; 392a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 39363d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxBytes = getLong(input.rxBytes, i, 0L); 39463d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxPackets = getLong(input.rxPackets, i, 0L); 39563d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txBytes = getLong(input.txBytes, i, 0L); 39663d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txPackets = getLong(input.txPackets, i, 0L); 39763d27a9233fed934340231f438493746084a681dJeff Sharkey entry.operations = getLong(input.operations, i, 0L); 398a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 39970c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey recordData(bucketStart, bucketEnd, entry); 40019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 40119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 40219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 40319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey /** 40475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Ensure that buckets exist for given time range, creating as needed. 40575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 40675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private void ensureBuckets(long start, long end) { 40775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // normalize incoming range to bucket boundaries 40875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey start -= start % bucketDuration; 40975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey end += (bucketDuration - (end % bucketDuration)) % bucketDuration; 41075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 41175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (long now = start; now < end; now += bucketDuration) { 41275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // try finding existing bucket 41375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int index = Arrays.binarySearch(bucketStart, 0, bucketCount, now); 41475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (index < 0) { 41575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket missing, create and insert 41675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey insertBucket(~index, now); 41775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 41875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 41975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 42075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 42175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 42275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Insert new bucket at requested index and starting time. 42375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 42475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private void insertBucket(int index, long start) { 42575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create more buckets when needed 4264a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey if (bucketCount >= bucketStart.length) { 4274a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey final int newLength = Math.max(bucketStart.length, 10) * 3 / 2; 42875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = Arrays.copyOf(bucketStart, newLength); 429558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey if (activeTime != null) activeTime = Arrays.copyOf(activeTime, newLength); 43063d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength); 43163d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength); 43263d27a9233fed934340231f438493746084a681dJeff Sharkey if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength); 43363d27a9233fed934340231f438493746084a681dJeff Sharkey if (txPackets != null) txPackets = Arrays.copyOf(txPackets, newLength); 43463d27a9233fed934340231f438493746084a681dJeff Sharkey if (operations != null) operations = Arrays.copyOf(operations, newLength); 43575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 43675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 43775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create gap when inserting bucket in middle 43875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (index < bucketCount) { 43975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int dstPos = index + 1; 44075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int length = bucketCount - index; 44175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 44275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey System.arraycopy(bucketStart, index, bucketStart, dstPos, length); 443558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey if (activeTime != null) System.arraycopy(activeTime, index, activeTime, dstPos, length); 44463d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length); 44563d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length); 44663d27a9233fed934340231f438493746084a681dJeff Sharkey if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length); 44763d27a9233fed934340231f438493746084a681dJeff Sharkey if (txPackets != null) System.arraycopy(txPackets, index, txPackets, dstPos, length); 44863d27a9233fed934340231f438493746084a681dJeff Sharkey if (operations != null) System.arraycopy(operations, index, operations, dstPos, length); 44975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 45075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 45175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart[index] = start; 452558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey setLong(activeTime, index, 0L); 45363d27a9233fed934340231f438493746084a681dJeff Sharkey setLong(rxBytes, index, 0L); 45463d27a9233fed934340231f438493746084a681dJeff Sharkey setLong(rxPackets, index, 0L); 45563d27a9233fed934340231f438493746084a681dJeff Sharkey setLong(txBytes, index, 0L); 45663d27a9233fed934340231f438493746084a681dJeff Sharkey setLong(txPackets, index, 0L); 45763d27a9233fed934340231f438493746084a681dJeff Sharkey setLong(operations, index, 0L); 45875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount++; 45975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 46075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 46175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 46275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Remove buckets older than requested cutoff. 46375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 46463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey @Deprecated 46575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void removeBucketsBefore(long cutoff) { 46675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey int i; 46775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (i = 0; i < bucketCount; i++) { 46875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curStart = bucketStart[i]; 46975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curEnd = curStart + bucketDuration; 47075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 47175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // cutoff happens before or during this bucket; everything before 47275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // this bucket should be removed. 47375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curEnd > cutoff) break; 47475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 47575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 47675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (i > 0) { 47775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int length = bucketStart.length; 47875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = Arrays.copyOfRange(bucketStart, i, length); 479558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey if (activeTime != null) activeTime = Arrays.copyOfRange(activeTime, i, length); 48063d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length); 48163d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length); 48263d27a9233fed934340231f438493746084a681dJeff Sharkey if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length); 48363d27a9233fed934340231f438493746084a681dJeff Sharkey if (txPackets != null) txPackets = Arrays.copyOfRange(txPackets, i, length); 48463d27a9233fed934340231f438493746084a681dJeff Sharkey if (operations != null) operations = Arrays.copyOfRange(operations, i, length); 48575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount -= i; 48663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 48763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // TODO: subtract removed values from totalBytes 48875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 48975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 49075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 49161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey /** 49219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey * Return interpolated data usage across the requested range. Interpolates 49319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey * across buckets, so values may be rounded slightly. 49419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey */ 495434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey public Entry getValues(long start, long end, Entry recycle) { 496434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return getValues(start, end, Long.MAX_VALUE, recycle); 497434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } 498434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey 499434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey /** 500434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey * Return interpolated data usage across the requested range. Interpolates 501434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey * across buckets, so values may be rounded slightly. 502434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey */ 503434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey public Entry getValues(long start, long end, long now, Entry recycle) { 504434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey final Entry entry = recycle != null ? recycle : new Entry(); 505434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey entry.bucketDuration = end - start; 506558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey entry.bucketStart = start; 507558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey entry.activeTime = activeTime != null ? 0 : UNKNOWN; 50863d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxBytes = rxBytes != null ? 0 : UNKNOWN; 50963d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxPackets = rxPackets != null ? 0 : UNKNOWN; 51063d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txBytes = txBytes != null ? 0 : UNKNOWN; 51163d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txPackets = txPackets != null ? 0 : UNKNOWN; 51263d27a9233fed934340231f438493746084a681dJeff Sharkey entry.operations = operations != null ? 0 : UNKNOWN; 51319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 51469b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey final int startIndex = getIndexAfter(end); 51569b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey for (int i = startIndex; i >= 0; i--) { 51619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long curStart = bucketStart[i]; 51719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long curEnd = curStart + bucketDuration; 51819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 51934c73acf88c8190b8cd51d8b8f2b9c22aa7f7941Jeff Sharkey // bucket is older than request; we're finished 52034c73acf88c8190b8cd51d8b8f2b9c22aa7f7941Jeff Sharkey if (curEnd <= start) break; 52134c73acf88c8190b8cd51d8b8f2b9c22aa7f7941Jeff Sharkey // bucket is newer than request; keep looking 52234c73acf88c8190b8cd51d8b8f2b9c22aa7f7941Jeff Sharkey if (curStart >= end) continue; 52319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 524434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey // include full value for active buckets, otherwise only fractional 525434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey final boolean activeBucket = curStart < now && curEnd > now; 52669b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey final long overlap; 52769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey if (activeBucket) { 52869b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey overlap = bucketDuration; 52969b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } else { 53069b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey final long overlapEnd = curEnd < end ? curEnd : end; 53169b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey final long overlapStart = curStart > start ? curStart : start; 53269b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey overlap = overlapEnd - overlapStart; 53369b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } 534a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey if (overlap <= 0) continue; 535a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 536a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey // integer math each time is faster than floating point 537558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketDuration; 53863d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration; 53963d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration; 54063d27a9233fed934340231f438493746084a681dJeff Sharkey if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration; 54163d27a9233fed934340231f438493746084a681dJeff Sharkey if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketDuration; 54263d27a9233fed934340231f438493746084a681dJeff Sharkey if (operations != null) entry.operations += operations[i] * overlap / bucketDuration; 54319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 544434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return entry; 54519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 54619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 54719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey /** 54861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey * @deprecated only for temporary testing 54961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey */ 55061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey @Deprecated 551293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey public void generateRandom(long start, long end, long bytes) { 552293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final Random r = new Random(); 553293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey 554293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final float fractionRx = r.nextFloat(); 555293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long rxBytes = (long) (bytes * fractionRx); 556293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long txBytes = (long) (bytes * (1 - fractionRx)); 557293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey 558293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long rxPackets = rxBytes / 1024; 559293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long txPackets = txBytes / 1024; 560293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long operations = rxBytes / 2048; 561293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey 562293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey generateRandom(start, end, rxBytes, rxPackets, txBytes, txPackets, operations, r); 563293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey } 564293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey 565293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey /** 566293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey * @deprecated only for temporary testing 567293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey */ 568293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey @Deprecated 56963d27a9233fed934340231f438493746084a681dJeff Sharkey public void generateRandom(long start, long end, long rxBytes, long rxPackets, long txBytes, 570293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey long txPackets, long operations, Random r) { 57161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey ensureBuckets(start, end); 57261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 573a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final NetworkStats.Entry entry = new NetworkStats.Entry( 574b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); 57504cd0e47dbc1e9769ac6f258c923d5b17fa57986Jeff Sharkey while (rxBytes > 1024 || rxPackets > 128 || txBytes > 1024 || txPackets > 128 57604cd0e47dbc1e9769ac6f258c923d5b17fa57986Jeff Sharkey || operations > 32) { 57761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey final long curStart = randomLong(r, start, end); 578293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long curEnd = curStart + randomLong(r, 0, (end - curStart) / 2); 57963d27a9233fed934340231f438493746084a681dJeff Sharkey 58063d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxBytes = randomLong(r, 0, rxBytes); 58163d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxPackets = randomLong(r, 0, rxPackets); 58263d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txBytes = randomLong(r, 0, txBytes); 58363d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txPackets = randomLong(r, 0, txPackets); 58463d27a9233fed934340231f438493746084a681dJeff Sharkey entry.operations = randomLong(r, 0, operations); 58563d27a9233fed934340231f438493746084a681dJeff Sharkey 58663d27a9233fed934340231f438493746084a681dJeff Sharkey rxBytes -= entry.rxBytes; 58763d27a9233fed934340231f438493746084a681dJeff Sharkey rxPackets -= entry.rxPackets; 58863d27a9233fed934340231f438493746084a681dJeff Sharkey txBytes -= entry.txBytes; 58963d27a9233fed934340231f438493746084a681dJeff Sharkey txPackets -= entry.txPackets; 59063d27a9233fed934340231f438493746084a681dJeff Sharkey operations -= entry.operations; 591f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 592f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey recordData(curStart, curEnd, entry); 59361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 59461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 59561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 596293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey public static long randomLong(Random r, long start, long end) { 59761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey return (long) (start + (r.nextFloat() * (end - start))); 59861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 59961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 60055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey /** 60155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey * Quickly determine if this history intersects with given window. 60255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey */ 60355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey public boolean intersects(long start, long end) { 60455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final long dataStart = getStart(); 60555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey final long dataEnd = getEnd(); 60655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (start >= dataStart && start <= dataEnd) return true; 60755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (end >= dataStart && end <= dataEnd) return true; 60855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (dataStart >= start && dataStart <= end) return true; 60955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (dataEnd >= start && dataEnd <= end) return true; 61055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey return false; 61155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 61255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 61363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void dump(IndentingPrintWriter pw, boolean fullHistory) { 61455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print("NetworkStatsHistory: bucketDuration="); 61555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.println(bucketDuration / SECOND_IN_MILLIS); 61663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.increaseIndent(); 617350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 618350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey final int start = fullHistory ? 0 : Math.max(0, bucketCount - 32); 619350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (start > 0) { 62063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print("(omitting "); pw.print(start); pw.println(" buckets)"); 621350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 622350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 623350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey for (int i = start; i < bucketCount; i++) { 62455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print("st="); pw.print(bucketStart[i] / SECOND_IN_MILLIS); 62555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (rxBytes != null) { pw.print(" rb="); pw.print(rxBytes[i]); } 62655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (rxPackets != null) { pw.print(" rp="); pw.print(rxPackets[i]); } 62755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (txBytes != null) { pw.print(" tb="); pw.print(txBytes[i]); } 62855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (txPackets != null) { pw.print(" tp="); pw.print(txPackets[i]); } 62955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (operations != null) { pw.print(" op="); pw.print(operations[i]); } 63063d27a9233fed934340231f438493746084a681dJeff Sharkey pw.println(); 63175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 63263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 63363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.decreaseIndent(); 63475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 63575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 63655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey public void dumpCheckin(PrintWriter pw) { 63755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print("d,"); 63855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print(bucketDuration / SECOND_IN_MILLIS); 63955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.println(); 64055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 64155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey for (int i = 0; i < bucketCount; i++) { 64255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print("b,"); 64355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.print(bucketStart[i] / SECOND_IN_MILLIS); pw.print(','); 64455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (rxBytes != null) { pw.print(rxBytes[i]); } else { pw.print("*"); } pw.print(','); 64555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (rxPackets != null) { pw.print(rxPackets[i]); } else { pw.print("*"); } pw.print(','); 64655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (txBytes != null) { pw.print(txBytes[i]); } else { pw.print("*"); } pw.print(','); 64755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (txPackets != null) { pw.print(txPackets[i]); } else { pw.print("*"); } pw.print(','); 64855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey if (operations != null) { pw.print(operations[i]); } else { pw.print("*"); } 64955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey pw.println(); 65055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 65155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey } 65255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey 653da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki public void writeToProto(ProtoOutputStream proto, long tag) { 654da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki final long start = proto.start(tag); 655da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki 656da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS, bucketDuration); 657da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki 658da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki for (int i = 0; i < bucketCount; i++) { 659da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS); 660da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki 661da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS, bucketStart[i]); 662da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki writeToProto(proto, NetworkStatsHistoryBucketProto.RX_BYTES, rxBytes, i); 663da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki writeToProto(proto, NetworkStatsHistoryBucketProto.RX_PACKETS, rxPackets, i); 664da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki writeToProto(proto, NetworkStatsHistoryBucketProto.TX_BYTES, txBytes, i); 665da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki writeToProto(proto, NetworkStatsHistoryBucketProto.TX_PACKETS, txPackets, i); 666da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki writeToProto(proto, NetworkStatsHistoryBucketProto.OPERATIONS, operations, i); 667da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki 668da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki proto.end(startBucket); 669da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki } 670da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki 671da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki proto.end(start); 672da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki } 673da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki 674da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki private static void writeToProto(ProtoOutputStream proto, long tag, long[] array, int index) { 675da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki if (array != null) { 676da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki proto.write(tag, array[index]); 677da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki } 678da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki } 679da65a52f87ca1a31c9e01e99756e38d37d7e7202Makoto Onuki 68075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey @Override 68175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public String toString() { 68275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final CharArrayWriter writer = new CharArrayWriter(); 68363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey dump(new IndentingPrintWriter(writer, " "), false); 68475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return writer.toString(); 68575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 68675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 68775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() { 688bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 68975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory createFromParcel(Parcel in) { 69075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return new NetworkStatsHistory(in); 69175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 69275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 693bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 69475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory[] newArray(int size) { 69575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return new NetworkStatsHistory[size]; 69675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 69775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey }; 69875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 69963d27a9233fed934340231f438493746084a681dJeff Sharkey private static long getLong(long[] array, int i, long value) { 70063d27a9233fed934340231f438493746084a681dJeff Sharkey return array != null ? array[i] : value; 70163d27a9233fed934340231f438493746084a681dJeff Sharkey } 70263d27a9233fed934340231f438493746084a681dJeff Sharkey 70363d27a9233fed934340231f438493746084a681dJeff Sharkey private static void setLong(long[] array, int i, long value) { 70463d27a9233fed934340231f438493746084a681dJeff Sharkey if (array != null) array[i] = value; 70563d27a9233fed934340231f438493746084a681dJeff Sharkey } 70663d27a9233fed934340231f438493746084a681dJeff Sharkey 70763d27a9233fed934340231f438493746084a681dJeff Sharkey private static void addLong(long[] array, int i, long value) { 70863d27a9233fed934340231f438493746084a681dJeff Sharkey if (array != null) array[i] += value; 70963d27a9233fed934340231f438493746084a681dJeff Sharkey } 71063d27a9233fed934340231f438493746084a681dJeff Sharkey 71163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public int estimateResizeBuckets(long newBucketDuration) { 71263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return (int) (size() * getBucketDuration() / newBucketDuration); 71363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 71463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 715a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey /** 716a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * Utility methods for interacting with {@link DataInputStream} and 717a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * {@link DataOutputStream}, mostly dealing with writing partial arrays. 718a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey */ 719a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public static class DataStreamUtils { 72063d27a9233fed934340231f438493746084a681dJeff Sharkey @Deprecated 72163d27a9233fed934340231f438493746084a681dJeff Sharkey public static long[] readFullLongArray(DataInputStream in) throws IOException { 722a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final int size = in.readInt(); 7231f99a483e410811473b12d8efedd79c738df7af3Jeff Sharkey if (size < 0) throw new ProtocolException("negative array size"); 724a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final long[] values = new long[size]; 725a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey for (int i = 0; i < values.length; i++) { 726a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey values[i] = in.readLong(); 727a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 728a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey return values; 729a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 730a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 73163d27a9233fed934340231f438493746084a681dJeff Sharkey /** 73263d27a9233fed934340231f438493746084a681dJeff Sharkey * Read variable-length {@link Long} using protobuf-style approach. 73363d27a9233fed934340231f438493746084a681dJeff Sharkey */ 73463d27a9233fed934340231f438493746084a681dJeff Sharkey public static long readVarLong(DataInputStream in) throws IOException { 73563d27a9233fed934340231f438493746084a681dJeff Sharkey int shift = 0; 73663d27a9233fed934340231f438493746084a681dJeff Sharkey long result = 0; 73763d27a9233fed934340231f438493746084a681dJeff Sharkey while (shift < 64) { 73863d27a9233fed934340231f438493746084a681dJeff Sharkey byte b = in.readByte(); 73963d27a9233fed934340231f438493746084a681dJeff Sharkey result |= (long) (b & 0x7F) << shift; 74063d27a9233fed934340231f438493746084a681dJeff Sharkey if ((b & 0x80) == 0) 74163d27a9233fed934340231f438493746084a681dJeff Sharkey return result; 74263d27a9233fed934340231f438493746084a681dJeff Sharkey shift += 7; 74363d27a9233fed934340231f438493746084a681dJeff Sharkey } 74463d27a9233fed934340231f438493746084a681dJeff Sharkey throw new ProtocolException("malformed long"); 74563d27a9233fed934340231f438493746084a681dJeff Sharkey } 74663d27a9233fed934340231f438493746084a681dJeff Sharkey 74763d27a9233fed934340231f438493746084a681dJeff Sharkey /** 74863d27a9233fed934340231f438493746084a681dJeff Sharkey * Write variable-length {@link Long} using protobuf-style approach. 74963d27a9233fed934340231f438493746084a681dJeff Sharkey */ 75063d27a9233fed934340231f438493746084a681dJeff Sharkey public static void writeVarLong(DataOutputStream out, long value) throws IOException { 75163d27a9233fed934340231f438493746084a681dJeff Sharkey while (true) { 75263d27a9233fed934340231f438493746084a681dJeff Sharkey if ((value & ~0x7FL) == 0) { 75363d27a9233fed934340231f438493746084a681dJeff Sharkey out.writeByte((int) value); 75463d27a9233fed934340231f438493746084a681dJeff Sharkey return; 75563d27a9233fed934340231f438493746084a681dJeff Sharkey } else { 75663d27a9233fed934340231f438493746084a681dJeff Sharkey out.writeByte(((int) value & 0x7F) | 0x80); 75763d27a9233fed934340231f438493746084a681dJeff Sharkey value >>>= 7; 75863d27a9233fed934340231f438493746084a681dJeff Sharkey } 75963d27a9233fed934340231f438493746084a681dJeff Sharkey } 76063d27a9233fed934340231f438493746084a681dJeff Sharkey } 76163d27a9233fed934340231f438493746084a681dJeff Sharkey 76263d27a9233fed934340231f438493746084a681dJeff Sharkey public static long[] readVarLongArray(DataInputStream in) throws IOException { 76363d27a9233fed934340231f438493746084a681dJeff Sharkey final int size = in.readInt(); 76463d27a9233fed934340231f438493746084a681dJeff Sharkey if (size == -1) return null; 7651f99a483e410811473b12d8efedd79c738df7af3Jeff Sharkey if (size < 0) throw new ProtocolException("negative array size"); 76663d27a9233fed934340231f438493746084a681dJeff Sharkey final long[] values = new long[size]; 76763d27a9233fed934340231f438493746084a681dJeff Sharkey for (int i = 0; i < values.length; i++) { 76863d27a9233fed934340231f438493746084a681dJeff Sharkey values[i] = readVarLong(in); 76963d27a9233fed934340231f438493746084a681dJeff Sharkey } 77063d27a9233fed934340231f438493746084a681dJeff Sharkey return values; 77163d27a9233fed934340231f438493746084a681dJeff Sharkey } 77263d27a9233fed934340231f438493746084a681dJeff Sharkey 77363d27a9233fed934340231f438493746084a681dJeff Sharkey public static void writeVarLongArray(DataOutputStream out, long[] values, int size) 774a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey throws IOException { 77563d27a9233fed934340231f438493746084a681dJeff Sharkey if (values == null) { 77663d27a9233fed934340231f438493746084a681dJeff Sharkey out.writeInt(-1); 77763d27a9233fed934340231f438493746084a681dJeff Sharkey return; 77863d27a9233fed934340231f438493746084a681dJeff Sharkey } 779a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey if (size > values.length) { 780a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey throw new IllegalArgumentException("size larger than length"); 781a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 782a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey out.writeInt(size); 783a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey for (int i = 0; i < size; i++) { 78463d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLong(out, values[i]); 785a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 78675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 78775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 78875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 789a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey /** 790a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * Utility methods for interacting with {@link Parcel} structures, mostly 791a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * dealing with writing partial arrays. 792a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey */ 793a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public static class ParcelUtils { 794a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public static long[] readLongArray(Parcel in) { 795a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final int size = in.readInt(); 79663d27a9233fed934340231f438493746084a681dJeff Sharkey if (size == -1) return null; 797a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final long[] values = new long[size]; 798a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey for (int i = 0; i < values.length; i++) { 799a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey values[i] = in.readLong(); 800a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 801a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey return values; 80275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 80375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 804a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public static void writeLongArray(Parcel out, long[] values, int size) { 80563d27a9233fed934340231f438493746084a681dJeff Sharkey if (values == null) { 80663d27a9233fed934340231f438493746084a681dJeff Sharkey out.writeInt(-1); 80763d27a9233fed934340231f438493746084a681dJeff Sharkey return; 808a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 809a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey if (size > values.length) { 810a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey throw new IllegalArgumentException("size larger than length"); 811a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 812a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey out.writeInt(size); 813a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey for (int i = 0; i < size; i++) { 81463d27a9233fed934340231f438493746084a681dJeff Sharkey out.writeLong(values[i]); 815a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 81675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 81775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 81875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 81975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey} 820