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