diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index 78f64e08d967e44282ebd1a6798275f04d81cd36..fa58fb09ee5dc080d8ae8183d2a273ff9f80918b 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -74,20 +74,18 @@ public class DictionaryFacilitatorForSuggest {
         // TODO: Remove sub dictionary members and use mSubDictMap.
         public final ContactsBinaryDictionary mContactsDictionary;
         public final UserBinaryDictionary mUserDictionary;
-        public final UserHistoryDictionary mUserHistoryDictionary;
         public final PersonalizationDictionary mPersonalizationDictionary;
 
         public Dictionaries() {
             mLocale = null;
             mContactsDictionary = null;
             mUserDictionary = null;
-            mUserHistoryDictionary = null;
             mPersonalizationDictionary = null;
         }
 
         public Dictionaries(final Locale locale, final Dictionary mainDict,
             final ContactsBinaryDictionary contactsDict, final UserBinaryDictionary userDict,
-            final UserHistoryDictionary userHistoryDict,
+            final ExpandableBinaryDictionary userHistoryDict,
             final PersonalizationDictionary personalizationDict) {
             mLocale = locale;
             // Main dictionary can be asynchronously loaded.
@@ -96,8 +94,7 @@ public class DictionaryFacilitatorForSuggest {
             setSubDict(Dictionary.TYPE_CONTACTS, mContactsDictionary);
             mUserDictionary = userDict;
             setSubDict(Dictionary.TYPE_USER, mUserDictionary);
-            mUserHistoryDictionary = userHistoryDict;
-            setSubDict(Dictionary.TYPE_USER_HISTORY, mUserHistoryDictionary);
+            setSubDict(Dictionary.TYPE_USER_HISTORY, userHistoryDict);
             mPersonalizationDictionary = personalizationDict;
             setSubDict(Dictionary.TYPE_PERSONALIZATION, mPersonalizationDictionary);
         }
@@ -193,9 +190,9 @@ public class DictionaryFacilitatorForSuggest {
         }
 
         // Open or move user history dictionary.
-        final UserHistoryDictionary newUserHistoryDict;
+        final ExpandableBinaryDictionary newUserHistoryDict;
         if (!closeUserHistoryDictionary && mDictionaries.hasDict(Dictionary.TYPE_USER_HISTORY)) {
-            newUserHistoryDict = mDictionaries.mUserHistoryDictionary;
+            newUserHistoryDict = mDictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
         } else if (usePersonalizedDicts) {
             newUserHistoryDict = PersonalizationHelper.getUserHistoryDictionary(context, newLocale);
         } else {
@@ -353,7 +350,7 @@ public class DictionaryFacilitatorForSuggest {
         final PersonalizationDictionary personalizationDict =
                 mDictionaries.mPersonalizationDictionary;
         if (personalizationDict != null) {
-            personalizationDict.flush();
+            personalizationDict.asyncFlushBinaryDictionary();
         }
     }
 
@@ -391,7 +388,9 @@ public class DictionaryFacilitatorForSuggest {
     public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
             final String previousWord, final int timeStampInSeconds) {
         final Dictionaries dictionaries = mDictionaries;
-        if (!dictionaries.hasDict(Dictionary.TYPE_USER_HISTORY)) {
+        final ExpandableBinaryDictionary userHistoryDictionary =
+                dictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
+        if (userHistoryDictionary != null) {
             return;
         }
         final int maxFreq = getMaxFrequency(suggestion);
@@ -433,14 +432,15 @@ public class DictionaryFacilitatorForSuggest {
         // We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
         // We don't add words with 0-frequency (assuming they would be profanity etc.).
         final boolean isValid = maxFreq > 0;
-        dictionaries.mUserHistoryDictionary.addToDictionary(
-                previousWord, secondWord, isValid, timeStampInSeconds);
+        UserHistoryDictionary.addToDictionary(userHistoryDictionary, previousWord, secondWord,
+                isValid, timeStampInSeconds);
     }
 
     public void cancelAddingUserHistory(final String previousWord, final String committedWord) {
-        final UserHistoryDictionary userHistoryDictionary = mDictionaries.mUserHistoryDictionary;
+        final ExpandableBinaryDictionary userHistoryDictionary =
+                mDictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
         if (userHistoryDictionary != null) {
-            userHistoryDictionary.cancelAddingUserHistory(previousWord, committedWord);
+            userHistoryDictionary.removeBigramDynamically(previousWord, committedWord);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 89fa819c1456fef4d58988647fffc36aba5eb3af..4077d12b349b78c63985727a84b586fb25131faa 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -298,7 +298,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     /**
      * Dynamically adds a word unigram to the dictionary. May overwrite an existing entry.
      */
-    protected void addWordDynamically(final String word, final int frequency,
+    public void addWordDynamically(final String word, final int frequency,
             final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord,
             final boolean isBlacklisted, final int timestamp) {
         reloadDictionaryIfRequired();
@@ -325,7 +325,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     /**
      * Dynamically adds a word bigram in the dictionary. May overwrite an existing entry.
      */
-    protected void addBigramDynamically(final String word0, final String word1,
+    public void addBigramDynamically(final String word0, final String word1,
             final int frequency, final int timestamp) {
         reloadDictionaryIfRequired();
         ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
@@ -348,7 +348,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     /**
      * Dynamically remove a word bigram in the dictionary.
      */
-    protected void removeBigramDynamically(final String word0, final String word1) {
+    public void removeBigramDynamically(final String word0, final String word1) {
         reloadDictionaryIfRequired();
         ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
             @Override
@@ -634,7 +634,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     /**
      * Flush binary dictionary to dictionary file.
      */
-    protected void asyncFlushBinaryDictionary() {
+    public void asyncFlushBinaryDictionary() {
         final Runnable newTask = new Runnable() {
             @Override
             public void run() {
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 46862c1c0b4465be9091d989919754bab6bcb560..35b4ccd401cb19cd2559a604a81fe012a5639e9e 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -65,12 +65,8 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
             dumpAllWordsForDebug();
         }
         // Flush pending writes.
-        flush();
-        super.close();
-    }
-
-    public void flush() {
         asyncFlushBinaryDictionary();
+        super.close();
     }
 
     @Override
@@ -103,33 +99,6 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
         addMultipleDictionaryEntriesDynamically(languageModelParams, callback);
     }
 
-    /**
-     * Pair will be added to the decaying dictionary.
-     *
-     * The first word may be null. That means we don't know the context, in other words,
-     * it's only a unigram. The first word may also be an empty string : this means start
-     * context, as in beginning of a sentence for example.
-     * The second word may not be null (a NullPointerException would be thrown).
-     */
-    public void addToDictionary(final String word0, final String word1, final boolean isValid,
-            final int timestamp) {
-        if (word1.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH ||
-                (word0 != null && word0.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH)) {
-            return;
-        }
-        final int frequency = isValid ?
-                FREQUENCY_FOR_WORDS_IN_DICTS : FREQUENCY_FOR_WORDS_NOT_IN_DICTS;
-        addWordDynamically(word1, frequency, null /* shortcutTarget */, 0 /* shortcutFreq */,
-                false /* isNotAWord */, false /* isBlacklisted */, timestamp);
-        // Do not insert a word as a bigram of itself
-        if (word1.equals(word0)) {
-            return;
-        }
-        if (null != word0) {
-            addBigramDynamically(word0, word1, frequency, timestamp);
-        }
-    }
-
     @Override
     protected void loadInitialContentsLocked() {
         // No initial contents.
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index 504e9b2f34b0f69429a694217517b1bb3531a74f..8a29c354d5ecacdb276696f39915d272a5ef19cf 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -18,7 +18,9 @@ package com.android.inputmethod.latin.personalization;
 
 import android.content.Context;
 
+import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.Dictionary;
+import com.android.inputmethod.latin.ExpandableBinaryDictionary;
 
 import java.io.File;
 import java.util.Locale;
@@ -40,13 +42,36 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas
                 dictFile);
     }
 
-    public void cancelAddingUserHistory(final String word0, final String word1) {
-        removeBigramDynamically(word0, word1);
-    }
-
     @Override
     public boolean isValidWord(final String word) {
         // Strings out of this dictionary should not be considered existing words.
         return false;
     }
+
+    /**
+     * Pair will be added to the user history dictionary.
+     *
+     * The first word may be null. That means we don't know the context, in other words,
+     * it's only a unigram. The first word may also be an empty string : this means start
+     * context, as in beginning of a sentence for example.
+     * The second word may not be null (a NullPointerException would be thrown).
+     */
+    public static void addToDictionary(final ExpandableBinaryDictionary userHistoryDictionary,
+            final String word0, final String word1, final boolean isValid, final int timestamp) {
+        if (word1.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH ||
+                (word0 != null && word0.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH)) {
+            return;
+        }
+        final int frequency = isValid ?
+                FREQUENCY_FOR_WORDS_IN_DICTS : FREQUENCY_FOR_WORDS_NOT_IN_DICTS;
+        userHistoryDictionary.addWordDynamically(word1, frequency, null /* shortcutTarget */,
+                0 /* shortcutFreq */, false /* isNotAWord */, false /* isBlacklisted */, timestamp);
+        // Do not insert a word as a bigram of itself
+        if (word1.equals(word0)) {
+            return;
+        }
+        if (null != word0) {
+            userHistoryDictionary.addBigramDynamically(word0, word1, frequency, timestamp);
+        }
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
index e054ab68cdff833142682ac18d6e7ef6699ecc4d..4399ba04f4804c1135dc4510eaa16ad17c6232df 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
@@ -111,7 +111,7 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
     private static void addToDict(final UserHistoryDictionary dict, final List<String> words) {
         String prevWord = null;
         for (String word : words) {
-            dict.addToDictionary(prevWord, word, true,
+            UserHistoryDictionary.addToDictionary(dict, prevWord, word, true,
                     (int)TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()));
             prevWord = word;
         }
@@ -262,7 +262,7 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
         dict.waitAllTasksForTests();
         String prevWord = null;
         for (final String word : words) {
-            dict.addToDictionary(prevWord, word, true, mCurrentTime);
+            UserHistoryDictionary.addToDictionary(dict, prevWord, word, true, mCurrentTime);
             prevWord = word;
             assertTrue(dict.isInUnderlyingBinaryDictionaryForTests(word));
         }