1cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal/*
2cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal * Copyright (C) 2016 The Android Open Source Project
3cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal *
4cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal * Licensed under the Apache License, Version 2.0 (the "License");
5cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal * you may not use this file except in compliance with the License.
6cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal * You may obtain a copy of the License at
7cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal *
8cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal *      http://www.apache.org/licenses/LICENSE-2.0
9cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal *
10cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal * Unless required by applicable law or agreed to in writing, software
11cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal * distributed under the License is distributed on an "AS IS" BASIS,
12cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal * See the License for the specific language governing permissions and
14cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal * limitations under the License.
15cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal */
16cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal
17cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawalpackage com.android.server.wifi.util;
18cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal
19cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawalimport java.util.ArrayList;
20cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal
21cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal/**
22cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal * A ring buffer where each element of the ring is itself a byte array.
23cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal */
24cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawalpublic class ByteArrayRingBuffer {
25cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    private ArrayList<byte[]> mArrayList;
26ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal    private int mMaxBytes;
27cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    private int mBytesUsed;
28cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal
29cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    /**
30cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * Creates a ring buffer that holds at most |maxBytes| of data. The overhead for each element
31cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * is not included in this limit.
32ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal     * @param maxBytes upper bound on the amount of data to hold
33cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     */
34cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    public ByteArrayRingBuffer(int maxBytes) {
35ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        if (maxBytes < 1) {
36ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal            throw new IllegalArgumentException();
37ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        }
38cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal        mArrayList = new ArrayList<byte[]>();
39cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal        mMaxBytes = maxBytes;
40cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal        mBytesUsed = 0;
41cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    }
42cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal
43cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    /**
44cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * Adds |newData| to the ring buffer. Removes existing entries to make room, if necessary.
45cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * Existing entries are removed in FIFO order.
46cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * <p><b>Note:</b> will fail if |newData| itself exceeds the size limit for this buffer.
47cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * Will first remove all existing entries in this case. (This guarantees that the ring buffer
48cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * always represents a contiguous sequence of data.)
49cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * @param newData data to be added to the ring
50cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * @return true if the data was added
51cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     */
52cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    public boolean appendBuffer(byte[] newData) {
53ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        pruneToSize(mMaxBytes - newData.length);
54cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal        if (mBytesUsed + newData.length > mMaxBytes) {
55cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal            return false;
56cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal        }
57cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal
58cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal        mArrayList.add(newData);
59cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal        mBytesUsed += newData.length;
60cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal        return true;
61cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    }
62cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal
63cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    /**
64cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * Returns the |i|-th element of the ring. The element retains its position in the ring.
65cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * @param i
66cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * @return the requested element
67cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     */
68cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    public byte[] getBuffer(int i) {
69cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal        return mArrayList.get(i);
70cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    }
71cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal
72cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    /**
73cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * Returns the number of elements present in the ring.
74cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     * @return the number of elements present
75cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal     */
76cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    public int getNumBuffers() {
77cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal        return mArrayList.size();
78cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal    }
79ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal
80ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal    /**
81ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal     * Resize the buffer, removing existing data if necessary.
82ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal     * @param maxBytes upper bound on the amount of data to hold
83ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal     */
84ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal    public void resize(int maxBytes) {
85ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        pruneToSize(maxBytes);
86ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        mMaxBytes = maxBytes;
87ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal    }
88ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal
89ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal    private void pruneToSize(int sizeBytes) {
90ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        int newBytesUsed = mBytesUsed;
91ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        int i = 0;
92ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        while (i < mArrayList.size() && newBytesUsed > sizeBytes) {
93ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal            newBytesUsed -= mArrayList.get(i).length;
94ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal            i++;
95ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        }
96ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        mArrayList.subList(0, i).clear();
97ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal        mBytesUsed = newBytesUsed;
98ca0bac5826ab430d1b765b201a609f7bc38401eemukesh agrawal    }
99cc84bc6179db408b1e45168d43e10ba0ab089fcamukesh agrawal}
100