Merge "Fix a failing test."
diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
index 672759a..b44741c 100644
--- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
+++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
@@ -534,6 +534,7 @@
     @Override
     public void onPageScrolled(final int position, final float positionOffset,
             final int positionOffsetPixels) {
+        mEmojiPalettesAdapter.onPageScrolled();
         final Pair<Integer, Integer> newPos =
                 mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(position);
         final int newCategoryId = newPos.first;
@@ -718,6 +719,14 @@
             }
         }
 
+        public void onPageScrolled() {
+            // Make sure the delayed key-down event (highlight effect and haptic feedback) will be
+            // canceled.
+            final EmojiPageKeyboardView currentKeyboardView =
+                  mActiveKeyboardViews.get(mActivePosition);
+            currentKeyboardView.releaseCurrentKey();
+        }
+
         @Override
         public int getCount() {
             return mEmojiCategory.getTotalPageCountOfAllCategories();
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index a787ef1..d626ff9 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -29,7 +29,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.personalization.AccountUtils;
 import com.android.inputmethod.latin.utils.StringUtils;
 
@@ -73,8 +72,13 @@
     private final boolean mUseFirstLastBigrams;
 
     public ContactsBinaryDictionary(final Context context, final Locale locale) {
-        super(context, getDictNameWithLocale(NAME, locale), locale,
-                Dictionary.TYPE_CONTACTS, false /* isUpdatable */);
+        this(context, locale, null /* dictFile */);
+    }
+
+    public ContactsBinaryDictionary(final Context context, final Locale locale,
+            final File dictFile) {
+        super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_CONTACTS,
+                false /* isUpdatable */, dictFile);
         mLocale = locale;
         mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale);
         registerObserver(context);
@@ -84,12 +88,6 @@
         loadDictionary();
     }
 
-    // Dummy constructor for tests.
-    @UsedForTesting
-    public ContactsBinaryDictionary(final Context context, final Locale locale, final File file) {
-        this(context, locale);
-    }
-
     private synchronized void registerObserver(final Context context) {
         // Perform a managed query. The Activity will handle closing and requerying the cursor
         // when needed.
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index c2451ce..251583c 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -213,15 +213,10 @@
      * @param dictType the dictionary type, as a human-readable string
      * @param isUpdatable whether to support dynamically updating the dictionary. Please note that
      *        dynamic dictionary has negative effects on memory space and computation time.
+     * @param dictFile dictionary file path. if null, use default dictionary path based on
+     *        dictionary type.
      */
     public ExpandableBinaryDictionary(final Context context, final String dictName,
-            final Locale locale, final String dictType, final boolean isUpdatable) {
-        this(context, dictName, locale, dictType, isUpdatable,
-                new File(context.getFilesDir(), dictName + DICT_FILE_EXTENSION));
-    }
-
-    // Creates an instance that uses a given dictionary file.
-    public ExpandableBinaryDictionary(final Context context, final String dictName,
             final Locale locale, final String dictType, final boolean isUpdatable,
             final File dictFile) {
         super(dictType);
@@ -229,15 +224,17 @@
         mContext = context;
         mLocale = locale;
         mIsUpdatable = isUpdatable;
-        mDictFile = dictFile;
+        mDictFile = (dictFile != null) ? dictFile
+                : new File(context.getFilesDir(), dictName + DICT_FILE_EXTENSION);
         mBinaryDictionary = null;
         mDictNameDictionaryUpdateController = getDictionaryUpdateController(dictName);
         // Currently, only dynamic personalization dictionary is updatable.
         mDictionaryWriter = getDictionaryWriter(isUpdatable);
     }
 
-    protected static String getDictNameWithLocale(final String name, final Locale locale) {
-        return name + "." + locale.toString();
+    protected static String getDictName(final String name, final Locale locale,
+            final File dictFile) {
+        return dictFile != null ? dictFile.getName() : name + "." + locale.toString();
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 845bafe..e9468a2 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1731,13 +1731,7 @@
         final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1;
         p.println("  Keyboard mode = " + keyboardMode);
         final SettingsValues settingsValues = mSettings.getCurrent();
-        p.println("  mIsSuggestionsRequested = " + settingsValues.isSuggestionsRequested());
-        p.println("  mCorrectionEnabled=" + settingsValues.mCorrectionEnabled);
-        p.println("  isComposingWord=" + mInputLogic.mWordComposer.isComposingWord());
-        p.println("  mSoundOn=" + settingsValues.mSoundOn);
-        p.println("  mVibrateOn=" + settingsValues.mVibrateOn);
-        p.println("  mKeyPreviewPopupOn=" + settingsValues.mKeyPreviewPopupOn);
-        p.println("  inputAttributes=" + settingsValues.mInputAttributes);
+        p.println(settingsValues.dump());
         // TODO: Dump all settings values
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
index 9ccd9e4..801fb5b 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
@@ -28,12 +28,12 @@
     private final Object mLock = new Object();
 
     public SynchronouslyLoadedUserBinaryDictionary(final Context context, final Locale locale) {
-        this(context, locale, false);
+        this(context, locale, false /* alsoUseMoreRestrictiveLocales */);
     }
 
     public SynchronouslyLoadedUserBinaryDictionary(final Context context, final Locale locale,
             final boolean alsoUseMoreRestrictiveLocales) {
-        super(context, locale, alsoUseMoreRestrictiveLocales);
+        super(context, locale, alsoUseMoreRestrictiveLocales, null /* dictFile */);
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 8011247..2a195f5 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -28,7 +28,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.compat.UserDictionaryCompatUtils;
 import com.android.inputmethod.latin.utils.LocaleUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
@@ -78,19 +77,17 @@
     final public boolean mEnabled;
 
     public UserBinaryDictionary(final Context context, final Locale locale) {
-        this(context, locale, false);
+        this(context, locale, false /* alsoUseMoreRestrictiveLocales */, null /* dictFile */);
     }
 
-    // Dummy constructor for tests.
-    @UsedForTesting
-    public UserBinaryDictionary(final Context context, final Locale locale, final File file) {
-        this(context, locale);
+    public UserBinaryDictionary(final Context context, final Locale locale, final File dictFile) {
+        this(context, locale, false /* alsoUseMoreRestrictiveLocales */, dictFile);
     }
 
     public UserBinaryDictionary(final Context context, final Locale locale,
-            final boolean alsoUseMoreRestrictiveLocales) {
-        super(context, getDictNameWithLocale(NAME, locale), locale, Dictionary.TYPE_USER,
-                false /* isUpdatable */);
+            final boolean alsoUseMoreRestrictiveLocales, final File dictFile) {
+        super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_USER,
+                false /* isUpdatable */, dictFile);
         if (null == locale) throw new NullPointerException(); // Catch the error earlier
         final String localeStr = locale.toString();
         if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) {
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 6a7a336..9c74c24 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -52,21 +52,10 @@
     private final String mDictName;
 
     /* package */ DecayingExpandableBinaryDictionaryBase(final Context context,
-            final Locale locale, final String dictionaryType, final String dictName) {
-        super(context, dictName, locale, dictionaryType, true);
-        mLocale = locale;
-        mDictName = dictName;
-        if (mLocale != null && mLocale.toString().length() > 1) {
-            reloadDictionaryIfRequired();
-        }
-    }
-
-    // Creates an instance that uses a given dictionary file for testing.
-    @UsedForTesting
-    /* package */ DecayingExpandableBinaryDictionaryBase(final Context context,
-            final Locale locale, final String dictionaryType, final String dictName,
+            final String dictName, final Locale locale, final String dictionaryType,
             final File dictFile) {
-        super(context, dictName, locale, dictionaryType, true, dictFile);
+        super(context, getDictName(dictName, locale, dictFile), locale, dictionaryType,
+                true /* isUpdatable */, dictFile);
         mLocale = locale;
         mDictName = dictName;
         if (mLocale != null && mLocale.toString().length() > 1) {
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
index 6526148..4afd5b4 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
@@ -16,27 +16,23 @@
 
 package com.android.inputmethod.latin.personalization;
 
-import com.android.inputmethod.annotations.UsedForTesting;
+import android.content.Context;
+
 import com.android.inputmethod.latin.Dictionary;
 
 import java.io.File;
 import java.util.Locale;
 
-import android.content.Context;
-
 public class PersonalizationDictionary extends DecayingExpandableBinaryDictionaryBase {
     /* package */ static final String NAME = PersonalizationDictionary.class.getSimpleName();
 
     /* package */ PersonalizationDictionary(final Context context, final Locale locale) {
-        super(context, locale, Dictionary.TYPE_PERSONALIZATION,
-                getDictNameWithLocale(NAME, locale));
+        this(context, locale, null /* dictFile */);
     }
 
-    // Creates an instance that uses a given dictionary file for testing.
-    @UsedForTesting
     public PersonalizationDictionary(final Context context, final Locale locale,
             final File dictFile) {
-        super(context, locale, Dictionary.TYPE_PERSONALIZATION, getDictNameWithLocale(NAME, locale),
+        super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_PERSONALIZATION,
                 dictFile);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index 6778c23..504e9b2 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -16,29 +16,27 @@
 
 package com.android.inputmethod.latin.personalization;
 
-import com.android.inputmethod.annotations.UsedForTesting;
+import android.content.Context;
+
 import com.android.inputmethod.latin.Dictionary;
 
 import java.io.File;
 import java.util.Locale;
 
-import android.content.Context;
-
 /**
  * Locally gathers stats about the words user types and various other signals like auto-correction
  * cancellation or manual picks. This allows the keyboard to adapt to the typist over time.
  */
 public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase {
     /* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName();
+
     /* package */ UserHistoryDictionary(final Context context, final Locale locale) {
-        super(context, locale, Dictionary.TYPE_USER_HISTORY, getDictNameWithLocale(NAME, locale));
+        this(context, locale, null /* dictFile */);
     }
 
-    // Creates an instance that uses a given dictionary file for testing.
-    @UsedForTesting
     public UserHistoryDictionary(final Context context, final Locale locale,
             final File dictFile) {
-        super(context, locale, Dictionary.TYPE_USER_HISTORY, getDictNameWithLocale(NAME, locale),
+        super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_USER_HISTORY,
                 dictFile);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 90d3519..77968f7 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -329,4 +329,86 @@
         }
         return prefs.getBoolean(Settings.PREF_VOICE_INPUT_KEY, true);
     }
+
+    public String dump() {
+        final StringBuilder sb = new StringBuilder("Current settings :");
+        sb.append("\n   mSpacingAndPunctuations = ");
+        sb.append("" + mSpacingAndPunctuations.dump());
+        sb.append("\n   mDelayUpdateOldSuggestions = ");
+        sb.append("" + mDelayUpdateOldSuggestions);
+        sb.append("\n   mAutoCap = ");
+        sb.append("" + mAutoCap);
+        sb.append("\n   mVibrateOn = ");
+        sb.append("" + mVibrateOn);
+        sb.append("\n   mSoundOn = ");
+        sb.append("" + mSoundOn);
+        sb.append("\n   mKeyPreviewPopupOn = ");
+        sb.append("" + mKeyPreviewPopupOn);
+        sb.append("\n   mShowsVoiceInputKey = ");
+        sb.append("" + mShowsVoiceInputKey);
+        sb.append("\n   mIncludesOtherImesInLanguageSwitchList = ");
+        sb.append("" + mIncludesOtherImesInLanguageSwitchList);
+        sb.append("\n   mShowsLanguageSwitchKey = ");
+        sb.append("" + mShowsLanguageSwitchKey);
+        sb.append("\n   mUseContactsDict = ");
+        sb.append("" + mUseContactsDict);
+        sb.append("\n   mUsePersonalizedDicts = ");
+        sb.append("" + mUsePersonalizedDicts);
+        sb.append("\n   mUseDoubleSpacePeriod = ");
+        sb.append("" + mUseDoubleSpacePeriod);
+        sb.append("\n   mBlockPotentiallyOffensive = ");
+        sb.append("" + mBlockPotentiallyOffensive);
+        sb.append("\n   mBigramPredictionEnabled = ");
+        sb.append("" + mBigramPredictionEnabled);
+        sb.append("\n   mGestureInputEnabled = ");
+        sb.append("" + mGestureInputEnabled);
+        sb.append("\n   mGestureTrailEnabled = ");
+        sb.append("" + mGestureTrailEnabled);
+        sb.append("\n   mGestureFloatingPreviewTextEnabled = ");
+        sb.append("" + mGestureFloatingPreviewTextEnabled);
+        sb.append("\n   mSlidingKeyInputPreviewEnabled = ");
+        sb.append("" + mSlidingKeyInputPreviewEnabled);
+        sb.append("\n   mPhraseGestureEnabled = ");
+        sb.append("" + mPhraseGestureEnabled);
+        sb.append("\n   mKeyLongpressTimeout = ");
+        sb.append("" + mKeyLongpressTimeout);
+        sb.append("\n   mLocale = ");
+        sb.append("" + mLocale);
+        sb.append("\n   mInputAttributes = ");
+        sb.append("" + mInputAttributes);
+        sb.append("\n   mKeypressVibrationDuration = ");
+        sb.append("" + mKeypressVibrationDuration);
+        sb.append("\n   mKeypressSoundVolume = ");
+        sb.append("" + mKeypressSoundVolume);
+        sb.append("\n   mKeyPreviewPopupDismissDelay = ");
+        sb.append("" + mKeyPreviewPopupDismissDelay);
+        sb.append("\n   mAutoCorrectEnabled = ");
+        sb.append("" + mAutoCorrectEnabled);
+        sb.append("\n   mAutoCorrectionThreshold = ");
+        sb.append("" + mAutoCorrectionThreshold);
+        sb.append("\n   mCorrectionEnabled = ");
+        sb.append("" + mCorrectionEnabled);
+        sb.append("\n   mSuggestionVisibility = ");
+        sb.append("" + mSuggestionVisibility);
+        sb.append("\n   mUseOnlyPersonalizationDictionaryForDebug = ");
+        sb.append("" + mUseOnlyPersonalizationDictionaryForDebug);
+        sb.append("\n   mDisplayOrientation = ");
+        sb.append("" + mDisplayOrientation);
+        sb.append("\n   mAppWorkarounds = ");
+        final AppWorkaroundsUtils awu = mAppWorkarounds.get(null, 0);
+        sb.append("" + (null == awu ? "null" : awu.toString()));
+        sb.append("\n   mAdditionalFeaturesSettingValues = ");
+        sb.append("" + Arrays.toString(mAdditionalFeaturesSettingValues));
+        sb.append("\n   mIsInternal = ");
+        sb.append("" + mIsInternal);
+        sb.append("\n   mKeyPreviewShowUpDuration = ");
+        sb.append("" + mKeyPreviewShowUpDuration);
+        sb.append("\n   mKeyPreviewDismissDuration = ");
+        sb.append("" + mKeyPreviewDismissDuration);
+        sb.append("\n   mKeyPreviewShowUpStartScale = ");
+        sb.append("" + mKeyPreviewShowUpStartScale);
+        sb.append("\n   mKeyPreviewDismissEndScale = ");
+        sb.append("" + mKeyPreviewDismissEndScale);
+        return sb.toString();
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
index 60ca5ba..03883a4 100644
--- a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
+++ b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
@@ -115,4 +115,29 @@
     public boolean isSentenceSeparator(final int code) {
         return code == mSentenceSeparator;
     }
+
+    public String dump() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("mSortedSymbolsPrecededBySpace = ");
+        sb.append("" + Arrays.toString(mSortedSymbolsPrecededBySpace));
+        sb.append("\n   mSortedSymbolsFollowedBySpace = ");
+        sb.append("" + Arrays.toString(mSortedSymbolsFollowedBySpace));
+        sb.append("\n   mSortedWordConnectors = ");
+        sb.append("" + Arrays.toString(mSortedWordConnectors));
+        sb.append("\n   mSortedWordSeparators = ");
+        sb.append("" + Arrays.toString(mSortedWordSeparators));
+        sb.append("\n   mSuggestPuncList = ");
+        sb.append("" + mSuggestPuncList);
+        sb.append("\n   mSentenceSeparator = ");
+        sb.append("" + mSentenceSeparator);
+        sb.append("\n   mSentenceSeparatorAndSpace = ");
+        sb.append("" + mSentenceSeparatorAndSpace);
+        sb.append("\n   mCurrentLanguageHasSpaces = ");
+        sb.append("" + mCurrentLanguageHasSpaces);
+        sb.append("\n   mUsesAmericanTypography = ");
+        sb.append("" + mUsesAmericanTypography);
+        sb.append("\n   mUsesGermanRules = ");
+        sb.append("" + mUsesGermanRules);
+        return sb.toString();
+    }
 }