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