NetworkStatsHistory.java revision d2a458750e5a3d490af09cecb5c28370baf0a913
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; 2775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.Arrays; 2875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 2975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/** 3075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collection of historical network statistics, recorded into equally-sized 3175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * "buckets" in time. Internally it stores data in {@code long} series for more 3275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * efficient persistence. 3375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * <p> 3475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Each bucket is defined by a {@link #bucketStart} timestamp, and lasts for 3575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * {@link #bucketDuration}. Internally assumes that {@link #bucketStart} is 3675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * sorted at all times. 3775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 3875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * @hide 3975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 4075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypublic class NetworkStatsHistory implements Parcelable { 4175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static final int VERSION = 1; 4275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 4375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // TODO: teach about zigzag encoding to use less disk space 4475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // TODO: teach how to convert between bucket sizes 4575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 4675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public final long bucketDuration; 4775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 48d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public int bucketCount; 49d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public long[] bucketStart; 50d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public long[] rx; 51d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public long[] tx; 5275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 53d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey public NetworkStatsHistory(long bucketDuration) { 5475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey this.bucketDuration = bucketDuration; 5575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = new long[0]; 5675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx = new long[0]; 5775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx = new long[0]; 5875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount = bucketStart.length; 5975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 6075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 6175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory(Parcel in) { 6275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketDuration = in.readLong(); 6375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = readLongArray(in); 6475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx = in.createLongArray(); 6575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx = in.createLongArray(); 6675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount = bucketStart.length; 6775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 6875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 6975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** {@inheritDoc} */ 7075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void writeToParcel(Parcel out, int flags) { 7175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(bucketDuration); 7275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, bucketStart, bucketCount); 7375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, rx, bucketCount); 7475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, tx, bucketCount); 7575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 7675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 7775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory(DataInputStream in) throws IOException { 7875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int version = in.readInt(); 7975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketDuration = in.readLong(); 8075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = readLongArray(in); 8175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx = readLongArray(in); 8275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx = readLongArray(in); 8375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount = bucketStart.length; 8475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 8575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 8675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void writeToStream(DataOutputStream out) throws IOException { 8775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeInt(VERSION); 8875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(bucketDuration); 8975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, bucketStart, bucketCount); 9075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, rx, bucketCount); 9175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey writeLongArray(out, tx, bucketCount); 9275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 9375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 9475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** {@inheritDoc} */ 9575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public int describeContents() { 9675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return 0; 9775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 9875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 9975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 10075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Record that data traffic occurred in the given time range. Will 10175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * distribute across internal buckets, creating new buckets as needed. 10275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 10375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void recordData(long start, long end, long rx, long tx) { 10475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create any buckets needed by this range 10575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey ensureBuckets(start, end); 10675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 10775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // distribute data usage into buckets 10875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long duration = end - start; 10975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = bucketCount - 1; i >= 0; i--) { 11075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curStart = bucketStart[i]; 11175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curEnd = curStart + bucketDuration; 11275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 11375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket is older than record; we're finished 11475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curEnd < start) break; 11575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket is newer than record; keep looking 11675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curStart > end) continue; 11775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 11875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); 11975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (overlap > 0) { 12075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey this.rx[i] += rx * overlap / duration; 12175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey this.tx[i] += tx * overlap / duration; 12275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 12375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 12475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 12575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 12675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 12775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Ensure that buckets exist for given time range, creating as needed. 12875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 12975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private void ensureBuckets(long start, long end) { 13075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // normalize incoming range to bucket boundaries 13175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey start -= start % bucketDuration; 13275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey end += (bucketDuration - (end % bucketDuration)) % bucketDuration; 13375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 13475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (long now = start; now < end; now += bucketDuration) { 13575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // try finding existing bucket 13675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int index = Arrays.binarySearch(bucketStart, 0, bucketCount, now); 13775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (index < 0) { 13875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // bucket missing, create and insert 13975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey insertBucket(~index, now); 14075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 14175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 14275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 14375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 14475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 14575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Insert new bucket at requested index and starting time. 14675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 14775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private void insertBucket(int index, long start) { 14875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create more buckets when needed 14975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (bucketCount + 1 > bucketStart.length) { 15075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int newLength = bucketStart.length + 10; 15175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = Arrays.copyOf(bucketStart, newLength); 15275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx = Arrays.copyOf(rx, newLength); 15375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx = Arrays.copyOf(tx, newLength); 15475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 15575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 15675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // create gap when inserting bucket in middle 15775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (index < bucketCount) { 15875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int dstPos = index + 1; 15975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int length = bucketCount - index; 16075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 16175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey System.arraycopy(bucketStart, index, bucketStart, dstPos, length); 16275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey System.arraycopy(rx, index, rx, dstPos, length); 16375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey System.arraycopy(tx, index, tx, dstPos, length); 16475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 16575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 16675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart[index] = start; 16775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx[index] = 0; 16875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx[index] = 0; 16975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount++; 17075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 17175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 17275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey /** 17375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Remove buckets older than requested cutoff. 17475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 17575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void removeBucketsBefore(long cutoff) { 17675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey int i; 17775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (i = 0; i < bucketCount; i++) { 17875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curStart = bucketStart[i]; 17975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long curEnd = curStart + bucketDuration; 18075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 18175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // cutoff happens before or during this bucket; everything before 18275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // this bucket should be removed. 18375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (curEnd > cutoff) break; 18475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 18575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 18675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (i > 0) { 18775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int length = bucketStart.length; 18875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketStart = Arrays.copyOfRange(bucketStart, i, length); 18975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey rx = Arrays.copyOfRange(rx, i, length); 19075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey tx = Arrays.copyOfRange(tx, i, length); 19175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey bucketCount -= i; 19275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 19375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 19475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 19575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void dump(String prefix, PrintWriter pw) { 19675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey pw.print(prefix); 197d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey pw.println("NetworkStatsHistory:"); 19875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < bucketCount; i++) { 19975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey pw.print(prefix); 20075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey pw.print(" timestamp="); pw.print(bucketStart[i]); 20175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey pw.print(" rx="); pw.print(rx[i]); 20275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey pw.print(" tx="); pw.println(tx[i]); 20375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 20475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 20575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 20675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey @Override 20775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public String toString() { 20875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final CharArrayWriter writer = new CharArrayWriter(); 20975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey dump("", new PrintWriter(writer)); 21075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return writer.toString(); 21175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 21275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 21375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() { 21475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory createFromParcel(Parcel in) { 21575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return new NetworkStatsHistory(in); 21675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 21775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 21875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkStatsHistory[] newArray(int size) { 21975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return new NetworkStatsHistory[size]; 22075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 22175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey }; 22275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 22375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static long[] readLongArray(DataInputStream in) throws IOException { 22475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int size = in.readInt(); 22575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long[] values = new long[size]; 22675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < values.length; i++) { 22775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey values[i] = in.readLong(); 22875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 22975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return values; 23075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 23175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 23275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static void writeLongArray(DataOutputStream out, long[] values, int size) throws IOException { 23375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (size > values.length) { 23475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey throw new IllegalArgumentException("size larger than length"); 23575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 23675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeInt(size); 23775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < size; i++) { 23875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(values[i]); 23975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 24075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 24175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 24275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static long[] readLongArray(Parcel in) { 24375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final int size = in.readInt(); 24475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long[] values = new long[size]; 24575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < values.length; i++) { 24675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey values[i] = in.readLong(); 24775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 24875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey return values; 24975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 25075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 25175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static void writeLongArray(Parcel out, long[] values, int size) { 25275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (size > values.length) { 25375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey throw new IllegalArgumentException("size larger than length"); 25475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 25575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeInt(size); 25675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < size; i++) { 25775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey out.writeLong(values[i]); 25875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 25975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 26075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 26175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey} 262