diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 16a563bcb54f8b442b4ef19907a059dc127f9d56..6b6ec2b4502b93e01aa658285733e3b8bdb89b80 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -107,9 +107,9 @@ public class BinaryDictionary extends Dictionary {
     }
 
     @Override
-    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback) {
-        if (mNativeDict == 0) return;
+    public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+            final CharSequence previousWord, final WordCallback callback) {
+        if (mNativeDict == 0) return null;
 
         int[] codePoints = StringUtils.toCodePointArray(previousWord.toString());
         Arrays.fill(mOutputChars_bigrams, (char) 0);
@@ -142,12 +142,14 @@ public class BinaryDictionary extends Dictionary {
             }
         }
         Utils.addAllSuggestions(mDicTypeId, Dictionary.BIGRAM, suggestions, callback);
+        return suggestions;
     }
 
     // proximityInfo and/or prevWordForBigrams may not be null.
     @Override
-    public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
-            final WordCallback callback, final ProximityInfo proximityInfo) {
+    public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+            final CharSequence prevWordForBigrams, final WordCallback callback,
+            final ProximityInfo proximityInfo) {
         final int count = getSuggestions(codes, prevWordForBigrams, proximityInfo, mOutputChars,
                 mScores, mSpaceIndices);
 
@@ -167,6 +169,7 @@ public class BinaryDictionary extends Dictionary {
             }
         }
         Utils.addAllSuggestions(mDicTypeId, Dictionary.UNIGRAM, suggestions, callback);
+        return suggestions;
     }
 
     /* package for test */ boolean isValidDictionary() {
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 10e511eaff82c180664ed6593b0acdc1cef08f0b..2a02603ca6ca3ae34973ec2b22fd7ee5d83ac508 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -120,12 +120,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
         }
     }
 
-    @Override
-    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback) {
-        super.getBigrams(codes, previousWord, callback);
-    }
-
     private boolean useFirstLastBigramsForLocale(Locale locale) {
         // TODO: Add firstname/lastname bigram rules for other languages.
         if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index c75e55d80f0d1eb1ecfa740f06350a54c535242f..55913b8eb987800dfbeca82014845c164ba44cf5 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -17,6 +17,9 @@
 package com.android.inputmethod.latin;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.ArrayList;
 
 /**
  * Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
@@ -61,9 +64,10 @@ public abstract class Dictionary {
      * @param prevWordForBigrams the previous word, or null if none
      * @param callback the callback object to send matched words to as possible candidates
      * @param proximityInfo the object for key proximity. May be ignored by some implementations.
+     * @return the list of suggestions
      * @see WordCallback#addWord(char[], int, int, int, int, int)
      */
-    abstract public void getWords(final WordComposer composer,
+    abstract public ArrayList<SuggestedWordInfo> getWords(final WordComposer composer,
             final CharSequence prevWordForBigrams, final WordCallback callback,
             final ProximityInfo proximityInfo);
 
@@ -73,11 +77,10 @@ public abstract class Dictionary {
      * @param composer the key sequence to match
      * @param previousWord the word before
      * @param callback the callback object to send possible word following previous word
+     * @return the list of suggestions
      */
-    public void getBigrams(final WordComposer composer, final CharSequence previousWord,
-            final WordCallback callback) {
-        // empty base implementation
-    }
+    public abstract ArrayList<SuggestedWordInfo> getBigrams(final WordComposer composer,
+            final CharSequence previousWord, final WordCallback callback);
 
     /**
      * Checks if the given word occurs in the dictionary
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 26c2e637e6a1130b3ab78f222eae83892200bc93..6b424f88f3fa97eb2d6385b1157b15055e09474b 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -17,9 +17,11 @@
 package com.android.inputmethod.latin;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 
 import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -50,17 +52,42 @@ public class DictionaryCollection extends Dictionary {
     }
 
     @Override
-    public void getWords(final WordComposer composer, final CharSequence prevWordForBigrams,
-            final WordCallback callback, final ProximityInfo proximityInfo) {
-        for (final Dictionary dict : mDictionaries)
-            dict.getWords(composer, prevWordForBigrams, callback, proximityInfo);
+    public ArrayList<SuggestedWordInfo> getWords(final WordComposer composer,
+            final CharSequence prevWordForBigrams, final WordCallback callback,
+            final ProximityInfo proximityInfo) {
+        final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries;
+        if (dictionaries.isEmpty()) return null;
+        // To avoid creating unnecessary objects, we get the list out of the first
+        // dictionary and add the rest to it if not null, hence the get(0)
+        ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getWords(composer,
+                prevWordForBigrams, callback, proximityInfo);
+        if (null == suggestions) suggestions = new ArrayList<SuggestedWordInfo>();
+        final int length = dictionaries.size();
+        for (int i = 0; i < length; ++ i) {
+            final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getWords(composer,
+                    prevWordForBigrams, callback, proximityInfo);
+            if (null != sugg) suggestions.addAll(sugg);
+        }
+        return suggestions;
     }
 
     @Override
-    public void getBigrams(final WordComposer composer, final CharSequence previousWord,
-            final WordCallback callback) {
-        for (final Dictionary dict : mDictionaries)
-            dict.getBigrams(composer, previousWord, callback);
+    public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer composer,
+            final CharSequence previousWord, final WordCallback callback) {
+        final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries;
+        if (dictionaries.isEmpty()) return null;
+        // To avoid creating unnecessary objects, we get the list out of the first
+        // dictionary and add the rest to it if not null, hence the get(0)
+        ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getBigrams(composer,
+                previousWord, callback);
+        if (null == suggestions) suggestions = new ArrayList<SuggestedWordInfo>();
+        final int length = dictionaries.size();
+        for (int i = 0; i < length; ++ i) {
+            final ArrayList<SuggestedWordInfo> sugg =
+                    dictionaries.get(i).getBigrams(composer, previousWord, callback);
+            if (null != sugg) suggestions.addAll(sugg);
+        }
+        return suggestions;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 41d4aa0617c55e4b15c9b6650604ae716234ea48..732bc180219d31eee6bea0a977fe30348f5ea2cc 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -19,6 +19,7 @@ import android.os.SystemClock;
 import android.util.Log;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.makedict.BinaryDictInputOutput;
 import com.android.inputmethod.latin.makedict.FusionDictionary;
 import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
@@ -194,13 +195,14 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     }
 
     @Override
-    public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
-            final WordCallback callback, final ProximityInfo proximityInfo) {
+    public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+            final CharSequence prevWordForBigrams, final WordCallback callback,
+            final ProximityInfo proximityInfo) {
         asyncReloadDictionaryIfRequired();
-        getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+        return getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
     }
 
-    protected final void getWordsInner(final WordComposer codes,
+    protected final ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
             final CharSequence prevWordForBigrams, final WordCallback callback,
             final ProximityInfo proximityInfo) {
         // Ensure that there are no concurrent calls to getWords. If there are, do nothing and
@@ -208,32 +210,35 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
         if (mLocalDictionaryController.tryLock()) {
             try {
                 if (mBinaryDictionary != null) {
-                    mBinaryDictionary.getWords(codes, prevWordForBigrams, callback, proximityInfo);
+                    return mBinaryDictionary.getWords(codes, prevWordForBigrams, callback,
+                            proximityInfo);
                 }
             } finally {
                 mLocalDictionaryController.unlock();
             }
         }
+        return null;
     }
 
     @Override
-    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback) {
+    public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+            final CharSequence previousWord, final WordCallback callback) {
         asyncReloadDictionaryIfRequired();
-        getBigramsInner(codes, previousWord, callback);
+        return getBigramsInner(codes, previousWord, callback);
     }
 
-    protected void getBigramsInner(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback) {
+    protected ArrayList<SuggestedWordInfo> getBigramsInner(final WordComposer codes,
+            final CharSequence previousWord, final WordCallback callback) {
         if (mLocalDictionaryController.tryLock()) {
             try {
                 if (mBinaryDictionary != null) {
-                    mBinaryDictionary.getBigrams(codes, previousWord, callback);
+                    return mBinaryDictionary.getBigrams(codes, previousWord, callback);
                 }
             } finally {
                 mLocalDictionaryController.unlock();
             }
         }
+        return null;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index d1eec6b7c01268bb0d6ce515a2549287798bb851..7d131a664ab9c43a8a8f71fcc44ad35e0a2ca9f9 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -248,20 +248,22 @@ public class ExpandableDictionary extends Dictionary {
     }
 
     @Override
-    public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
-            final WordCallback callback, final ProximityInfo proximityInfo) {
+    public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+            final CharSequence prevWordForBigrams, final WordCallback callback,
+            final ProximityInfo proximityInfo) {
         synchronized (mUpdatingLock) {
             // If we need to update, start off a background task
             if (mRequiresReload) startDictionaryLoadingTaskLocked();
             // Currently updating contacts, don't return any results.
-            if (mUpdatingDictionary) return;
+            if (mUpdatingDictionary) return null;
         }
         if (codes.size() >= BinaryDictionary.MAX_WORD_LENGTH) {
-            return;
+            return null;
         }
         final ArrayList<SuggestedWordInfo> suggestions =
                 getWordsInner(codes, prevWordForBigrams, proximityInfo);
         Utils.addAllSuggestions(mDicTypeId, Dictionary.UNIGRAM, suggestions, callback);
+        return suggestions;
     }
 
     protected final ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
@@ -611,13 +613,15 @@ public class ExpandableDictionary extends Dictionary {
     }
 
     @Override
-    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback) {
+    public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+            final CharSequence previousWord, final WordCallback callback) {
         if (!reloadDictionaryIfRequired()) {
             final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
             runBigramReverseLookUp(previousWord, suggestions);
             Utils.addAllSuggestions(mDicTypeId, Dictionary.BIGRAM, suggestions, callback);
+            return suggestions;
         }
+        return null;
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
index 673b54500849aea756dae203ade15c8fbef50bd8..d706022bd35cecd99a4e72d14c31a4303b203bad 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
@@ -19,7 +19,9 @@ package com.android.inputmethod.latin;
 import android.content.Context;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 
+import java.util.ArrayList;
 import java.util.Locale;
 
 public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryDictionary {
@@ -30,11 +32,11 @@ public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryD
     }
 
     @Override
-    public synchronized void getWords(final WordComposer codes,
+    public synchronized ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
             final CharSequence prevWordForBigrams, final WordCallback callback,
             final ProximityInfo proximityInfo) {
         syncReloadDictionaryIfRequired();
-        getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+        return getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
index 1606a34e077dbe95cf4ec39770a2fde724bb42ec..984e2e7071175d9f09c7fddc8d93a20284fc9f41 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
@@ -19,6 +19,9 @@ package com.android.inputmethod.latin;
 import android.content.Context;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.ArrayList;
 
 public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionary {
 
@@ -32,11 +35,11 @@ public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionar
     }
 
     @Override
-    public synchronized void getWords(final WordComposer codes,
+    public synchronized ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
             final CharSequence prevWordForBigrams, final WordCallback callback,
             final ProximityInfo proximityInfo) {
         syncReloadDictionaryIfRequired();
-        getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+        return getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
     }
 
     @Override