NetworkStatsHistory.java revision bfdd680ab44da173a4a39fcd6feccdebb9d1f855
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; 2963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static com.android.internal.util.ArrayUtils.total; 30a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 3175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Parcel; 3275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Parcelable; 3369b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkeyimport android.util.MathUtils; 3475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 3563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 3663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 3775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.CharArrayWriter; 3875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.DataInputStream; 3975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.DataOutputStream; 4075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.IOException; 4161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.net.ProtocolException; 4275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.Arrays; 4361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.util.Random; 4475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 4575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/** 4675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collection of historical network statistics, recorded into equally-sized 4775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * "buckets" in time. Internally it stores data in {@code long} series for more 4875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * efficient persistence. 4975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * <p> 5075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Each bucket is defined by a {@link #bucketStart} timestamp, and lasts for 5175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * {@link #bucketDuration}. Internally assumes that {@link #bucketStart} is 5275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * sorted at all times. 5375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 5475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * @hide 5575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 5675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypublic class NetworkStatsHistory implements Parcelable { 571b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey private static final int VERSION_INIT = 1; 5863d27a9233fed934340231f438493746084a681dJeff Sharkey private static final int VERSION_ADD_PACKETS = 2; 59558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey private static final int VERSION_ADD_ACTIVE = 3; 6075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 61558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_ACTIVE_TIME = 0x01; 62558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_RX_BYTES = 0x02; 63558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_RX_PACKETS = 0x04; 64558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_TX_BYTES = 0x08; 65558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_TX_PACKETS = 0x10; 66558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public static final int FIELD_OPERATIONS = 0x20; 67d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 6863d27a9233fed934340231f438493746084a681dJeff Sharkey public static final int FIELD_ALL = 0xFFFFFFFF; 6963d27a9233fed934340231f438493746084a681dJeff Sharkey 7063d27a9233fed934340231f438493746084a681dJeff Sharkey private long bucketDuration; 71d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private int bucketCount; 72d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private long[] bucketStart; 73558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey private long[] activeTime; 74d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private long[] rxBytes; 75a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey private long[] rxPackets; 76d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private long[] txBytes; 77a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey private long[] txPackets; 7863d27a9233fed934340231f438493746084a681dJeff Sharkey private long[] operations; 7963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey private long totalBytes; 80d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 81d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public static class Entry { 8263d27a9233fed934340231f438493746084a681dJeff Sharkey public static final long UNKNOWN = -1; 8363d27a9233fed934340231f438493746084a681dJeff Sharkey 84d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public long bucketDuration; 85558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public long bucketStart; 86558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey public long activeTime; 87d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public long rxBytes; 88a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public long rxPackets; 89d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public long txBytes; 90a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public long txPackets; 9163d27a9233fed934340231f438493746084a681dJeff Sharkey public long operations; 92d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 9375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 94d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public NetworkStatsHistory(long bucketDuration) { 9563d27a9233fed934340231f438493746084a681dJeff Sharkey this(bucketDuration, 10, FIELD_ALL); 964a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey } 974a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey 984a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey public NetworkStatsHistory(long bucketDuration, int initialSize) { 9963d27a9233fed934340231f438493746084a681dJeff Sharkey this(bucketDuration, initialSize, FIELD_ALL); 10063d27a9233fed934340231f438493746084a681dJeff Sharkey } 10163d27a9233fed934340231f438493746084a681dJeff Sharkey 10263d27a9233fed934340231f438493746084a681dJeff Sharkey public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) { 10375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey this.bucketDuration = bucketDuration; 1044a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey bucketStart = new long[initialSize]; 105558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey if ((fields & FIELD_ACTIVE_TIME) != 0) activeTime = new long[initialSize]; 10663d27a9233fed934340231f438493746084a681dJeff Sharkey if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize]; 10763d27a9233fed934340231f438493746084a681dJeff Sharkey if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize]; 10863d27a9233fed934340231f438493746084a681dJeff Sharkey if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize]; 10963d27a9233fed934340231f438493746084a681dJeff Sharkey if ((fields & FIELD_TX_PACKETS) != 0) txPackets = new long[initialSize]; 11063d27a9233fed934340231f438493746084a681dJeff Sharkey if ((fields & FIELD_OPERATIONS) != 0) operations = new long[initialSize]; 1114a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey bucketCount = 0; 11263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey totalBytes = 0; 11363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 11463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 11563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public NetworkStatsHistory(NetworkStatsHistory existing, long bucketDuration) { 11663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey this(bucketDuration, existing.estimateResizeBuckets(bucketDuration)); 11763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey recordEntireHistory(existing); 11875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 11975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 12075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory(Parcel in) { 12175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketDuration = in.readLong(); 12275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = readLongArray(in); 123558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey activeTime = readLongArray(in); 124a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey rxBytes = readLongArray(in); 125a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey rxPackets = readLongArray(in); 126a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey txBytes = readLongArray(in); 127a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey txPackets = readLongArray(in); 12863d27a9233fed934340231f438493746084a681dJeff Sharkey operations = readLongArray(in); 12975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount = bucketStart.length; 13063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey totalBytes = in.readLong(); 13175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 13275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 133bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 13475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void writeToParcel(Parcel out, int flags) { 13575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(bucketDuration); 13675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, bucketStart, bucketCount); 137558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey writeLongArray(out, activeTime, bucketCount); 138d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey writeLongArray(out, rxBytes, bucketCount); 139a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey writeLongArray(out, rxPackets, bucketCount); 140d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey writeLongArray(out, txBytes, bucketCount); 141a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey writeLongArray(out, txPackets, bucketCount); 14263d27a9233fed934340231f438493746084a681dJeff Sharkey writeLongArray(out, operations, bucketCount); 14363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey out.writeLong(totalBytes); 14475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 14575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 14675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory(DataInputStream in) throws IOException { 14775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int version = in.readInt(); 14861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey switch (version) { 1491b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey case VERSION_INIT: { 15061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey bucketDuration = in.readLong(); 15163d27a9233fed934340231f438493746084a681dJeff Sharkey bucketStart = readFullLongArray(in); 15263d27a9233fed934340231f438493746084a681dJeff Sharkey rxBytes = readFullLongArray(in); 153a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey rxPackets = new long[bucketStart.length]; 15463d27a9233fed934340231f438493746084a681dJeff Sharkey txBytes = readFullLongArray(in); 155a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey txPackets = new long[bucketStart.length]; 15663d27a9233fed934340231f438493746084a681dJeff Sharkey operations = new long[bucketStart.length]; 15763d27a9233fed934340231f438493746084a681dJeff Sharkey bucketCount = bucketStart.length; 15863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey totalBytes = total(rxBytes) + total(txBytes); 15963d27a9233fed934340231f438493746084a681dJeff Sharkey break; 16063d27a9233fed934340231f438493746084a681dJeff Sharkey } 161558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey case VERSION_ADD_PACKETS: 162558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey case VERSION_ADD_ACTIVE: { 16363d27a9233fed934340231f438493746084a681dJeff Sharkey bucketDuration = in.readLong(); 16463d27a9233fed934340231f438493746084a681dJeff Sharkey bucketStart = readVarLongArray(in); 165558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey activeTime = (version >= VERSION_ADD_ACTIVE) ? readVarLongArray(in) 166558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey : new long[bucketStart.length]; 16763d27a9233fed934340231f438493746084a681dJeff Sharkey rxBytes = readVarLongArray(in); 16863d27a9233fed934340231f438493746084a681dJeff Sharkey rxPackets = readVarLongArray(in); 16963d27a9233fed934340231f438493746084a681dJeff Sharkey txBytes = readVarLongArray(in); 17063d27a9233fed934340231f438493746084a681dJeff Sharkey txPackets = readVarLongArray(in); 17163d27a9233fed934340231f438493746084a681dJeff Sharkey operations = readVarLongArray(in); 17261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey bucketCount = bucketStart.length; 17363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey totalBytes = total(rxBytes) + total(txBytes); 17461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey break; 17561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 17661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey default: { 17761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey throw new ProtocolException("unexpected version: " + version); 17861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 17961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 18075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 18175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 18275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void writeToStream(DataOutputStream out) throws IOException { 183558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey out.writeInt(VERSION_ADD_ACTIVE); 18475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(bucketDuration); 18563d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, bucketStart, bucketCount); 186558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey writeVarLongArray(out, activeTime, bucketCount); 18763d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, rxBytes, bucketCount); 18863d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, rxPackets, bucketCount); 18963d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, txBytes, bucketCount); 19063d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, txPackets, bucketCount); 19163d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLongArray(out, operations, bucketCount); 19275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 19375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 194bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 19575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public int describeContents() { 19675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return 0; 19775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 19875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 199d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public int size() { 200d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey return bucketCount; 201d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 202d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 203d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public long getBucketDuration() { 204d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey return bucketDuration; 205d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 206d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 207434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey public long getStart() { 208434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey if (bucketCount > 0) { 209434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return bucketStart[0]; 210434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } else { 211434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return Long.MAX_VALUE; 212434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } 213434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } 214434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey 215434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey public long getEnd() { 216434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey if (bucketCount > 0) { 217434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return bucketStart[bucketCount - 1] + bucketDuration; 218434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } else { 219434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return Long.MIN_VALUE; 220434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } 221434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } 222434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey 223d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey /** 22463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey * Return total bytes represented by this history. 22563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey */ 22663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public long getTotalBytes() { 22763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return totalBytes; 22863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 22963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 23063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey /** 23169b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey * Return index of bucket that contains or is immediately before the 23269b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey * requested time. 23369b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey */ 23469b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey public int getIndexBefore(long time) { 23569b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); 23669b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey if (index < 0) { 23769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey index = (~index) - 1; 23869b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } else { 23969b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey index -= 1; 24069b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } 24169b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey return MathUtils.constrain(index, 0, bucketCount - 1); 24269b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } 24369b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey 24469b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey /** 24569b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey * Return index of bucket that contains or is immediately after the 24669b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey * requested time. 24769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey */ 24869b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey public int getIndexAfter(long time) { 24969b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); 25069b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey if (index < 0) { 25169b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey index = ~index; 25269b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } else { 25369b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey index += 1; 25469b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } 25569b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey return MathUtils.constrain(index, 0, bucketCount - 1); 25669b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } 25769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey 25869b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey /** 259d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey * Return specific stats entry. 260d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey */ 261d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey public Entry getValues(int i, Entry recycle) { 262d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey final Entry entry = recycle != null ? recycle : new Entry(); 263d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry.bucketStart = bucketStart[i]; 264d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry.bucketDuration = bucketDuration; 265558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey entry.activeTime = getLong(activeTime, i, UNKNOWN); 26663d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxBytes = getLong(rxBytes, i, UNKNOWN); 26763d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxPackets = getLong(rxPackets, i, UNKNOWN); 26863d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txBytes = getLong(txBytes, i, UNKNOWN); 26963d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txPackets = getLong(txPackets, i, UNKNOWN); 27063d27a9233fed934340231f438493746084a681dJeff Sharkey entry.operations = getLong(operations, i, UNKNOWN); 271d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey return entry; 272d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey } 273d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey 27475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 27575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Record that data traffic occurred in the given time range. Will 27675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * distribute across internal buckets, creating new buckets as needed. 27775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 278a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey @Deprecated 279a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public void recordData(long start, long end, long rxBytes, long txBytes) { 280b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey recordData(start, end, new NetworkStats.Entry( 281b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0L)); 282a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 283a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 284a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey /** 285a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * Record that data traffic occurred in the given time range. Will 286a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * distribute across internal buckets, creating new buckets as needed. 287a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey */ 288a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public void recordData(long start, long end, NetworkStats.Entry entry) { 28963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long rxBytes = entry.rxBytes; 29063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long rxPackets = entry.rxPackets; 29163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long txBytes = entry.txBytes; 29263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long txPackets = entry.txPackets; 29363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey long operations = entry.operations; 29463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 29563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (entry.isNegative()) { 296a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey throw new IllegalArgumentException("tried recording negative data"); 2971b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 29863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey if (entry.isEmpty()) { 299367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey return; 300367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey } 3011b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 30275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create any buckets needed by this range 30375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey ensureBuckets(start, end); 30475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 30575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // distribute data usage into buckets 306a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey long duration = end - start; 30769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey final int startIndex = getIndexAfter(end); 30869b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey for (int i = startIndex; i >= 0; i--) { 30975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curStart = bucketStart[i]; 31075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curEnd = curStart + bucketDuration; 31175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 31275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket is older than record; we're finished 31375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curEnd < start) break; 31475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket is newer than record; keep looking 31575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curStart > end) continue; 31675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 31775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); 318a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey if (overlap <= 0) continue; 319a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 320a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey // integer math each time is faster than floating point 32163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long fracRxBytes = rxBytes * overlap / duration; 32263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long fracRxPackets = rxPackets * overlap / duration; 32363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long fracTxBytes = txBytes * overlap / duration; 32463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long fracTxPackets = txPackets * overlap / duration; 32563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey final long fracOperations = operations * overlap / duration; 326a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 327558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey addLong(activeTime, i, overlap); 32863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey addLong(this.rxBytes, i, fracRxBytes); rxBytes -= fracRxBytes; 32963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey addLong(this.rxPackets, i, fracRxPackets); rxPackets -= fracRxPackets; 33063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey addLong(this.txBytes, i, fracTxBytes); txBytes -= fracTxBytes; 33163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey addLong(this.txPackets, i, fracTxPackets); txPackets -= fracTxPackets; 33263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey addLong(this.operations, i, fracOperations); operations -= fracOperations; 333a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 334a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey duration -= overlap; 33575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 33663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 33763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey totalBytes += entry.rxBytes + entry.txBytes; 33875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 33975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 34075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 34119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey * Record an entire {@link NetworkStatsHistory} into this history. Usually 34219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey * for combining together stats for external reporting. 34319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey */ 34419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey public void recordEntireHistory(NetworkStatsHistory input) { 345a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final NetworkStats.Entry entry = new NetworkStats.Entry( 346b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); 34719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey for (int i = 0; i < input.bucketCount; i++) { 34819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long start = input.bucketStart[i]; 34919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long end = start + input.bucketDuration; 350a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 35163d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxBytes = getLong(input.rxBytes, i, 0L); 35263d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxPackets = getLong(input.rxPackets, i, 0L); 35363d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txBytes = getLong(input.txBytes, i, 0L); 35463d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txPackets = getLong(input.txPackets, i, 0L); 35563d27a9233fed934340231f438493746084a681dJeff Sharkey entry.operations = getLong(input.operations, i, 0L); 356a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 357a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey recordData(start, end, entry); 35819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 35919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 36019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 36119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey /** 36275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Ensure that buckets exist for given time range, creating as needed. 36375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 36475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private void ensureBuckets(long start, long end) { 36575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // normalize incoming range to bucket boundaries 36675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey start -= start % bucketDuration; 36775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey end += (bucketDuration - (end % bucketDuration)) % bucketDuration; 36875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 36975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (long now = start; now < end; now += bucketDuration) { 37075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // try finding existing bucket 37175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int index = Arrays.binarySearch(bucketStart, 0, bucketCount, now); 37275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (index < 0) { 37375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket missing, create and insert 37475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey insertBucket(~index, now); 37575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 37675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 37775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 37875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 37975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 38075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Insert new bucket at requested index and starting time. 38175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 38275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private void insertBucket(int index, long start) { 38375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create more buckets when needed 3844a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey if (bucketCount >= bucketStart.length) { 3854a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey final int newLength = Math.max(bucketStart.length, 10) * 3 / 2; 38675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = Arrays.copyOf(bucketStart, newLength); 387558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey if (activeTime != null) activeTime = Arrays.copyOf(activeTime, newLength); 38863d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength); 38963d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength); 39063d27a9233fed934340231f438493746084a681dJeff Sharkey if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength); 39163d27a9233fed934340231f438493746084a681dJeff Sharkey if (txPackets != null) txPackets = Arrays.copyOf(txPackets, newLength); 39263d27a9233fed934340231f438493746084a681dJeff Sharkey if (operations != null) operations = Arrays.copyOf(operations, newLength); 39375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 39475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 39575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create gap when inserting bucket in middle 39675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (index < bucketCount) { 39775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int dstPos = index + 1; 39875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int length = bucketCount - index; 39975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 40075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey System.arraycopy(bucketStart, index, bucketStart, dstPos, length); 401558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey if (activeTime != null) System.arraycopy(activeTime, index, activeTime, dstPos, length); 40263d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length); 40363d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length); 40463d27a9233fed934340231f438493746084a681dJeff Sharkey if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length); 40563d27a9233fed934340231f438493746084a681dJeff Sharkey if (txPackets != null) System.arraycopy(txPackets, index, txPackets, dstPos, length); 40663d27a9233fed934340231f438493746084a681dJeff Sharkey if (operations != null) System.arraycopy(operations, index, operations, dstPos, length); 40775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 40875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 40975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart[index] = start; 410558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey setLong(activeTime, index, 0L); 41163d27a9233fed934340231f438493746084a681dJeff Sharkey setLong(rxBytes, index, 0L); 41263d27a9233fed934340231f438493746084a681dJeff Sharkey setLong(rxPackets, index, 0L); 41363d27a9233fed934340231f438493746084a681dJeff Sharkey setLong(txBytes, index, 0L); 41463d27a9233fed934340231f438493746084a681dJeff Sharkey setLong(txPackets, index, 0L); 41563d27a9233fed934340231f438493746084a681dJeff Sharkey setLong(operations, index, 0L); 41675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount++; 41775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 41875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 41975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 42075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Remove buckets older than requested cutoff. 42175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 42263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey @Deprecated 42375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void removeBucketsBefore(long cutoff) { 42475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey int i; 42575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (i = 0; i < bucketCount; i++) { 42675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curStart = bucketStart[i]; 42775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curEnd = curStart + bucketDuration; 42875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 42975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // cutoff happens before or during this bucket; everything before 43075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // this bucket should be removed. 43175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curEnd > cutoff) break; 43275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 43375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 43475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (i > 0) { 43575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int length = bucketStart.length; 43675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = Arrays.copyOfRange(bucketStart, i, length); 437558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey if (activeTime != null) activeTime = Arrays.copyOfRange(activeTime, i, length); 43863d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length); 43963d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length); 44063d27a9233fed934340231f438493746084a681dJeff Sharkey if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length); 44163d27a9233fed934340231f438493746084a681dJeff Sharkey if (txPackets != null) txPackets = Arrays.copyOfRange(txPackets, i, length); 44263d27a9233fed934340231f438493746084a681dJeff Sharkey if (operations != null) operations = Arrays.copyOfRange(operations, i, length); 44375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount -= i; 44463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 44563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey // TODO: subtract removed values from totalBytes 44675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 44775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 44875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 44961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey /** 45019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey * Return interpolated data usage across the requested range. Interpolates 45119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey * across buckets, so values may be rounded slightly. 45219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey */ 453434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey public Entry getValues(long start, long end, Entry recycle) { 454434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return getValues(start, end, Long.MAX_VALUE, recycle); 455434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey } 456434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey 457434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey /** 458434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey * Return interpolated data usage across the requested range. Interpolates 459434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey * across buckets, so values may be rounded slightly. 460434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey */ 461434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey public Entry getValues(long start, long end, long now, Entry recycle) { 462434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey final Entry entry = recycle != null ? recycle : new Entry(); 463434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey entry.bucketDuration = end - start; 464558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey entry.bucketStart = start; 465558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey entry.activeTime = activeTime != null ? 0 : UNKNOWN; 46663d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxBytes = rxBytes != null ? 0 : UNKNOWN; 46763d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxPackets = rxPackets != null ? 0 : UNKNOWN; 46863d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txBytes = txBytes != null ? 0 : UNKNOWN; 46963d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txPackets = txPackets != null ? 0 : UNKNOWN; 47063d27a9233fed934340231f438493746084a681dJeff Sharkey entry.operations = operations != null ? 0 : UNKNOWN; 47119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 47269b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey final int startIndex = getIndexAfter(end); 47369b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey for (int i = startIndex; i >= 0; i--) { 47419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long curStart = bucketStart[i]; 47519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long curEnd = curStart + bucketDuration; 47619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 47734c73acf88c8190b8cd51d8b8f2b9c22aa7f7941Jeff Sharkey // bucket is older than request; we're finished 47834c73acf88c8190b8cd51d8b8f2b9c22aa7f7941Jeff Sharkey if (curEnd <= start) break; 47934c73acf88c8190b8cd51d8b8f2b9c22aa7f7941Jeff Sharkey // bucket is newer than request; keep looking 48034c73acf88c8190b8cd51d8b8f2b9c22aa7f7941Jeff Sharkey if (curStart >= end) continue; 48119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 482434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey // include full value for active buckets, otherwise only fractional 483434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey final boolean activeBucket = curStart < now && curEnd > now; 48469b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey final long overlap; 48569b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey if (activeBucket) { 48669b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey overlap = bucketDuration; 48769b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } else { 48869b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey final long overlapEnd = curEnd < end ? curEnd : end; 48969b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey final long overlapStart = curStart > start ? curStart : start; 49069b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey overlap = overlapEnd - overlapStart; 49169b0f63af2e3babc2e9f048c4682032a0c17d9d0Jeff Sharkey } 492a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey if (overlap <= 0) continue; 493a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 494a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey // integer math each time is faster than floating point 495558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketDuration; 49663d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration; 49763d27a9233fed934340231f438493746084a681dJeff Sharkey if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration; 49863d27a9233fed934340231f438493746084a681dJeff Sharkey if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration; 49963d27a9233fed934340231f438493746084a681dJeff Sharkey if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketDuration; 50063d27a9233fed934340231f438493746084a681dJeff Sharkey if (operations != null) entry.operations += operations[i] * overlap / bucketDuration; 50119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 502434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey return entry; 50319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 50419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 50519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey /** 50661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey * @deprecated only for temporary testing 50761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey */ 50861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey @Deprecated 509293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey public void generateRandom(long start, long end, long bytes) { 510293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final Random r = new Random(); 511293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey 512293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final float fractionRx = r.nextFloat(); 513293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long rxBytes = (long) (bytes * fractionRx); 514293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long txBytes = (long) (bytes * (1 - fractionRx)); 515293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey 516293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long rxPackets = rxBytes / 1024; 517293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long txPackets = txBytes / 1024; 518293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long operations = rxBytes / 2048; 519293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey 520293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey generateRandom(start, end, rxBytes, rxPackets, txBytes, txPackets, operations, r); 521293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey } 522293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey 523293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey /** 524293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey * @deprecated only for temporary testing 525293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey */ 526293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey @Deprecated 52763d27a9233fed934340231f438493746084a681dJeff Sharkey public void generateRandom(long start, long end, long rxBytes, long rxPackets, long txBytes, 528293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey long txPackets, long operations, Random r) { 52961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey ensureBuckets(start, end); 53061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 531a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final NetworkStats.Entry entry = new NetworkStats.Entry( 532b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); 53304cd0e47dbc1e9769ac6f258c923d5b17fa57986Jeff Sharkey while (rxBytes > 1024 || rxPackets > 128 || txBytes > 1024 || txPackets > 128 53404cd0e47dbc1e9769ac6f258c923d5b17fa57986Jeff Sharkey || operations > 32) { 53561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey final long curStart = randomLong(r, start, end); 536293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey final long curEnd = curStart + randomLong(r, 0, (end - curStart) / 2); 53763d27a9233fed934340231f438493746084a681dJeff Sharkey 53863d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxBytes = randomLong(r, 0, rxBytes); 53963d27a9233fed934340231f438493746084a681dJeff Sharkey entry.rxPackets = randomLong(r, 0, rxPackets); 54063d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txBytes = randomLong(r, 0, txBytes); 54163d27a9233fed934340231f438493746084a681dJeff Sharkey entry.txPackets = randomLong(r, 0, txPackets); 54263d27a9233fed934340231f438493746084a681dJeff Sharkey entry.operations = randomLong(r, 0, operations); 54363d27a9233fed934340231f438493746084a681dJeff Sharkey 54463d27a9233fed934340231f438493746084a681dJeff Sharkey rxBytes -= entry.rxBytes; 54563d27a9233fed934340231f438493746084a681dJeff Sharkey rxPackets -= entry.rxPackets; 54663d27a9233fed934340231f438493746084a681dJeff Sharkey txBytes -= entry.txBytes; 54763d27a9233fed934340231f438493746084a681dJeff Sharkey txPackets -= entry.txPackets; 54863d27a9233fed934340231f438493746084a681dJeff Sharkey operations -= entry.operations; 549f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 550f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey recordData(curStart, curEnd, entry); 55161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 55261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 55361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 554293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey public static long randomLong(Random r, long start, long end) { 55561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey return (long) (start + (r.nextFloat() * (end - start))); 55661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 55761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 55863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public void dump(IndentingPrintWriter pw, boolean fullHistory) { 55961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey pw.print("NetworkStatsHistory: bucketDuration="); pw.println(bucketDuration); 56063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.increaseIndent(); 561350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 562350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey final int start = fullHistory ? 0 : Math.max(0, bucketCount - 32); 563350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (start > 0) { 56463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print("(omitting "); pw.print(start); pw.println(" buckets)"); 565350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 566350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 567350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey for (int i = start; i < bucketCount; i++) { 56863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.print("bucketStart="); pw.print(bucketStart[i]); 56947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey if (activeTime != null) { pw.print(" activeTime="); pw.print(activeTime[i]); } 57047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey if (rxBytes != null) { pw.print(" rxBytes="); pw.print(rxBytes[i]); } 57147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey if (rxPackets != null) { pw.print(" rxPackets="); pw.print(rxPackets[i]); } 57247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey if (txBytes != null) { pw.print(" txBytes="); pw.print(txBytes[i]); } 57347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey if (txPackets != null) { pw.print(" txPackets="); pw.print(txPackets[i]); } 57447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey if (operations != null) { pw.print(" operations="); pw.print(operations[i]); } 57563d27a9233fed934340231f438493746084a681dJeff Sharkey pw.println(); 57675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 57763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 57863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey pw.decreaseIndent(); 57975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 58075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 58175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey @Override 58275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public String toString() { 58375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final CharArrayWriter writer = new CharArrayWriter(); 58463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey dump(new IndentingPrintWriter(writer, " "), false); 58575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return writer.toString(); 58675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 58775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 58875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() { 589bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 59075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory createFromParcel(Parcel in) { 59175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return new NetworkStatsHistory(in); 59275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 59375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 594bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey @Override 59575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory[] newArray(int size) { 59675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return new NetworkStatsHistory[size]; 59775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 59875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey }; 59975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 60063d27a9233fed934340231f438493746084a681dJeff Sharkey private static long getLong(long[] array, int i, long value) { 60163d27a9233fed934340231f438493746084a681dJeff Sharkey return array != null ? array[i] : value; 60263d27a9233fed934340231f438493746084a681dJeff Sharkey } 60363d27a9233fed934340231f438493746084a681dJeff Sharkey 60463d27a9233fed934340231f438493746084a681dJeff Sharkey private static void setLong(long[] array, int i, long value) { 60563d27a9233fed934340231f438493746084a681dJeff Sharkey if (array != null) array[i] = value; 60663d27a9233fed934340231f438493746084a681dJeff Sharkey } 60763d27a9233fed934340231f438493746084a681dJeff Sharkey 60863d27a9233fed934340231f438493746084a681dJeff Sharkey private static void addLong(long[] array, int i, long value) { 60963d27a9233fed934340231f438493746084a681dJeff Sharkey if (array != null) array[i] += value; 61063d27a9233fed934340231f438493746084a681dJeff Sharkey } 61163d27a9233fed934340231f438493746084a681dJeff Sharkey 61263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey public int estimateResizeBuckets(long newBucketDuration) { 61363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey return (int) (size() * getBucketDuration() / newBucketDuration); 61463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey } 61563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey 616a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey /** 617a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * Utility methods for interacting with {@link DataInputStream} and 618a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * {@link DataOutputStream}, mostly dealing with writing partial arrays. 619a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey */ 620a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public static class DataStreamUtils { 62163d27a9233fed934340231f438493746084a681dJeff Sharkey @Deprecated 62263d27a9233fed934340231f438493746084a681dJeff Sharkey public static long[] readFullLongArray(DataInputStream in) throws IOException { 623a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final int size = in.readInt(); 624a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final long[] values = new long[size]; 625a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey for (int i = 0; i < values.length; i++) { 626a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey values[i] = in.readLong(); 627a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 628a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey return values; 629a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 630a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 63163d27a9233fed934340231f438493746084a681dJeff Sharkey /** 63263d27a9233fed934340231f438493746084a681dJeff Sharkey * Read variable-length {@link Long} using protobuf-style approach. 63363d27a9233fed934340231f438493746084a681dJeff Sharkey */ 63463d27a9233fed934340231f438493746084a681dJeff Sharkey public static long readVarLong(DataInputStream in) throws IOException { 63563d27a9233fed934340231f438493746084a681dJeff Sharkey int shift = 0; 63663d27a9233fed934340231f438493746084a681dJeff Sharkey long result = 0; 63763d27a9233fed934340231f438493746084a681dJeff Sharkey while (shift < 64) { 63863d27a9233fed934340231f438493746084a681dJeff Sharkey byte b = in.readByte(); 63963d27a9233fed934340231f438493746084a681dJeff Sharkey result |= (long) (b & 0x7F) << shift; 64063d27a9233fed934340231f438493746084a681dJeff Sharkey if ((b & 0x80) == 0) 64163d27a9233fed934340231f438493746084a681dJeff Sharkey return result; 64263d27a9233fed934340231f438493746084a681dJeff Sharkey shift += 7; 64363d27a9233fed934340231f438493746084a681dJeff Sharkey } 64463d27a9233fed934340231f438493746084a681dJeff Sharkey throw new ProtocolException("malformed long"); 64563d27a9233fed934340231f438493746084a681dJeff Sharkey } 64663d27a9233fed934340231f438493746084a681dJeff Sharkey 64763d27a9233fed934340231f438493746084a681dJeff Sharkey /** 64863d27a9233fed934340231f438493746084a681dJeff Sharkey * Write variable-length {@link Long} using protobuf-style approach. 64963d27a9233fed934340231f438493746084a681dJeff Sharkey */ 65063d27a9233fed934340231f438493746084a681dJeff Sharkey public static void writeVarLong(DataOutputStream out, long value) throws IOException { 65163d27a9233fed934340231f438493746084a681dJeff Sharkey while (true) { 65263d27a9233fed934340231f438493746084a681dJeff Sharkey if ((value & ~0x7FL) == 0) { 65363d27a9233fed934340231f438493746084a681dJeff Sharkey out.writeByte((int) value); 65463d27a9233fed934340231f438493746084a681dJeff Sharkey return; 65563d27a9233fed934340231f438493746084a681dJeff Sharkey } else { 65663d27a9233fed934340231f438493746084a681dJeff Sharkey out.writeByte(((int) value & 0x7F) | 0x80); 65763d27a9233fed934340231f438493746084a681dJeff Sharkey value >>>= 7; 65863d27a9233fed934340231f438493746084a681dJeff Sharkey } 65963d27a9233fed934340231f438493746084a681dJeff Sharkey } 66063d27a9233fed934340231f438493746084a681dJeff Sharkey } 66163d27a9233fed934340231f438493746084a681dJeff Sharkey 66263d27a9233fed934340231f438493746084a681dJeff Sharkey public static long[] readVarLongArray(DataInputStream in) throws IOException { 66363d27a9233fed934340231f438493746084a681dJeff Sharkey final int size = in.readInt(); 66463d27a9233fed934340231f438493746084a681dJeff Sharkey if (size == -1) return null; 66563d27a9233fed934340231f438493746084a681dJeff Sharkey final long[] values = new long[size]; 66663d27a9233fed934340231f438493746084a681dJeff Sharkey for (int i = 0; i < values.length; i++) { 66763d27a9233fed934340231f438493746084a681dJeff Sharkey values[i] = readVarLong(in); 66863d27a9233fed934340231f438493746084a681dJeff Sharkey } 66963d27a9233fed934340231f438493746084a681dJeff Sharkey return values; 67063d27a9233fed934340231f438493746084a681dJeff Sharkey } 67163d27a9233fed934340231f438493746084a681dJeff Sharkey 67263d27a9233fed934340231f438493746084a681dJeff Sharkey public static void writeVarLongArray(DataOutputStream out, long[] values, int size) 673a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey throws IOException { 67463d27a9233fed934340231f438493746084a681dJeff Sharkey if (values == null) { 67563d27a9233fed934340231f438493746084a681dJeff Sharkey out.writeInt(-1); 67663d27a9233fed934340231f438493746084a681dJeff Sharkey return; 67763d27a9233fed934340231f438493746084a681dJeff Sharkey } 678a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey if (size > values.length) { 679a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey throw new IllegalArgumentException("size larger than length"); 680a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 681a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey out.writeInt(size); 682a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey for (int i = 0; i < size; i++) { 68363d27a9233fed934340231f438493746084a681dJeff Sharkey writeVarLong(out, values[i]); 684a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 68575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 68675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 68775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 688a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey /** 689a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * Utility methods for interacting with {@link Parcel} structures, mostly 690a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey * dealing with writing partial arrays. 691a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey */ 692a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public static class ParcelUtils { 693a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public static long[] readLongArray(Parcel in) { 694a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final int size = in.readInt(); 69563d27a9233fed934340231f438493746084a681dJeff Sharkey if (size == -1) return null; 696a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final long[] values = new long[size]; 697a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey for (int i = 0; i < values.length; i++) { 698a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey values[i] = in.readLong(); 699a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 700a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey return values; 70175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 70275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 703a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey public static void writeLongArray(Parcel out, long[] values, int size) { 70463d27a9233fed934340231f438493746084a681dJeff Sharkey if (values == null) { 70563d27a9233fed934340231f438493746084a681dJeff Sharkey out.writeInt(-1); 70663d27a9233fed934340231f438493746084a681dJeff Sharkey return; 707a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 708a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey if (size > values.length) { 709a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey throw new IllegalArgumentException("size larger than length"); 710a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 711a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey out.writeInt(size); 712a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey for (int i = 0; i < size; i++) { 71363d27a9233fed934340231f438493746084a681dJeff Sharkey out.writeLong(values[i]); 714a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 71575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 71675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 71775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 71875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey} 719