NetworkStatsHistory.java revision 558a23200697d306b75750cf4612cf0717e73537
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;
29a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
3075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Parcel;
3175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Parcelable;
3275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.CharArrayWriter;
3475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.DataInputStream;
3575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.DataOutputStream;
3675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.IOException;
3775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.PrintWriter;
3861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.net.ProtocolException;
3975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.Arrays;
4061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.util.Random;
4175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
4275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/**
4375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collection of historical network statistics, recorded into equally-sized
4475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * "buckets" in time. Internally it stores data in {@code long} series for more
4575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * efficient persistence.
4675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * <p>
4775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Each bucket is defined by a {@link #bucketStart} timestamp, and lasts for
4875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * {@link #bucketDuration}. Internally assumes that {@link #bucketStart} is
4975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * sorted at all times.
5075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey *
5175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * @hide
5275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */
5375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypublic class NetworkStatsHistory implements Parcelable {
541b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private static final int VERSION_INIT = 1;
5563d27a9233fed934340231f438493746084a681dJeff Sharkey    private static final int VERSION_ADD_PACKETS = 2;
56558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey    private static final int VERSION_ADD_ACTIVE = 3;
5775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
58558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey    public static final int FIELD_ACTIVE_TIME = 0x01;
59558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey    public static final int FIELD_RX_BYTES = 0x02;
60558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey    public static final int FIELD_RX_PACKETS = 0x04;
61558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey    public static final int FIELD_TX_BYTES = 0x08;
62558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey    public static final int FIELD_TX_PACKETS = 0x10;
63558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey    public static final int FIELD_OPERATIONS = 0x20;
64d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
6563d27a9233fed934340231f438493746084a681dJeff Sharkey    public static final int FIELD_ALL = 0xFFFFFFFF;
6663d27a9233fed934340231f438493746084a681dJeff Sharkey
6763d27a9233fed934340231f438493746084a681dJeff Sharkey    private long bucketDuration;
68d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private int bucketCount;
69d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] bucketStart;
70558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey    private long[] activeTime;
71d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] rxBytes;
72a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    private long[] rxPackets;
73d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    private long[] txBytes;
74a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    private long[] txPackets;
7563d27a9233fed934340231f438493746084a681dJeff Sharkey    private long[] operations;
76d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
77d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    public static class Entry {
7863d27a9233fed934340231f438493746084a681dJeff Sharkey        public static final long UNKNOWN = -1;
7963d27a9233fed934340231f438493746084a681dJeff Sharkey
80d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        public long bucketDuration;
81558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        public long bucketStart;
82558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        public long activeTime;
83d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        public long rxBytes;
84a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        public long rxPackets;
85d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        public long txBytes;
86a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        public long txPackets;
8763d27a9233fed934340231f438493746084a681dJeff Sharkey        public long operations;
88d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    }
8975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
90d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    public NetworkStatsHistory(long bucketDuration) {
9163d27a9233fed934340231f438493746084a681dJeff Sharkey        this(bucketDuration, 10, FIELD_ALL);
924a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    }
934a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey
944a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    public NetworkStatsHistory(long bucketDuration, int initialSize) {
9563d27a9233fed934340231f438493746084a681dJeff Sharkey        this(bucketDuration, initialSize, FIELD_ALL);
9663d27a9233fed934340231f438493746084a681dJeff Sharkey    }
9763d27a9233fed934340231f438493746084a681dJeff Sharkey
9863d27a9233fed934340231f438493746084a681dJeff Sharkey    public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) {
9975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        this.bucketDuration = bucketDuration;
1004a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        bucketStart = new long[initialSize];
101558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        if ((fields & FIELD_ACTIVE_TIME) != 0) activeTime = new long[initialSize];
10263d27a9233fed934340231f438493746084a681dJeff Sharkey        if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize];
10363d27a9233fed934340231f438493746084a681dJeff Sharkey        if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize];
10463d27a9233fed934340231f438493746084a681dJeff Sharkey        if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize];
10563d27a9233fed934340231f438493746084a681dJeff Sharkey        if ((fields & FIELD_TX_PACKETS) != 0) txPackets = new long[initialSize];
10663d27a9233fed934340231f438493746084a681dJeff Sharkey        if ((fields & FIELD_OPERATIONS) != 0) operations = new long[initialSize];
1074a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        bucketCount = 0;
10875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
10975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
11075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkStatsHistory(Parcel in) {
11175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        bucketDuration = in.readLong();
11275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        bucketStart = readLongArray(in);
113558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        activeTime = readLongArray(in);
114a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        rxBytes = readLongArray(in);
115a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        rxPackets = readLongArray(in);
116a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        txBytes = readLongArray(in);
117a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        txPackets = readLongArray(in);
11863d27a9233fed934340231f438493746084a681dJeff Sharkey        operations = readLongArray(in);
11975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        bucketCount = bucketStart.length;
12075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
12175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
12275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /** {@inheritDoc} */
12375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public void writeToParcel(Parcel out, int flags) {
12475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        out.writeLong(bucketDuration);
12575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        writeLongArray(out, bucketStart, bucketCount);
126558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        writeLongArray(out, activeTime, bucketCount);
127d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        writeLongArray(out, rxBytes, bucketCount);
128a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        writeLongArray(out, rxPackets, bucketCount);
129d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        writeLongArray(out, txBytes, bucketCount);
130a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        writeLongArray(out, txPackets, bucketCount);
13163d27a9233fed934340231f438493746084a681dJeff Sharkey        writeLongArray(out, operations, bucketCount);
13275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
13375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
13475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkStatsHistory(DataInputStream in) throws IOException {
13575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final int version = in.readInt();
13661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        switch (version) {
1371b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            case VERSION_INIT: {
13861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                bucketDuration = in.readLong();
13963d27a9233fed934340231f438493746084a681dJeff Sharkey                bucketStart = readFullLongArray(in);
14063d27a9233fed934340231f438493746084a681dJeff Sharkey                rxBytes = readFullLongArray(in);
141a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                rxPackets = new long[bucketStart.length];
14263d27a9233fed934340231f438493746084a681dJeff Sharkey                txBytes = readFullLongArray(in);
143a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                txPackets = new long[bucketStart.length];
14463d27a9233fed934340231f438493746084a681dJeff Sharkey                operations = new long[bucketStart.length];
14563d27a9233fed934340231f438493746084a681dJeff Sharkey                bucketCount = bucketStart.length;
14663d27a9233fed934340231f438493746084a681dJeff Sharkey                break;
14763d27a9233fed934340231f438493746084a681dJeff Sharkey            }
148558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey            case VERSION_ADD_PACKETS:
149558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey            case VERSION_ADD_ACTIVE: {
15063d27a9233fed934340231f438493746084a681dJeff Sharkey                bucketDuration = in.readLong();
15163d27a9233fed934340231f438493746084a681dJeff Sharkey                bucketStart = readVarLongArray(in);
152558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey                activeTime = (version >= VERSION_ADD_ACTIVE) ? readVarLongArray(in)
153558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey                        : new long[bucketStart.length];
15463d27a9233fed934340231f438493746084a681dJeff Sharkey                rxBytes = readVarLongArray(in);
15563d27a9233fed934340231f438493746084a681dJeff Sharkey                rxPackets = readVarLongArray(in);
15663d27a9233fed934340231f438493746084a681dJeff Sharkey                txBytes = readVarLongArray(in);
15763d27a9233fed934340231f438493746084a681dJeff Sharkey                txPackets = readVarLongArray(in);
15863d27a9233fed934340231f438493746084a681dJeff Sharkey                operations = readVarLongArray(in);
15961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                bucketCount = bucketStart.length;
16061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                break;
16161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
16261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            default: {
16361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                throw new ProtocolException("unexpected version: " + version);
16461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
16561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
16675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
16775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
16875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public void writeToStream(DataOutputStream out) throws IOException {
169558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        out.writeInt(VERSION_ADD_ACTIVE);
17075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        out.writeLong(bucketDuration);
17163d27a9233fed934340231f438493746084a681dJeff Sharkey        writeVarLongArray(out, bucketStart, bucketCount);
172558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        writeVarLongArray(out, activeTime, bucketCount);
17363d27a9233fed934340231f438493746084a681dJeff Sharkey        writeVarLongArray(out, rxBytes, bucketCount);
17463d27a9233fed934340231f438493746084a681dJeff Sharkey        writeVarLongArray(out, rxPackets, bucketCount);
17563d27a9233fed934340231f438493746084a681dJeff Sharkey        writeVarLongArray(out, txBytes, bucketCount);
17663d27a9233fed934340231f438493746084a681dJeff Sharkey        writeVarLongArray(out, txPackets, bucketCount);
17763d27a9233fed934340231f438493746084a681dJeff Sharkey        writeVarLongArray(out, operations, bucketCount);
17875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
17975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
18075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /** {@inheritDoc} */
18175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public int describeContents() {
18275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        return 0;
18375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
18475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
185d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    public int size() {
186d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        return bucketCount;
187d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    }
188d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
189d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    public long getBucketDuration() {
190d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        return bucketDuration;
191d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    }
192d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
193434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey    public long getStart() {
194434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey        if (bucketCount > 0) {
195434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            return bucketStart[0];
196434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey        } else {
197434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            return Long.MAX_VALUE;
198434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey        }
199434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey    }
200434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey
201434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey    public long getEnd() {
202434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey        if (bucketCount > 0) {
203434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            return bucketStart[bucketCount - 1] + bucketDuration;
204434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey        } else {
205434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            return Long.MIN_VALUE;
206434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey        }
207434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey    }
208434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey
209d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    /**
210d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey     * Return specific stats entry.
211d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey     */
212d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    public Entry getValues(int i, Entry recycle) {
213d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        final Entry entry = recycle != null ? recycle : new Entry();
214d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        entry.bucketStart = bucketStart[i];
215d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        entry.bucketDuration = bucketDuration;
216558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        entry.activeTime = getLong(activeTime, i, UNKNOWN);
21763d27a9233fed934340231f438493746084a681dJeff Sharkey        entry.rxBytes = getLong(rxBytes, i, UNKNOWN);
21863d27a9233fed934340231f438493746084a681dJeff Sharkey        entry.rxPackets = getLong(rxPackets, i, UNKNOWN);
21963d27a9233fed934340231f438493746084a681dJeff Sharkey        entry.txBytes = getLong(txBytes, i, UNKNOWN);
22063d27a9233fed934340231f438493746084a681dJeff Sharkey        entry.txPackets = getLong(txPackets, i, UNKNOWN);
22163d27a9233fed934340231f438493746084a681dJeff Sharkey        entry.operations = getLong(operations, i, UNKNOWN);
222d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        return entry;
223d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey    }
224d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
22575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
22675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Record that data traffic occurred in the given time range. Will
22775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * distribute across internal buckets, creating new buckets as needed.
22875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
229a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    @Deprecated
230a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public void recordData(long start, long end, long rxBytes, long txBytes) {
231b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        recordData(start, end, new NetworkStats.Entry(
232b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0L));
233a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
234a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
235a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /**
236a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * Record that data traffic occurred in the given time range. Will
237a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * distribute across internal buckets, creating new buckets as needed.
238a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     */
239a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public void recordData(long start, long end, NetworkStats.Entry entry) {
240a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 || entry.txPackets < 0
241a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                || entry.operations < 0) {
242a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            throw new IllegalArgumentException("tried recording negative data");
2431b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
2441b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
24575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // create any buckets needed by this range
24675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        ensureBuckets(start, end);
24775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
24875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // distribute data usage into buckets
249a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        long duration = end - start;
25075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        for (int i = bucketCount - 1; i >= 0; i--) {
25175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            final long curStart = bucketStart[i];
25275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            final long curEnd = curStart + bucketDuration;
25375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
25475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            // bucket is older than record; we're finished
25575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            if (curEnd < start) break;
25675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            // bucket is newer than record; keep looking
25775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            if (curStart > end) continue;
25875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
25975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            final long overlap = Math.min(curEnd, end) - Math.max(curStart, start);
260a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            if (overlap <= 0) continue;
261a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
262a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            // integer math each time is faster than floating point
263a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            final long fracRxBytes = entry.rxBytes * overlap / duration;
264a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            final long fracRxPackets = entry.rxPackets * overlap / duration;
265a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            final long fracTxBytes = entry.txBytes * overlap / duration;
266a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            final long fracTxPackets = entry.txPackets * overlap / duration;
267558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey            final long fracOperations = entry.operations * overlap / duration;
268a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
269558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey            addLong(activeTime, i, overlap);
27063d27a9233fed934340231f438493746084a681dJeff Sharkey            addLong(rxBytes, i, fracRxBytes); entry.rxBytes -= fracRxBytes;
27163d27a9233fed934340231f438493746084a681dJeff Sharkey            addLong(rxPackets, i, fracRxPackets); entry.rxPackets -= fracRxPackets;
27263d27a9233fed934340231f438493746084a681dJeff Sharkey            addLong(txBytes, i, fracTxBytes); entry.txBytes -= fracTxBytes;
27363d27a9233fed934340231f438493746084a681dJeff Sharkey            addLong(txPackets, i, fracTxPackets); entry.txPackets -= fracTxPackets;
27463d27a9233fed934340231f438493746084a681dJeff Sharkey            addLong(operations, i, fracOperations); entry.operations -= fracOperations;
275a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
276a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            duration -= overlap;
27775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
27875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
27975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
28075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
28119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey     * Record an entire {@link NetworkStatsHistory} into this history. Usually
28219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey     * for combining together stats for external reporting.
28319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey     */
28419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey    public void recordEntireHistory(NetworkStatsHistory input) {
285a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        final NetworkStats.Entry entry = new NetworkStats.Entry(
286b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
28719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        for (int i = 0; i < input.bucketCount; i++) {
28819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            final long start = input.bucketStart[i];
28919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            final long end = start + input.bucketDuration;
290a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
29163d27a9233fed934340231f438493746084a681dJeff Sharkey            entry.rxBytes = getLong(input.rxBytes, i, 0L);
29263d27a9233fed934340231f438493746084a681dJeff Sharkey            entry.rxPackets = getLong(input.rxPackets, i, 0L);
29363d27a9233fed934340231f438493746084a681dJeff Sharkey            entry.txBytes = getLong(input.txBytes, i, 0L);
29463d27a9233fed934340231f438493746084a681dJeff Sharkey            entry.txPackets = getLong(input.txPackets, i, 0L);
29563d27a9233fed934340231f438493746084a681dJeff Sharkey            entry.operations = getLong(input.operations, i, 0L);
296a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
297a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            recordData(start, end, entry);
29819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        }
29919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey    }
30019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey
30119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey    /**
30275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Ensure that buckets exist for given time range, creating as needed.
30375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
30475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private void ensureBuckets(long start, long end) {
30575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // normalize incoming range to bucket boundaries
30675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        start -= start % bucketDuration;
30775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        end += (bucketDuration - (end % bucketDuration)) % bucketDuration;
30875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
30975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        for (long now = start; now < end; now += bucketDuration) {
31075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            // try finding existing bucket
31175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            final int index = Arrays.binarySearch(bucketStart, 0, bucketCount, now);
31275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            if (index < 0) {
31375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                // bucket missing, create and insert
31475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                insertBucket(~index, now);
31575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
31675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
31775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
31875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
31975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
32075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Insert new bucket at requested index and starting time.
32175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
32275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private void insertBucket(int index, long start) {
32375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // create more buckets when needed
3244a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        if (bucketCount >= bucketStart.length) {
3254a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            final int newLength = Math.max(bucketStart.length, 10) * 3 / 2;
32675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            bucketStart = Arrays.copyOf(bucketStart, newLength);
327558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey            if (activeTime != null) activeTime = Arrays.copyOf(activeTime, newLength);
32863d27a9233fed934340231f438493746084a681dJeff Sharkey            if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength);
32963d27a9233fed934340231f438493746084a681dJeff Sharkey            if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength);
33063d27a9233fed934340231f438493746084a681dJeff Sharkey            if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength);
33163d27a9233fed934340231f438493746084a681dJeff Sharkey            if (txPackets != null) txPackets = Arrays.copyOf(txPackets, newLength);
33263d27a9233fed934340231f438493746084a681dJeff Sharkey            if (operations != null) operations = Arrays.copyOf(operations, newLength);
33375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
33475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
33575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // create gap when inserting bucket in middle
33675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        if (index < bucketCount) {
33775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            final int dstPos = index + 1;
33875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            final int length = bucketCount - index;
33975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
34075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
341558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey            if (activeTime != null) System.arraycopy(activeTime, index, activeTime, dstPos, length);
34263d27a9233fed934340231f438493746084a681dJeff Sharkey            if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
34363d27a9233fed934340231f438493746084a681dJeff Sharkey            if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length);
34463d27a9233fed934340231f438493746084a681dJeff Sharkey            if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length);
34563d27a9233fed934340231f438493746084a681dJeff Sharkey            if (txPackets != null) System.arraycopy(txPackets, index, txPackets, dstPos, length);
34663d27a9233fed934340231f438493746084a681dJeff Sharkey            if (operations != null) System.arraycopy(operations, index, operations, dstPos, length);
34775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
34875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
34975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        bucketStart[index] = start;
350558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        setLong(activeTime, index, 0L);
35163d27a9233fed934340231f438493746084a681dJeff Sharkey        setLong(rxBytes, index, 0L);
35263d27a9233fed934340231f438493746084a681dJeff Sharkey        setLong(rxPackets, index, 0L);
35363d27a9233fed934340231f438493746084a681dJeff Sharkey        setLong(txBytes, index, 0L);
35463d27a9233fed934340231f438493746084a681dJeff Sharkey        setLong(txPackets, index, 0L);
35563d27a9233fed934340231f438493746084a681dJeff Sharkey        setLong(operations, index, 0L);
35675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        bucketCount++;
35775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
35875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
35975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
36075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Remove buckets older than requested cutoff.
36175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
36275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public void removeBucketsBefore(long cutoff) {
36375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        int i;
36475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        for (i = 0; i < bucketCount; i++) {
36575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            final long curStart = bucketStart[i];
36675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            final long curEnd = curStart + bucketDuration;
36775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
36875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            // cutoff happens before or during this bucket; everything before
36975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            // this bucket should be removed.
37075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            if (curEnd > cutoff) break;
37175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
37275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
37375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        if (i > 0) {
37475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            final int length = bucketStart.length;
37575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            bucketStart = Arrays.copyOfRange(bucketStart, i, length);
376558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey            if (activeTime != null) activeTime = Arrays.copyOfRange(activeTime, i, length);
37763d27a9233fed934340231f438493746084a681dJeff Sharkey            if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length);
37863d27a9233fed934340231f438493746084a681dJeff Sharkey            if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length);
37963d27a9233fed934340231f438493746084a681dJeff Sharkey            if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length);
38063d27a9233fed934340231f438493746084a681dJeff Sharkey            if (txPackets != null) txPackets = Arrays.copyOfRange(txPackets, i, length);
38163d27a9233fed934340231f438493746084a681dJeff Sharkey            if (operations != null) operations = Arrays.copyOfRange(operations, i, length);
38275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            bucketCount -= i;
38375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
38475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
38575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
38661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
38719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey     * Return interpolated data usage across the requested range. Interpolates
38819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey     * across buckets, so values may be rounded slightly.
38919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey     */
390434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey    public Entry getValues(long start, long end, Entry recycle) {
391434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey        return getValues(start, end, Long.MAX_VALUE, recycle);
392434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey    }
393434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey
394434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey    /**
395434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey     * Return interpolated data usage across the requested range. Interpolates
396434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey     * across buckets, so values may be rounded slightly.
397434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey     */
398434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey    public Entry getValues(long start, long end, long now, Entry recycle) {
399434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey        final Entry entry = recycle != null ? recycle : new Entry();
400434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey        entry.bucketDuration = end - start;
401558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        entry.bucketStart = start;
402558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey        entry.activeTime = activeTime != null ? 0 : UNKNOWN;
40363d27a9233fed934340231f438493746084a681dJeff Sharkey        entry.rxBytes = rxBytes != null ? 0 : UNKNOWN;
40463d27a9233fed934340231f438493746084a681dJeff Sharkey        entry.rxPackets = rxPackets != null ? 0 : UNKNOWN;
40563d27a9233fed934340231f438493746084a681dJeff Sharkey        entry.txBytes = txBytes != null ? 0 : UNKNOWN;
40663d27a9233fed934340231f438493746084a681dJeff Sharkey        entry.txPackets = txPackets != null ? 0 : UNKNOWN;
40763d27a9233fed934340231f438493746084a681dJeff Sharkey        entry.operations = operations != null ? 0 : UNKNOWN;
40819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey
40919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        for (int i = bucketCount - 1; i >= 0; i--) {
41019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            final long curStart = bucketStart[i];
41119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            final long curEnd = curStart + bucketDuration;
41219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey
41319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            // bucket is older than record; we're finished
41419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            if (curEnd < start) break;
41519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            // bucket is newer than record; keep looking
41619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            if (curStart > end) continue;
41719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey
418434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            // include full value for active buckets, otherwise only fractional
419434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            final boolean activeBucket = curStart < now && curEnd > now;
420a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            final long overlap = activeBucket ? bucketDuration
421a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                    : Math.min(curEnd, end) - Math.max(curStart, start);
422a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            if (overlap <= 0) continue;
423a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
424a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            // integer math each time is faster than floating point
425558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey            if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketDuration;
42663d27a9233fed934340231f438493746084a681dJeff Sharkey            if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
42763d27a9233fed934340231f438493746084a681dJeff Sharkey            if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration;
42863d27a9233fed934340231f438493746084a681dJeff Sharkey            if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration;
42963d27a9233fed934340231f438493746084a681dJeff Sharkey            if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketDuration;
43063d27a9233fed934340231f438493746084a681dJeff Sharkey            if (operations != null) entry.operations += operations[i] * overlap / bucketDuration;
43119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        }
43219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey
433434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey        return entry;
43419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey    }
43519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey
43619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey    /**
43761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     * @deprecated only for temporary testing
43861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
43961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    @Deprecated
44063d27a9233fed934340231f438493746084a681dJeff Sharkey    public void generateRandom(long start, long end, long rxBytes, long rxPackets, long txBytes,
44163d27a9233fed934340231f438493746084a681dJeff Sharkey            long txPackets, long operations) {
44261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        ensureBuckets(start, end);
44361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
444a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        final NetworkStats.Entry entry = new NetworkStats.Entry(
445b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
44661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final Random r = new Random();
44704cd0e47dbc1e9769ac6f258c923d5b17fa57986Jeff Sharkey        while (rxBytes > 1024 || rxPackets > 128 || txBytes > 1024 || txPackets > 128
44804cd0e47dbc1e9769ac6f258c923d5b17fa57986Jeff Sharkey                || operations > 32) {
44961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final long curStart = randomLong(r, start, end);
45061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final long curEnd = randomLong(r, curStart, end);
45163d27a9233fed934340231f438493746084a681dJeff Sharkey
45263d27a9233fed934340231f438493746084a681dJeff Sharkey            entry.rxBytes = randomLong(r, 0, rxBytes);
45363d27a9233fed934340231f438493746084a681dJeff Sharkey            entry.rxPackets = randomLong(r, 0, rxPackets);
45463d27a9233fed934340231f438493746084a681dJeff Sharkey            entry.txBytes = randomLong(r, 0, txBytes);
45563d27a9233fed934340231f438493746084a681dJeff Sharkey            entry.txPackets = randomLong(r, 0, txPackets);
45663d27a9233fed934340231f438493746084a681dJeff Sharkey            entry.operations = randomLong(r, 0, operations);
45763d27a9233fed934340231f438493746084a681dJeff Sharkey
45863d27a9233fed934340231f438493746084a681dJeff Sharkey            rxBytes -= entry.rxBytes;
45963d27a9233fed934340231f438493746084a681dJeff Sharkey            rxPackets -= entry.rxPackets;
46063d27a9233fed934340231f438493746084a681dJeff Sharkey            txBytes -= entry.txBytes;
46163d27a9233fed934340231f438493746084a681dJeff Sharkey            txPackets -= entry.txPackets;
46263d27a9233fed934340231f438493746084a681dJeff Sharkey            operations -= entry.operations;
463f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
464f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            recordData(curStart, curEnd, entry);
46561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
46661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
46761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
46861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    private static long randomLong(Random r, long start, long end) {
46961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        return (long) (start + (r.nextFloat() * (end - start)));
47061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
47161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
472350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    public void dump(String prefix, PrintWriter pw, boolean fullHistory) {
47375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        pw.print(prefix);
47461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        pw.print("NetworkStatsHistory: bucketDuration="); pw.println(bucketDuration);
475350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
476350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        final int start = fullHistory ? 0 : Math.max(0, bucketCount - 32);
477350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (start > 0) {
478350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            pw.print(prefix);
479350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            pw.print("  (omitting "); pw.print(start); pw.println(" buckets)");
480350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        }
481350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
482350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        for (int i = start; i < bucketCount; i++) {
48375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            pw.print(prefix);
48461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            pw.print("  bucketStart="); pw.print(bucketStart[i]);
485558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey            if (activeTime != null) pw.print(" activeTime="); pw.print(activeTime[i]);
48663d27a9233fed934340231f438493746084a681dJeff Sharkey            if (rxBytes != null) pw.print(" rxBytes="); pw.print(rxBytes[i]);
48763d27a9233fed934340231f438493746084a681dJeff Sharkey            if (rxPackets != null) pw.print(" rxPackets="); pw.print(rxPackets[i]);
48863d27a9233fed934340231f438493746084a681dJeff Sharkey            if (txBytes != null) pw.print(" txBytes="); pw.print(txBytes[i]);
48963d27a9233fed934340231f438493746084a681dJeff Sharkey            if (txPackets != null) pw.print(" txPackets="); pw.print(txPackets[i]);
49063d27a9233fed934340231f438493746084a681dJeff Sharkey            if (operations != null) pw.print(" operations="); pw.print(operations[i]);
49163d27a9233fed934340231f438493746084a681dJeff Sharkey            pw.println();
49275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
49375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
49475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
49575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
49675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public String toString() {
49775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final CharArrayWriter writer = new CharArrayWriter();
498350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        dump("", new PrintWriter(writer), false);
49975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        return writer.toString();
50075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
50175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
50275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
50375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public NetworkStatsHistory createFromParcel(Parcel in) {
50475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            return new NetworkStatsHistory(in);
50575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
50675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
50775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public NetworkStatsHistory[] newArray(int size) {
50875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            return new NetworkStatsHistory[size];
50975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
51075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
51175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
51263d27a9233fed934340231f438493746084a681dJeff Sharkey    private static long getLong(long[] array, int i, long value) {
51363d27a9233fed934340231f438493746084a681dJeff Sharkey        return array != null ? array[i] : value;
51463d27a9233fed934340231f438493746084a681dJeff Sharkey    }
51563d27a9233fed934340231f438493746084a681dJeff Sharkey
51663d27a9233fed934340231f438493746084a681dJeff Sharkey    private static void setLong(long[] array, int i, long value) {
51763d27a9233fed934340231f438493746084a681dJeff Sharkey        if (array != null) array[i] = value;
51863d27a9233fed934340231f438493746084a681dJeff Sharkey    }
51963d27a9233fed934340231f438493746084a681dJeff Sharkey
52063d27a9233fed934340231f438493746084a681dJeff Sharkey    private static void addLong(long[] array, int i, long value) {
52163d27a9233fed934340231f438493746084a681dJeff Sharkey        if (array != null) array[i] += value;
52263d27a9233fed934340231f438493746084a681dJeff Sharkey    }
52363d27a9233fed934340231f438493746084a681dJeff Sharkey
524a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /**
525a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * Utility methods for interacting with {@link DataInputStream} and
526a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * {@link DataOutputStream}, mostly dealing with writing partial arrays.
527a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     */
528a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public static class DataStreamUtils {
52963d27a9233fed934340231f438493746084a681dJeff Sharkey        @Deprecated
53063d27a9233fed934340231f438493746084a681dJeff Sharkey        public static long[] readFullLongArray(DataInputStream in) throws IOException {
531a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            final int size = in.readInt();
532a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            final long[] values = new long[size];
533a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            for (int i = 0; i < values.length; i++) {
534a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                values[i] = in.readLong();
535a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            }
536a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            return values;
537a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
538a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
53963d27a9233fed934340231f438493746084a681dJeff Sharkey        /**
54063d27a9233fed934340231f438493746084a681dJeff Sharkey         * Read variable-length {@link Long} using protobuf-style approach.
54163d27a9233fed934340231f438493746084a681dJeff Sharkey         */
54263d27a9233fed934340231f438493746084a681dJeff Sharkey        public static long readVarLong(DataInputStream in) throws IOException {
54363d27a9233fed934340231f438493746084a681dJeff Sharkey            int shift = 0;
54463d27a9233fed934340231f438493746084a681dJeff Sharkey            long result = 0;
54563d27a9233fed934340231f438493746084a681dJeff Sharkey            while (shift < 64) {
54663d27a9233fed934340231f438493746084a681dJeff Sharkey                byte b = in.readByte();
54763d27a9233fed934340231f438493746084a681dJeff Sharkey                result |= (long) (b & 0x7F) << shift;
54863d27a9233fed934340231f438493746084a681dJeff Sharkey                if ((b & 0x80) == 0)
54963d27a9233fed934340231f438493746084a681dJeff Sharkey                    return result;
55063d27a9233fed934340231f438493746084a681dJeff Sharkey                shift += 7;
55163d27a9233fed934340231f438493746084a681dJeff Sharkey            }
55263d27a9233fed934340231f438493746084a681dJeff Sharkey            throw new ProtocolException("malformed long");
55363d27a9233fed934340231f438493746084a681dJeff Sharkey        }
55463d27a9233fed934340231f438493746084a681dJeff Sharkey
55563d27a9233fed934340231f438493746084a681dJeff Sharkey        /**
55663d27a9233fed934340231f438493746084a681dJeff Sharkey         * Write variable-length {@link Long} using protobuf-style approach.
55763d27a9233fed934340231f438493746084a681dJeff Sharkey         */
55863d27a9233fed934340231f438493746084a681dJeff Sharkey        public static void writeVarLong(DataOutputStream out, long value) throws IOException {
55963d27a9233fed934340231f438493746084a681dJeff Sharkey            while (true) {
56063d27a9233fed934340231f438493746084a681dJeff Sharkey                if ((value & ~0x7FL) == 0) {
56163d27a9233fed934340231f438493746084a681dJeff Sharkey                    out.writeByte((int) value);
56263d27a9233fed934340231f438493746084a681dJeff Sharkey                    return;
56363d27a9233fed934340231f438493746084a681dJeff Sharkey                } else {
56463d27a9233fed934340231f438493746084a681dJeff Sharkey                    out.writeByte(((int) value & 0x7F) | 0x80);
56563d27a9233fed934340231f438493746084a681dJeff Sharkey                    value >>>= 7;
56663d27a9233fed934340231f438493746084a681dJeff Sharkey                }
56763d27a9233fed934340231f438493746084a681dJeff Sharkey            }
56863d27a9233fed934340231f438493746084a681dJeff Sharkey        }
56963d27a9233fed934340231f438493746084a681dJeff Sharkey
57063d27a9233fed934340231f438493746084a681dJeff Sharkey        public static long[] readVarLongArray(DataInputStream in) throws IOException {
57163d27a9233fed934340231f438493746084a681dJeff Sharkey            final int size = in.readInt();
57263d27a9233fed934340231f438493746084a681dJeff Sharkey            if (size == -1) return null;
57363d27a9233fed934340231f438493746084a681dJeff Sharkey            final long[] values = new long[size];
57463d27a9233fed934340231f438493746084a681dJeff Sharkey            for (int i = 0; i < values.length; i++) {
57563d27a9233fed934340231f438493746084a681dJeff Sharkey                values[i] = readVarLong(in);
57663d27a9233fed934340231f438493746084a681dJeff Sharkey            }
57763d27a9233fed934340231f438493746084a681dJeff Sharkey            return values;
57863d27a9233fed934340231f438493746084a681dJeff Sharkey        }
57963d27a9233fed934340231f438493746084a681dJeff Sharkey
58063d27a9233fed934340231f438493746084a681dJeff Sharkey        public static void writeVarLongArray(DataOutputStream out, long[] values, int size)
581a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                throws IOException {
58263d27a9233fed934340231f438493746084a681dJeff Sharkey            if (values == null) {
58363d27a9233fed934340231f438493746084a681dJeff Sharkey                out.writeInt(-1);
58463d27a9233fed934340231f438493746084a681dJeff Sharkey                return;
58563d27a9233fed934340231f438493746084a681dJeff Sharkey            }
586a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            if (size > values.length) {
587a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                throw new IllegalArgumentException("size larger than length");
588a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            }
589a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            out.writeInt(size);
590a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            for (int i = 0; i < size; i++) {
59163d27a9233fed934340231f438493746084a681dJeff Sharkey                writeVarLong(out, values[i]);
592a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            }
59375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
59475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
59575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
596a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /**
597a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * Utility methods for interacting with {@link Parcel} structures, mostly
598a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     * dealing with writing partial arrays.
599a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey     */
600a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public static class ParcelUtils {
601a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        public static long[] readLongArray(Parcel in) {
602a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            final int size = in.readInt();
60363d27a9233fed934340231f438493746084a681dJeff Sharkey            if (size == -1) return null;
604a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            final long[] values = new long[size];
605a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            for (int i = 0; i < values.length; i++) {
606a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                values[i] = in.readLong();
607a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            }
608a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            return values;
60975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
61075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
611a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        public static void writeLongArray(Parcel out, long[] values, int size) {
61263d27a9233fed934340231f438493746084a681dJeff Sharkey            if (values == null) {
61363d27a9233fed934340231f438493746084a681dJeff Sharkey                out.writeInt(-1);
61463d27a9233fed934340231f438493746084a681dJeff Sharkey                return;
615a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            }
616a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            if (size > values.length) {
617a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                throw new IllegalArgumentException("size larger than length");
618a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            }
619a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            out.writeInt(size);
620a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            for (int i = 0; i < size; i++) {
62163d27a9233fed934340231f438493746084a681dJeff Sharkey                out.writeLong(values[i]);
622a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            }
62375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
62475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
62575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
62675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey}
627