NetworkStatsHistory.java revision 61ee0bbb5b87fb5c4c3dc219868d52743def3d2b
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 1975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Parcel; 2075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Parcelable; 2175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 2275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.CharArrayWriter; 2375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.DataInputStream; 2475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.DataOutputStream; 2575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.IOException; 2675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.PrintWriter; 2761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.net.ProtocolException; 2875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.Arrays; 2961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.util.Random; 3075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 3175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/** 3275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collection of historical network statistics, recorded into equally-sized 3375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * "buckets" in time. Internally it stores data in {@code long} series for more 3475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * efficient persistence. 3575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * <p> 3675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Each bucket is defined by a {@link #bucketStart} timestamp, and lasts for 3775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * {@link #bucketDuration}. Internally assumes that {@link #bucketStart} is 3875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * sorted at all times. 3975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 4075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * @hide 4175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 4275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypublic class NetworkStatsHistory implements Parcelable { 4361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey private static final int VERSION_CURRENT = 1; 4475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 4575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // TODO: teach about zigzag encoding to use less disk space 4675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // TODO: teach how to convert between bucket sizes 4775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 4875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public final long bucketDuration; 4975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 50d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public int bucketCount; 51d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public long[] bucketStart; 52d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public long[] rx; 53d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public long[] tx; 5475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 55d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public NetworkStatsHistory(long bucketDuration) { 5675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey this.bucketDuration = bucketDuration; 5775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = new long[0]; 5875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx = new long[0]; 5975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx = new long[0]; 6075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount = bucketStart.length; 6175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 6275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 6375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory(Parcel in) { 6475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketDuration = in.readLong(); 6575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = readLongArray(in); 6675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx = in.createLongArray(); 6775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx = in.createLongArray(); 6875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount = bucketStart.length; 6975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 7075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 7175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** {@inheritDoc} */ 7275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void writeToParcel(Parcel out, int flags) { 7375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(bucketDuration); 7475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, bucketStart, bucketCount); 7575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, rx, bucketCount); 7675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, tx, bucketCount); 7775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 7875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 7975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory(DataInputStream in) throws IOException { 8075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int version = in.readInt(); 8161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey switch (version) { 8261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey case VERSION_CURRENT: { 8361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey bucketDuration = in.readLong(); 8461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey bucketStart = readLongArray(in); 8561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey rx = readLongArray(in); 8661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey tx = readLongArray(in); 8761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey bucketCount = bucketStart.length; 8861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey break; 8961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 9061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey default: { 9161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey throw new ProtocolException("unexpected version: " + version); 9261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 9361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 9475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 9575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 9675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void writeToStream(DataOutputStream out) throws IOException { 9761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey out.writeInt(VERSION_CURRENT); 9875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(bucketDuration); 9975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, bucketStart, bucketCount); 10075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, rx, bucketCount); 10175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, tx, bucketCount); 10275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 10375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 10475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** {@inheritDoc} */ 10575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public int describeContents() { 10675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return 0; 10775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 10875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 10975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 11075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Record that data traffic occurred in the given time range. Will 11175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * distribute across internal buckets, creating new buckets as needed. 11275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 11375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void recordData(long start, long end, long rx, long tx) { 11475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create any buckets needed by this range 11575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey ensureBuckets(start, end); 11675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 11775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // distribute data usage into buckets 11875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long duration = end - start; 11975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = bucketCount - 1; i >= 0; i--) { 12075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curStart = bucketStart[i]; 12175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curEnd = curStart + bucketDuration; 12275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 12375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket is older than record; we're finished 12475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curEnd < start) break; 12575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket is newer than record; keep looking 12675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curStart > end) continue; 12775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 12875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); 12975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (overlap > 0) { 13075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey this.rx[i] += rx * overlap / duration; 13175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey this.tx[i] += tx * overlap / duration; 13275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 13375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 13475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 13575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 13675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 13775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Ensure that buckets exist for given time range, creating as needed. 13875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 13975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private void ensureBuckets(long start, long end) { 14075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // normalize incoming range to bucket boundaries 14175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey start -= start % bucketDuration; 14275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey end += (bucketDuration - (end % bucketDuration)) % bucketDuration; 14375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 14475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (long now = start; now < end; now += bucketDuration) { 14575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // try finding existing bucket 14675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int index = Arrays.binarySearch(bucketStart, 0, bucketCount, now); 14775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (index < 0) { 14875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket missing, create and insert 14975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey insertBucket(~index, now); 15075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 15175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 15275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 15375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 15475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 15575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Insert new bucket at requested index and starting time. 15675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 15775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private void insertBucket(int index, long start) { 15875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create more buckets when needed 15975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (bucketCount + 1 > bucketStart.length) { 16075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int newLength = bucketStart.length + 10; 16175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = Arrays.copyOf(bucketStart, newLength); 16275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx = Arrays.copyOf(rx, newLength); 16375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx = Arrays.copyOf(tx, newLength); 16475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 16575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 16675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create gap when inserting bucket in middle 16775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (index < bucketCount) { 16875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int dstPos = index + 1; 16975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int length = bucketCount - index; 17075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 17175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey System.arraycopy(bucketStart, index, bucketStart, dstPos, length); 17275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey System.arraycopy(rx, index, rx, dstPos, length); 17375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey System.arraycopy(tx, index, tx, dstPos, length); 17475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 17575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 17675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart[index] = start; 17775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx[index] = 0; 17875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx[index] = 0; 17975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount++; 18075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 18175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 18275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 18375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Remove buckets older than requested cutoff. 18475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 18575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void removeBucketsBefore(long cutoff) { 18675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey int i; 18775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (i = 0; i < bucketCount; i++) { 18875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curStart = bucketStart[i]; 18975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curEnd = curStart + bucketDuration; 19075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 19175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // cutoff happens before or during this bucket; everything before 19275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // this bucket should be removed. 19375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curEnd > cutoff) break; 19475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 19575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 19675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (i > 0) { 19775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int length = bucketStart.length; 19875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = Arrays.copyOfRange(bucketStart, i, length); 19975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx = Arrays.copyOfRange(rx, i, length); 20075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx = Arrays.copyOfRange(tx, i, length); 20175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount -= i; 20275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 20375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 20475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 20561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey /** 20661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey * @deprecated only for temporary testing 20761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey */ 20861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey @Deprecated 20961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey public void generateRandom(long start, long end, long rx, long tx) { 21061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey ensureBuckets(start, end); 21161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 21261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey final Random r = new Random(); 21361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey while (rx > 1024 && tx > 1024) { 21461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey final long curStart = randomLong(r, start, end); 21561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey final long curEnd = randomLong(r, curStart, end); 21661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey final long curRx = randomLong(r, 0, rx); 21761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey final long curTx = randomLong(r, 0, tx); 21861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 21961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey recordData(curStart, curEnd, curRx, curTx); 22061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 22161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey rx -= curRx; 22261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey tx -= curTx; 22361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 22461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 22561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 22661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey private static long randomLong(Random r, long start, long end) { 22761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey return (long) (start + (r.nextFloat() * (end - start))); 22861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey } 22961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey 23075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void dump(String prefix, PrintWriter pw) { 23175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey pw.print(prefix); 23261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey pw.print("NetworkStatsHistory: bucketDuration="); pw.println(bucketDuration); 23375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < bucketCount; i++) { 23475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey pw.print(prefix); 23561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey pw.print(" bucketStart="); pw.print(bucketStart[i]); 23675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey pw.print(" rx="); pw.print(rx[i]); 23775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey pw.print(" tx="); pw.println(tx[i]); 23875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 23975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 24075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 24175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey @Override 24275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public String toString() { 24375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final CharArrayWriter writer = new CharArrayWriter(); 24475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey dump("", new PrintWriter(writer)); 24575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return writer.toString(); 24675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 24775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 24875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() { 24975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory createFromParcel(Parcel in) { 25075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return new NetworkStatsHistory(in); 25175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 25275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 25375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory[] newArray(int size) { 25475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return new NetworkStatsHistory[size]; 25575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 25675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey }; 25775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 25875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static long[] readLongArray(DataInputStream in) throws IOException { 25975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int size = in.readInt(); 26075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long[] values = new long[size]; 26175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < values.length; i++) { 26275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey values[i] = in.readLong(); 26375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 26475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return values; 26575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 26675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 26775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static void writeLongArray(DataOutputStream out, long[] values, int size) throws IOException { 26875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (size > values.length) { 26975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey throw new IllegalArgumentException("size larger than length"); 27075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 27175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeInt(size); 27275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < size; i++) { 27375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(values[i]); 27475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 27575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 27675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 27775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static long[] readLongArray(Parcel in) { 27875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int size = in.readInt(); 27975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long[] values = new long[size]; 28075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < values.length; i++) { 28175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey values[i] = in.readLong(); 28275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 28375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return values; 28475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 28575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 28675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static void writeLongArray(Parcel out, long[] values, int size) { 28775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (size > values.length) { 28875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey throw new IllegalArgumentException("size larger than length"); 28975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 29075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeInt(size); 29175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < size; i++) { 29275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(values[i]); 29375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 29475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 29575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 29675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey} 297