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.ArrayList; 20 import java.util.List; 21 import java.util.concurrent.ArrayBlockingQueue; 22 import java.util.concurrent.BlockingQueue; 23 24 /** 25 * Container for a list of log messages. The list of messages are 26 * maintained in a circular buffer (FIFO). 27 */ 28 public final class LogCatMessageList { 29 /** Preference key for size of the FIFO. */ 30 public static final String MAX_MESSAGES_PREFKEY = 31 "logcat.messagelist.max.size"; 32 33 /** Default value for max # of messages. */ 34 public static final int MAX_MESSAGES_DEFAULT = 5000; 35 36 private int mFifoSize; 37 private BlockingQueue<LogCatMessage> mQ; 38 39 /** 40 * Construct an empty message list. 41 * @param maxMessages capacity of the circular buffer 42 */ 43 public LogCatMessageList(int maxMessages) { 44 mFifoSize = maxMessages; 45 46 mQ = new ArrayBlockingQueue<LogCatMessage>(mFifoSize); 47 } 48 49 /** 50 * Resize the message list. 51 * @param n new size for the list 52 */ 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 69 /** 70 * Append a message to the list. If the list is full, the first 71 * message will be popped off of it. 72 * @param m log to be inserted 73 */ 74 public synchronized void appendMessages(final List<LogCatMessage> messages) { 75 ensureSpace(messages.size()); 76 for (LogCatMessage m: messages) { 77 mQ.offer(m); 78 } 79 } 80 81 /** 82 * Ensure that there is sufficient space for given number of messages. 83 * @return list of messages that were deleted to create additional space. 84 */ 85 public synchronized List<LogCatMessage> ensureSpace(int messageCount) { 86 List<LogCatMessage> l = new ArrayList<LogCatMessage>(messageCount); 87 88 while (mQ.remainingCapacity() < messageCount) { 89 l.add(mQ.poll()); 90 } 91 92 return l; 93 } 94 95 /** 96 * Returns the number of additional elements that this queue can 97 * ideally (in the absence of memory or resource constraints) 98 * accept without blocking. 99 * @return the remaining capacity 100 */ 101 public synchronized int remainingCapacity() { 102 return mQ.remainingCapacity(); 103 } 104 105 /** Clear all messages in the list. */ 106 public synchronized void clear() { 107 mQ.clear(); 108 } 109 110 /** Obtain a copy of the message list. */ 111 public synchronized List<LogCatMessage> getAllMessages() { 112 return new ArrayList<LogCatMessage>(mQ); 113 } 114 } 115