Kill the StringBuilderPool.

The intention may have been nice originally but these end up
being copied anyway :/
Let's remove them now, and in a later change, just keep
references to the created objects.

Change-Id: Ifba8357c20384f9eb40cd916665ed1fc6dc8cab1
diff --git a/java/src/com/android/inputmethod/latin/StringBuilderPool.java b/java/src/com/android/inputmethod/latin/StringBuilderPool.java
deleted file mode 100644
index a663ed4..0000000
--- a/java/src/com/android/inputmethod/latin/StringBuilderPool.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.latin;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A pool of string builders to be used from anywhere.
- */
-public class StringBuilderPool {
-    // Singleton
-    private static final StringBuilderPool sInstance = new StringBuilderPool();
-    private static final boolean DEBUG = false;
-    private StringBuilderPool() {}
-    // TODO: Make this a normal array with a size of 20, or a ConcurrentQueue
-    private final List<StringBuilder> mPool =
-            Collections.synchronizedList(new ArrayList<StringBuilder>());
-
-    public static StringBuilder getStringBuilder(final int initialSize) {
-        // TODO: although the pool is synchronized, the following is not thread-safe.
-        // Two threads entering this at the same time could take the same size of the pool and the
-        // second to attempt removing this index from the pool would crash with an
-        // IndexOutOfBoundsException.
-        // At the moment this pool is only used in Suggest.java and only in one thread so it's
-        // okay. The simplest thing to do here is probably to replace the ArrayList with a
-        // ConcurrentQueue.
-        final int poolSize = sInstance.mPool.size();
-        final StringBuilder sb = poolSize > 0 ? (StringBuilder) sInstance.mPool.remove(poolSize - 1)
-                : new StringBuilder(initialSize);
-        sb.setLength(0);
-        return sb;
-    }
-
-    public static void recycle(final StringBuilder garbage) {
-        if (DEBUG) {
-            final int gid = garbage.hashCode();
-            for (final StringBuilder q : sInstance.mPool) {
-                if (gid == q.hashCode()) throw new RuntimeException("Duplicate id " + gid);
-            }
-        }
-        sInstance.mPool.add(garbage);
-    }
-
-    public static void ensureCapacity(final int capacity, final int initialSize) {
-        for (int i = sInstance.mPool.size(); i < capacity; ++i) {
-            final StringBuilder sb = new StringBuilder(initialSize);
-            sInstance.mPool.add(sb);
-        }
-    }
-
-    public static int getSize() {
-        return sInstance.mPool.size();
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index 81c3b4e..7b34cae 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -142,7 +142,7 @@
             for (int j = 0; j < i; j++) {
                 CharSequence previous = suggestions.get(j);
                 if (TextUtils.equals(cur, previous)) {
-                    removeFromSuggestions(suggestions, i);
+                    suggestions.remove(i);
                     i--;
                     break;
                 }
@@ -151,14 +151,6 @@
         }
     }
 
-    private static void removeFromSuggestions(final ArrayList<CharSequence> suggestions,
-            final int index) {
-        final CharSequence garbage = suggestions.remove(index);
-        if (garbage instanceof StringBuilder) {
-            StringBuilderPool.recycle((StringBuilder)garbage);
-        }
-    }
-
     public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) {
         if (returnsNameInThisLocale) {
             return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale);
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index e04a4e8..f0bd7b1 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -98,7 +98,7 @@
     private int[] mBigramScores = new int[PREF_MAX_BIGRAMS];
 
     private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
-    ArrayList<CharSequence> mBigramSuggestions  = new ArrayList<CharSequence>();
+    private ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>();
     private CharSequence mConsideredWord;
 
     // TODO: Remove these member variables by passing more context to addWord() callback method
@@ -122,7 +122,6 @@
     private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) {
         mWhiteListDictionary = new WhitelistDictionary(context, locale);
         addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary);
-        StringBuilderPool.ensureCapacity(mPrefMaxSuggestions, getApproxMaxWordLength());
     }
 
     private void initAsynchronously(final Context context, final int dictionaryResId,
@@ -229,14 +228,13 @@
         mPrefMaxSuggestions = maxSuggestions;
         mScores = new int[mPrefMaxSuggestions];
         mBigramScores = new int[PREF_MAX_BIGRAMS];
-        collectGarbage(mSuggestions, mPrefMaxSuggestions);
-        StringBuilderPool.ensureCapacity(mPrefMaxSuggestions, getApproxMaxWordLength());
+        mSuggestions = new ArrayList<CharSequence>(mPrefMaxSuggestions);
     }
 
     private CharSequence capitalizeWord(boolean all, boolean first, CharSequence word) {
         if (TextUtils.isEmpty(word) || !(all || first)) return word;
         final int wordLength = word.length();
-        final StringBuilder sb = StringBuilderPool.getStringBuilder(getApproxMaxWordLength());
+        final StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
         // TODO: Must pay attention to locale when changing case.
         if (all) {
             sb.append(word.toString().toUpperCase());
@@ -250,12 +248,7 @@
     }
 
     protected void addBigramToSuggestions(CharSequence bigram) {
-        // TODO: Try to be a little more shrewd with resource allocation.
-        // At the moment we copy this object because the StringBuilders are pooled (see
-        // StringBuilderPool.java) and when we are finished using mSuggestions and
-        // mBigramSuggestions we will take everything from both and insert them back in the
-        // pool, so we can't allow the same object to be in both lists at the same time.
-        final StringBuilder sb = StringBuilderPool.getStringBuilder(getApproxMaxWordLength());
+        final StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
         sb.append(bigram);
         mSuggestions.add(sb);
     }
@@ -266,7 +259,7 @@
         mIsFirstCharCapitalized = false;
         mIsAllUpperCase = false;
         mTrailingSingleQuotesCount = 0;
-        collectGarbage(mSuggestions, mPrefMaxSuggestions);
+        mSuggestions = new ArrayList<CharSequence>(mPrefMaxSuggestions);
         Arrays.fill(mScores, 0);
 
         // Treating USER_TYPED as UNIGRAM suggestion for logging now.
@@ -274,7 +267,7 @@
         mConsideredWord = "";
 
         Arrays.fill(mBigramScores, 0);
-        collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS);
+        mBigramSuggestions = new ArrayList<CharSequence>(PREF_MAX_BIGRAMS);
 
         CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase();
         if (mMainDict != null && mMainDict.isValidWord(lowerPrevWord)) {
@@ -305,7 +298,7 @@
         mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
         mIsAllUpperCase = wordComposer.isAllUpperCase();
         mTrailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount();
-        collectGarbage(mSuggestions, mPrefMaxSuggestions);
+        mSuggestions = new ArrayList<CharSequence>(mPrefMaxSuggestions);
         Arrays.fill(mScores, 0);
 
         final String typedWord = wordComposer.getTypedWord();
@@ -328,7 +321,7 @@
         if (wordComposer.size() <= 1 && (correctionMode == CORRECTION_FULL_BIGRAM)) {
             // At first character typed, search only the bigrams
             Arrays.fill(mBigramScores, 0);
-            collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS);
+            mBigramSuggestions = new ArrayList<CharSequence>(PREF_MAX_BIGRAMS);
 
             if (!TextUtils.isEmpty(prevWordForBigram)) {
                 CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase();
@@ -542,7 +535,7 @@
 
         System.arraycopy(sortedScores, pos, sortedScores, pos + 1, prefMaxSuggestions - pos - 1);
         sortedScores[pos] = score;
-        final StringBuilder sb = StringBuilderPool.getStringBuilder(getApproxMaxWordLength());
+        final StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
         // TODO: Must pay attention to locale when changing case.
         if (mIsAllUpperCase) {
             sb.append(new String(word, offset, length).toUpperCase());
@@ -559,10 +552,7 @@
         }
         suggestions.add(pos, sb);
         if (suggestions.size() > prefMaxSuggestions) {
-            final CharSequence garbage = suggestions.remove(prefMaxSuggestions);
-            if (garbage instanceof StringBuilder) {
-                StringBuilderPool.recycle((StringBuilder)garbage);
-            }
+            suggestions.remove(prefMaxSuggestions);
         } else {
             LatinImeLogger.onAddSuggestedWord(sb.toString(), dicTypeId, dataTypeForLog);
         }
@@ -589,24 +579,6 @@
         return -1;
     }
 
-    private static void collectGarbage(ArrayList<CharSequence> suggestions,
-            int prefMaxSuggestions) {
-        int poolSize = StringBuilderPool.getSize();
-        int garbageSize = suggestions.size();
-        while (poolSize < prefMaxSuggestions && garbageSize > 0) {
-            final CharSequence garbage = suggestions.get(garbageSize - 1);
-            if (garbage instanceof StringBuilder) {
-                StringBuilderPool.recycle((StringBuilder)garbage);
-                poolSize++;
-            }
-            garbageSize--;
-        }
-        if (poolSize == prefMaxSuggestions + 1) {
-            Log.w("Suggest", "String pool got too big: " + poolSize);
-        }
-        suggestions.clear();
-    }
-
     public void close() {
         final Set<Dictionary> dictionaries = new HashSet<Dictionary>();
         dictionaries.addAll(mUnigramDictionaries.values());