Merge "Extract sudden jumping touch event hack into separate class"
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index f55e9bf..5cd995b 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -35,7 +35,7 @@
     <!-- Label for "switch to more symbol" modifier key.  Must be short to fit on key! -->
     <string name="label_to_more_symbol_key">= \\ &lt;</string>
     <!-- Label for "switch to more symbol" modifier key on tablets.  Must be short to fit on key! -->
-    <string name="label_to_more_symbol_for_tablet_key">\\ ^ [ {</string>
+    <string name="label_to_more_symbol_for_tablet_key">~ \\ {</string>
 
     <!-- Label for "Tab" key.  Must be short to fit on key! -->
     <string name="label_tab_key">Tab</string>
diff --git a/java/res/xml-sw600dp/kbd_key_styles.xml b/java/res/xml-sw600dp/kbd_key_styles.xml
index 15a3d1d..b93d300 100644
--- a/java/res/xml-sw600dp/kbd_key_styles.xml
+++ b/java/res/xml-sw600dp/kbd_key_styles.xml
@@ -118,19 +118,4 @@
         latin:keyLabelOption="fontNormal|hasPopupHint"
         latin:keyOutputText="@string/keylabel_for_popular_domain"
         latin:popupCharacters="@string/alternates_for_popular_domain" />
-    <switch>
-        <case
-            latin:passwordInput="true"
-        >
-            <key-style
-                latin:styleName="nonPasswordSymbolKeyStyle"
-                latin:enabled="false" />
-        </case>
-        <!-- latin:passwordInput="false" -->
-        <default>
-            <key-style
-                latin:styleName="nonPasswordSymbolKeyStyle"
-                latin:enabled="true" />
-        </default>
-    </switch>
 </merge>
diff --git a/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml b/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml
index 2909acb..c5143d9 100644
--- a/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml
+++ b/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml
@@ -33,28 +33,21 @@
         <Key
             latin:keyLabel="|" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="•"
             latin:popupCharacters="♪,♥,♠,♦,♣" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="√" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="π"
             latin:popupCharacters="Π" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="÷" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="×" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="§"
             latin:popupCharacters="¶" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="Δ" />
         <Key
             latin:keyStyle="deleteKeyStyle"
@@ -65,27 +58,21 @@
         latin:keyWidth="9.0%p"
     >
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="£"
             latin:keyXPos="4.5%p" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="¢" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="€" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="¥" />
         <Key
             latin:keyLabel="^"
             latin:popupCharacters="↑,↓,←,→" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="°"
             latin:popupCharacters="′,″" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="±"
             latin:popupCharacters="∞" />
         <Key
@@ -106,26 +93,20 @@
         <Key
             latin:keyLabel="\\" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="©" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="®" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="™" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="℅" />
         <Key
             latin:keyLabel="[" />
         <Key
             latin:keyLabel="]" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="¡" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="¿" />
     </Row>
     <Row
diff --git a/java/res/xml-sw768dp/kbd_key_styles.xml b/java/res/xml-sw768dp/kbd_key_styles.xml
index 1711c42..7c74bb5 100644
--- a/java/res/xml-sw768dp/kbd_key_styles.xml
+++ b/java/res/xml-sw768dp/kbd_key_styles.xml
@@ -104,19 +104,4 @@
         latin:keyLabelOption="fontNormal|hasPopupHint"
         latin:keyOutputText="@string/keylabel_for_popular_domain"
         latin:popupCharacters="@string/alternates_for_popular_domain" />
-    <switch>
-        <case
-            latin:passwordInput="true"
-        >
-            <key-style
-                latin:styleName="nonPasswordSymbolKeyStyle"
-                latin:enabled="false" />
-        </case>
-        <!-- latin:passwordInput="false" -->
-        <default>
-            <key-style
-                latin:styleName="nonPasswordSymbolKeyStyle"
-                latin:enabled="true" />
-        </default>
-    </switch>
 </merge>
diff --git a/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml b/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml
index 1f43a0f..82bc4b2 100644
--- a/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml
+++ b/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml
@@ -37,28 +37,21 @@
         <Key
             latin:keyLabel="|" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="•"
             latin:popupCharacters="♪,♥,♠,♦,♣" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="√" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="π"
             latin:popupCharacters="Π" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="÷" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="×" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="§"
             latin:popupCharacters="¶" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="Δ" />
         <Key
             latin:keyStyle="deleteKeyStyle"
@@ -73,26 +66,20 @@
             latin:keyLabelOption="alignLeft"
             latin:keyWidth="11.172%p" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="£" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="¢" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="€" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="¥" />
         <Key
             latin:keyLabel="^"
             latin:popupCharacters="↑,↓,←,→" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="°"
             latin:popupCharacters="′,″" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="±"
             latin:popupCharacters="∞" />
         <Key
@@ -113,26 +100,20 @@
         <Key
             latin:keyLabel="\\" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="©" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="®" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="™" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="℅" />
         <Key
             latin:keyLabel="[" />
         <Key
             latin:keyLabel="]" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="¡" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="¿" />
         <Key
             latin:keyStyle="backFromMoreSymbolKeyStyle"
diff --git a/java/res/xml/kbd_key_styles.xml b/java/res/xml/kbd_key_styles.xml
index 5612251..4846898 100644
--- a/java/res/xml/kbd_key_styles.xml
+++ b/java/res/xml/kbd_key_styles.xml
@@ -215,29 +215,6 @@
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_symbol_key"
         latin:parentStyle="functionalKeyStyle" />
-    <switch>
-        <case
-            latin:passwordInput="true"
-        >
-            <key-style
-                latin:styleName="nonPasswordSymbolKeyStyle"
-                latin:enabled="false" />
-            <key-style
-                latin:styleName="nonPasswordFunctionalKeyStyle"
-                latin:enabled="false"
-                latin:parentStyle="functionalKeyStyle" />
-        </case>
-        <!-- latin:passwordInput="false" -->
-        <default>
-            <key-style
-                latin:styleName="nonPasswordSymbolKeyStyle"
-                latin:enabled="true" />
-            <key-style
-                latin:styleName="nonPasswordFunctionalKeyStyle"
-                latin:enabled="true"
-                latin:parentStyle="functionalKeyStyle" />
-        </default>
-    </switch>
     <key-style
         latin:styleName="punctuationKeyStyle"
         latin:keyLabel="."
diff --git a/java/res/xml/kbd_rows_symbols_shift.xml b/java/res/xml/kbd_rows_symbols_shift.xml
index d523415..ff272f1 100644
--- a/java/res/xml/kbd_rows_symbols_shift.xml
+++ b/java/res/xml/kbd_rows_symbols_shift.xml
@@ -33,21 +33,16 @@
         <Key
             latin:keyLabel="|" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="•"
             latin:popupCharacters="♪,♥,♠,♦,♣" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="√" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="π"
             latin:popupCharacters="Π" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="÷" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="×" />
         <Key
             latin:keyLabel="{" />
@@ -61,16 +56,12 @@
         <Key
             latin:keyStyle="nonSpecialBackgroundTabKeyStyle" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="£" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="¢" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="€" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="°"
             latin:popupCharacters="′,″" />
         <Key
@@ -95,16 +86,12 @@
             latin:keyWidth="15%p"
             latin:visualInsetsRight="1%p" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="™" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="®" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="©" />
         <Key
-            latin:keyStyle="nonPasswordSymbolKeyStyle"
             latin:keyLabel="¶"
             latin:popupCharacters="§" />
         <Key
diff --git a/java/res/xml/kbd_symbols_shift_row4.xml b/java/res/xml/kbd_symbols_shift_row4.xml
index 9cb453f..bcab19b 100644
--- a/java/res/xml/kbd_symbols_shift_row4.xml
+++ b/java/res/xml/kbd_symbols_shift_row4.xml
@@ -35,13 +35,13 @@
                 <Key
                     latin:keyLabel="„"
                     latin:popupCharacters="“,”,„,‟,«,»,‘,’,‚,‛"
-                    latin:keyStyle="nonPasswordFunctionalKeyStyle" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <Key
                     latin:keyStyle="spaceKeyStyle"
                     latin:keyWidth="50%p" />
                 <Key
                     latin:keyLabel="…"
-                    latin:keyStyle="nonPasswordFunctionalKeyStyle" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <Key
                     latin:keyStyle="returnKeyStyle"
                     latin:keyWidth="fillRight" />
@@ -57,14 +57,14 @@
                     latin:keyLabel="„"
                     latin:popupCharacters="“,”,„,‟,«,»,‘,’,‚,‛"
                     latin:keyWidth="9.2%p"
-                    latin:keyStyle="nonPasswordFunctionalKeyStyle" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <Key
                     latin:keyStyle="spaceKeyStyle"
                     latin:keyWidth="35.83%p" />
                 <Key
                     latin:keyLabel="…"
                     latin:keyWidth="9.2%p"
-                    latin:keyStyle="nonPasswordFunctionalKeyStyle" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <Key
                     latin:keyStyle="returnKeyStyle"
                     latin:keyWidth="fillRight" />
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 397b7b1..f56b523 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -295,12 +295,8 @@
             mY = y;
             mWidth = keyWidth - mHorizontalGap;
 
-            CharSequence[] popupCharacters = style.getTextArray(
+            final CharSequence[] popupCharacters = style.getTextArray(
                     keyAttr, R.styleable.Keyboard_Key_popupCharacters);
-            if (params.mId.mPasswordInput) {
-                popupCharacters = PopupCharactersParser.filterOut(
-                        res, popupCharacters, PopupCharactersParser.NON_ASCII_FILTER);
-            }
             // In Arabic symbol layouts, we'd like to keep digits in popup characters regardless of
             // config_digit_popup_characters_enabled.
             if (params.mId.isAlphabetKeyboard() && !res.getBoolean(
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java b/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java
index 032489e..7c5abe3 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java
@@ -196,13 +196,6 @@
         }
     };
 
-    public static final CodeFilter NON_ASCII_FILTER = new CodeFilter() {
-        @Override
-        public boolean shouldFilterOut(int code) {
-            return code < 0x20 || code > 0x7e;
-        }
-    };
-
     public static CharSequence[] filterOut(Resources res, CharSequence[] popupCharacters,
             CodeFilter filter) {
         if (popupCharacters == null || popupCharacters.length < 1) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index e72b43a..48bcd3b 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -113,7 +113,7 @@
     // Key events coming any faster than this are long-presses.
     private static final int QUICK_PRESS = 200;
 
-    private static final int SCREEN_ORIENTATION_CHANGE_DETECTION_DELAY = 2;
+    private static final int START_INPUT_VIEW_DELAY_WHEN_SCREEN_ORIENTATION_STARTED = 10;
     private static final int ACCUMULATE_START_INPUT_VIEW_DELAY = 20;
     private static final int RESTORE_KEYBOARD_STATE_DELAY = 500;
 
@@ -198,8 +198,6 @@
 
     // Member variables for remembering the current device orientation.
     private int mDisplayOrientation;
-    private int mDisplayWidth;
-    private int mDisplayHeight;
 
     // Object for reacting to adding/removing a dictionary pack.
     private BroadcastReceiver mDictionaryPackInstallReceiver =
@@ -219,31 +217,10 @@
         private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5;
         private static final int MSG_SPACE_TYPED = 6;
         private static final int MSG_SET_BIGRAM_PREDICTIONS = 7;
-        private static final int MSG_CONFIRM_ORIENTATION_CHANGE = 8;
+        private static final int MSG_START_ORIENTATION_CHANGE = 8;
         private static final int MSG_START_INPUT_VIEW = 9;
         private static final int MSG_RESTORE_KEYBOARD_LAYOUT = 10;
 
-        private static class OrientationChangeArgs {
-            public final int mOldWidth;
-            public final int mOldHeight;
-            private int mRetryCount;
-
-            public OrientationChangeArgs(int oldw, int oldh) {
-                mOldWidth = oldw;
-                mOldHeight = oldh;
-                mRetryCount = 0;
-            }
-
-            public boolean hasTimedOut() {
-                mRetryCount++;
-                return mRetryCount >= 10;
-            }
-
-            public boolean hasOrientationChangeFinished(DisplayMetrics dm) {
-                return dm.widthPixels != mOldWidth && dm.heightPixels != mOldHeight;
-            }
-        }
-
         public UIHandler(LatinIME outerInstance) {
             super(outerInstance);
         }
@@ -291,18 +268,6 @@
                             (LatinKeyboard)msg.obj);
                 }
                 break;
-            case MSG_CONFIRM_ORIENTATION_CHANGE: {
-                final OrientationChangeArgs args = (OrientationChangeArgs)msg.obj;
-                final Resources res = latinIme.mResources;
-                final DisplayMetrics dm = res.getDisplayMetrics();
-                if (args.hasTimedOut() || args.hasOrientationChangeFinished(dm)) {
-                    latinIme.setDisplayGeometry(res.getConfiguration(), dm);
-                } else {
-                    // It seems orientation changing is on going.
-                    postConfirmOrientationChange(args);
-                }
-                break;
-            }
             case MSG_START_INPUT_VIEW:
                 latinIme.onStartInputView((EditorInfo)msg.obj, false);
                 break;
@@ -411,22 +376,16 @@
             }
         }
 
-        private void postConfirmOrientationChange(OrientationChangeArgs args) {
-            removeMessages(MSG_CONFIRM_ORIENTATION_CHANGE);
-            // Will confirm whether orientation change has finished or not again.
-            sendMessageDelayed(obtainMessage(MSG_CONFIRM_ORIENTATION_CHANGE, args),
-                    SCREEN_ORIENTATION_CHANGE_DETECTION_DELAY);
-        }
-
-        public void startOrientationChanging(int oldw, int oldh) {
-            postConfirmOrientationChange(new OrientationChangeArgs(oldw, oldh));
+        public void startOrientationChanging() {
+            sendMessageDelayed(obtainMessage(MSG_START_ORIENTATION_CHANGE),
+                    START_INPUT_VIEW_DELAY_WHEN_SCREEN_ORIENTATION_STARTED);
             final LatinIME latinIme = getOuterInstance();
             latinIme.mKeyboardSwitcher.getKeyboardState().save();
             postRestoreKeyboardLayout();
         }
 
         public boolean postStartInputView(EditorInfo attribute) {
-            if (hasMessages(MSG_CONFIRM_ORIENTATION_CHANGE) || hasMessages(MSG_START_INPUT_VIEW)) {
+            if (hasMessages(MSG_START_ORIENTATION_CHANGE) || hasMessages(MSG_START_INPUT_VIEW)) {
                 removeMessages(MSG_START_INPUT_VIEW);
                 // Postpone onStartInputView by ACCUMULATE_START_INPUT_VIEW_DELAY and see if
                 // orientation change has finished.
@@ -438,12 +397,6 @@
         }
     }
 
-    private void setDisplayGeometry(Configuration conf, DisplayMetrics metric) {
-        mDisplayOrientation = conf.orientation;
-        mDisplayWidth = metric.widthPixels;
-        mDisplayHeight = metric.heightPixels;
-    }
-
     @Override
     public void onCreate() {
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
@@ -481,7 +434,7 @@
             }
         }
 
-        setDisplayGeometry(res.getConfiguration(), res.getDisplayMetrics());
+        mDisplayOrientation = res.getConfiguration().orientation;
 
         // Register to receive ringer mode change and network state change.
         // Also receive installation and removal of a dictionary pack.
@@ -609,8 +562,9 @@
     public void onConfigurationChanged(Configuration conf) {
         mSubtypeSwitcher.onConfigurationChanged(conf);
         // If orientation changed while predicting, commit the change
-        if (conf.orientation != mDisplayOrientation) {
-            mHandler.startOrientationChanging(mDisplayWidth, mDisplayHeight);
+        if (mDisplayOrientation != conf.orientation) {
+            mDisplayOrientation = conf.orientation;
+            mHandler.startOrientationChanging();
             final InputConnection ic = getCurrentInputConnection();
             commitTyped(ic);
             if (ic != null) ic.finishComposingText(); // For voice input
diff --git a/java/src/com/android/inputmethod/latin/StringBuilderPool.java b/java/src/com/android/inputmethod/latin/StringBuilderPool.java
index 66f1237..a663ed4 100644
--- a/java/src/com/android/inputmethod/latin/StringBuilderPool.java
+++ b/java/src/com/android/inputmethod/latin/StringBuilderPool.java
@@ -26,12 +26,20 @@
 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
+    // 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);
@@ -40,6 +48,12 @@
     }
 
     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);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index e3cb698..29b6295 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -284,7 +284,14 @@
     }
 
     protected void addBigramToSuggestions(CharSequence bigram) {
-        mSuggestions.add(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());
+        sb.append(bigram);
+        mSuggestions.add(sb);
     }
 
     // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder