1 /* 2 * Copyright (C) 2011 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.ddmuilib.logcat; 18 19 import java.util.concurrent.ArrayBlockingQueue; 20 import java.util.concurrent.BlockingQueue; 21 22 /** 23 * Container for a list of log messages. The list of messages are 24 * maintained in a circular buffer (FIFO). 25 */ 26 public final class LogCatMessageList { 27 /** Preference key for size of the FIFO. */ 28 public static final String MAX_MESSAGES_PREFKEY = 29 "logcat.messagelist.max.size"; 30 31 /** Default value for max # of messages. */ 32 public static final int MAX_MESSAGES_DEFAULT = 5000; 33 34 private int mFifoSize; 35 private BlockingQueue<LogCatMessage> mQ; 36 private LogCatMessage[] mQArray; 37 38 /** 39 * Construct an empty message list. 40 * @param maxMessages capacity of the circular buffer 41 */ LogCatMessageList(int maxMessages)42 public LogCatMessageList(int maxMessages) { 43 mFifoSize = maxMessages; 44 45 mQ = new ArrayBlockingQueue<LogCatMessage>(mFifoSize); 46 mQArray = new LogCatMessage[mFifoSize]; 47 } 48 49 /** 50 * Resize the message list. 51 * @param n new size for the list 52 */ resize(int n)53 public synchronized void resize(int n) { 54 mFifoSize = n; 55 56 if (mFifoSize > mQ.size()) { 57 /* if resizing to a bigger fifo, we can copy over all elements from the current mQ */ 58 mQ = new ArrayBlockingQueue<LogCatMessage>(mFifoSize, true, mQ); 59 } else { 60 /* for a smaller fifo, copy over the last n entries */ 61 LogCatMessage[] curMessages = mQ.toArray(new LogCatMessage[mQ.size()]); 62 mQ = new ArrayBlockingQueue<LogCatMessage>(mFifoSize); 63 for (int i = curMessages.length - mFifoSize; i < curMessages.length; i++) { 64 mQ.offer(curMessages[i]); 65 } 66 } 67 68 mQArray = new LogCatMessage[mFifoSize]; 69 } 70 71 /** 72 * Append a message to the list. If the list is full, the first 73 * message will be popped off of it. 74 * @param m log to be inserted 75 */ appendMessage(final LogCatMessage m)76 public synchronized void appendMessage(final LogCatMessage m) { 77 if (mQ.remainingCapacity() == 0) { 78 /* make space by removing the first entry */ 79 mQ.poll(); 80 } 81 mQ.offer(m); 82 } 83 84 /** 85 * Returns the number of additional elements that this queue can 86 * ideally (in the absence of memory or resource constraints) 87 * accept without blocking. 88 * @return the remaining capacity 89 */ remainingCapacity()90 public synchronized int remainingCapacity() { 91 return mQ.remainingCapacity(); 92 } 93 94 /** 95 * Clear all messages in the list. 96 */ clear()97 public synchronized void clear() { 98 mQ.clear(); 99 } 100 101 /** 102 * Obtain all the messages currently present in the list. 103 * @return array containing all the log messages 104 */ toArray()105 public Object[] toArray() { 106 if (mQ.size() == mFifoSize) { 107 /* 108 * Once the queue is full, it stays full until the user explicitly clears 109 * all the logs. Optimize for this case by not reallocating the array. 110 */ 111 return mQ.toArray(mQArray); 112 } 113 return mQ.toArray(); 114 } 115 } 116