Merge "Ignore bigrams that are not also listed as unigrams" into jb-dev
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 0be8860..4fe447e 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -166,7 +166,9 @@
         <item>PC</item>
     </string-array>
     <!-- Description for generic subtype that has predefined layout.
-         The string resource name must be "subtype_generic_<layout name>". -->
+         The string resource name must be "subtype_generic_<layout name>".
+         The string resource with "No language" also must be added to strings.xml and the resource
+         name must be "subtype_no_language_<layout name>" -->
     <string name="subtype_generic_qwerty">%s (QWERTY)</string>
     <string name="subtype_generic_qwertz">%s (QWERTZ)</string>
     <string name="subtype_generic_azerty">%s (AZERTY)</string>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 93bd268..e258f3b 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -64,11 +64,11 @@
     <!-- Option summary for advanced settings screen [CHAR LIMIT=65 (two lines) or 30 (fits on one line, preferable)] -->
     <string name="advanced_settings_summary">Options for experts</string>
 
-    <!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=25] -->
+    <!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=30] -->
     <string name="include_other_imes_in_language_switch_list">Switch to other input methods</string>
     <!-- Option summary for including other IMEs in the language switch list [CHAR LIMIT=65] -->
     <string name="include_other_imes_in_language_switch_list_summary">Language switch key covers other input methods too</string>
-    <!-- Option to suppress language switch key [CHAR LIMIT=25] -->
+    <!-- Option to suppress language switch key [CHAR LIMIT=30] -->
     <string name="suppress_language_switch_key">Suppress language switch key</string>
 
     <!-- Option for the dismiss delay of the key popup [CHAR LIMIT=25] -->
@@ -256,10 +256,20 @@
     <string name="subtype_no_language">No language</string>
     <!-- Description for language agnostic QWERTY keyboard subtype [CHAR LIMIT=22] -->
     <string name="subtype_no_language_qwerty">No language (QWERTY)</string>
+    <!-- Description for language agnostic QWERTZ keyboard subtype [CHAR LIMIT=22] -->
+    <string name="subtype_no_language_qwertz">No language (QWERTZ)</string>
+    <!-- Description for language agnostic AZERTY keyboard subtype [CHAR LIMIT=22] -->
+    <string name="subtype_no_language_azerty">No language (AZERTY)</string>
+    <!-- Description for language agnostic Dvorak keyboard subtype [CHAR LIMIT=22] -->
+    <string name="subtype_no_language_dvorak">No language (Dvorak)</string>
+    <!-- Description for language agnostic Colemak keyboard subtype [CHAR LIMIT=22] -->
+    <string name="subtype_no_language_colemak">No language (Colemak)</string>
+    <!-- Description for language agnostic PC QWERTY keyboard subtype [CHAR LIMIT=22] -->
+    <string name="subtype_no_language_pcqwerty">No language (PC)</string>
 
-    <!-- Title of the preference settings for custom input styles (language and keyboard layout pairs) [CHAR LIMIT=22]-->
+    <!-- Title of the preference settings for custom input styles (language and keyboard layout pairs) [CHAR LIMIT=35]-->
     <string name="custom_input_styles_title">Custom input styles</string>
-    <!-- Title of the option menu to add a new style entry in the preference settings [CHAR_LIMIT=12] -->
+    <!-- Title of the option menu to add a new style entry in the preference settings [CHAR_LIMIT=16] -->
     <string name="add_style">Add style</string>
     <!-- Title of the button to add custom style entry in the settings dialog [CHAR_LIMIT=12]  -->
     <string name="add">Add</string>
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index d50d096..58bd845 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -20,6 +20,7 @@
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -48,11 +49,13 @@
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.ResearchLogger;
 import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
+import com.android.inputmethod.latin.StringUtils;
 import com.android.inputmethod.latin.SubtypeLocale;
 import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils;
 import com.android.inputmethod.latin.define.ProductionFlag;
 
+import java.util.Locale;
 import java.util.WeakHashMap;
 
 /**
@@ -85,9 +88,8 @@
     private float mSpacebarTextSize;
     private final int mSpacebarTextColor;
     private final int mSpacebarTextShadowColor;
-    // If the full language name needs to be smaller than this value to be drawn on space key,
-    // its short language name will be used instead.
-    private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f;
+    // The minimum x-scale to fit the language name on spacebar.
+    private static final float MINIMUM_XSCALE_OF_LANGUAGE_NAME = 0.8f;
     // Stuff to draw auto correction LED on spacebar.
     private boolean mAutoCorrectionSpacebarLedOn;
     private final boolean mAutoCorrectionSpacebarLedEnabled;
@@ -895,47 +897,38 @@
         }
     }
 
-    // Compute width of text with specified text size using paint.
-    private int getTextWidth(Paint paint, String text, float textSize) {
-        paint.setTextSize(textSize);
-        return (int)getLabelWidth(text, paint);
+    private boolean fitsTextIntoWidth(final int width, String text, Paint paint) {
+        paint.setTextScaleX(1.0f);
+        final float textWidth = getLabelWidth(text, paint);
+        if (textWidth < width) return true;
+
+        final float scaleX = width / textWidth;
+        if (scaleX < MINIMUM_XSCALE_OF_LANGUAGE_NAME) return false;
+
+        paint.setTextScaleX(scaleX);
+        return getLabelWidth(text, paint) < width;
     }
 
-    // Layout locale language name on spacebar.
-    private String layoutLanguageOnSpacebar(Paint paint, InputMethodSubtype subtype, int width,
-            float origTextSize) {
-        paint.setTextAlign(Align.CENTER);
-        paint.setTypeface(Typeface.DEFAULT);
-        // Estimate appropriate language name text size to fit in maxTextWidth.
-        String language = SubtypeLocale.getFullDisplayName(subtype);
-        int textWidth = getTextWidth(paint, language, origTextSize);
-        // Assuming text width and text size are proportional to each other.
-        float textSize = origTextSize * Math.min(width / textWidth, 1.0f);
-        // allow variable text size
-        textWidth = getTextWidth(paint, language, textSize);
-        // If text size goes too small or text does not fit, use middle or short name
-        final boolean useMiddleName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
-                || (textWidth > width);
-
-        final boolean useShortName;
-        if (useMiddleName) {
-            language = SubtypeLocale.getMiddleDisplayName(subtype);
-            textWidth = getTextWidth(paint, language, origTextSize);
-            textSize = origTextSize * Math.min(width / textWidth, 1.0f);
-            useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
-                    || (textWidth > width);
-        } else {
-            useShortName = false;
+    // Layout language name on spacebar.
+    private String layoutLanguageOnSpacebar(Paint paint, InputMethodSubtype subtype,
+            final int width) {
+        // Choose appropriate language name to fit into the width.
+        String text = getFullDisplayName(subtype, getResources());
+        if (fitsTextIntoWidth(width, text, paint)) {
+            return text;
         }
 
-        if (useShortName) {
-            language = SubtypeLocale.getShortDisplayName(subtype);
-            textWidth = getTextWidth(paint, language, origTextSize);
-            textSize = origTextSize * Math.min(width / textWidth, 1.0f);
+        text = getMiddleDisplayName(subtype);
+        if (fitsTextIntoWidth(width, text, paint)) {
+            return text;
         }
-        paint.setTextSize(textSize);
 
-        return language;
+        text = getShortDisplayName(subtype);
+        if (fitsTextIntoWidth(width, text, paint)) {
+            return text;
+        }
+
+        return "";
     }
 
     private void drawSpacebar(Key key, Canvas canvas, Paint paint) {
@@ -944,11 +937,12 @@
 
         // If input language are explicitly selected.
         if (mNeedsToDisplayLanguage) {
-            final String language = layoutLanguageOnSpacebar(
-                    paint, getKeyboard().mId.mSubtype, width, mSpacebarTextSize);
+            paint.setTextAlign(Align.CENTER);
+            paint.setTypeface(Typeface.DEFAULT);
+            paint.setTextSize(mSpacebarTextSize);
+            final InputMethodSubtype subtype = getKeyboard().mId.mSubtype;
+            final String language = layoutLanguageOnSpacebar(paint, subtype, width);
             // Draw language text with shadow
-            // In case there is no space icon, we will place the language text at the center of
-            // spacebar.
             final float descent = paint.descent();
             final float textHeight = -paint.ascent() + descent;
             final float baseline = height / 2 + textHeight / 2;
@@ -975,4 +969,46 @@
             drawIcon(canvas, mSpaceIcon, x, y, iconWidth, iconHeight);
         }
     }
+
+    // InputMethodSubtype's display name for spacebar text in its locale.
+    //        isAdditionalSubtype (T=true, F=false)
+    // locale layout | Short  Middle      Full
+    // ------ ------ - ---- --------- ----------------------
+    //  en_US qwerty F  En  English   English (US)           exception
+    //  en_GB qwerty F  En  English   English (UK)           exception
+    //  fr    azerty F  Fr  Français  Français
+    //  fr_CA qwerty F  Fr  Français  Français (Canada)
+    //  de    qwertz F  De  Deutsch   Deutsch
+    //  zz    qwerty F      QWERTY    QWERTY
+    //  fr    qwertz T  Fr  Français  Français (QWERTZ)
+    //  de    qwerty T  De  Deutsch   Deutsch (QWERTY)
+    //  en_US azerty T  En  English   English (US) (AZERTY)
+    //  zz    azerty T      AZERTY    AZERTY
+
+    // Get InputMethodSubtype's full display name in its locale.
+    static String getFullDisplayName(InputMethodSubtype subtype, Resources res) {
+        if (SubtypeLocale.isNoLanguage(subtype)) {
+            return SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype);
+        }
+
+        return SubtypeLocale.getSubtypeDisplayName(subtype, res);
+    }
+
+    // Get InputMethodSubtype's short display name in its locale.
+    static String getShortDisplayName(InputMethodSubtype subtype) {
+        if (SubtypeLocale.isNoLanguage(subtype)) {
+            return "";
+        }
+        final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+        return StringUtils.toTitleCase(locale.getLanguage(), locale);
+    }
+
+    // Get InputMethodSubtype's middle display name in its locale.
+    static String getMiddleDisplayName(InputMethodSubtype subtype) {
+        if (SubtypeLocale.isNoLanguage(subtype)) {
+            return SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype);
+        }
+        final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+        return StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
index b9023ae..06d3315 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
@@ -42,8 +42,7 @@
         final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
         final String filteredExtraValue = StringUtils.appendToCsvIfNotExists(
                 IS_ADDITIONAL_SUBTYPE, extraValue);
-        final int nameId = SubtypeLocale.getSubtypeNameIdFromKeyboardLayoutName(
-                keyboardLayoutSetName);
+        final int nameId = SubtypeLocale.getSubtypeNameId(localeString, keyboardLayoutSetName);
         return new InputMethodSubtype(nameId, R.drawable.ic_subtype_keyboard,
                 localeString, KEYBOARD_MODE,
                 layoutExtraValue + "," + filteredExtraValue, false, false);
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
index 8ce91fd..be807ab 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
@@ -41,7 +41,6 @@
 import android.widget.Spinner;
 import android.widget.SpinnerAdapter;
 
-import java.util.Locale;
 import java.util.TreeSet;
 
 public class AdditionalSubtypeSettings extends PreferenceFragment {
@@ -61,7 +60,7 @@
         }
 
         public SubtypeLocaleItem(String localeString) {
-            this(localeString, getDisplayName(localeString));
+            this(localeString, SubtypeLocale.getSubtypeLocaleDisplayName(localeString));
         }
 
         @Override
@@ -73,11 +72,6 @@
         public int compareTo(SubtypeLocaleItem o) {
             return first.compareTo(o.first);
         }
-
-        private static String getDisplayName(String localeString) {
-            final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
-            return StringUtils.toTitleCase(locale.getDisplayName(locale), locale);
-        }
     }
 
     static class SubtypeLocaleAdapter extends ArrayAdapter<SubtypeLocaleItem> {
@@ -185,7 +179,8 @@
                 setDialogTitle(R.string.add_style);
                 setKey(KEY_NEW_SUBTYPE);
             } else {
-                final String displayName = SubtypeLocale.getFullDisplayName(subtype);
+                final String displayName = SubtypeLocale.getSubtypeDisplayName(
+                        subtype, getContext().getResources());
                 setTitle(displayName);
                 setDialogTitle(displayName);
                 setKey(KEY_PREFIX + subtype.getLocale() + "_"
diff --git a/java/src/com/android/inputmethod/latin/LocaleUtils.java b/java/src/com/android/inputmethod/latin/LocaleUtils.java
index f19c59a..b938dd3 100644
--- a/java/src/com/android/inputmethod/latin/LocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/LocaleUtils.java
@@ -180,13 +180,13 @@
                 try {
                     if (newLocale != null && !newLocale.equals(oldLocale)) {
                         conf.locale = newLocale;
-                        res.updateConfiguration(conf, res.getDisplayMetrics());
+                        res.updateConfiguration(conf, null);
                     }
                     return job(res);
                 } finally {
                     if (newLocale != null && !newLocale.equals(oldLocale)) {
                         conf.locale = oldLocale;
-                        res.updateConfiguration(conf, res.getDisplayMetrics());
+                        res.updateConfiguration(conf, null);
                     }
                 }
             }
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 13264f7..74c4aea 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -300,13 +300,14 @@
         final PreferenceScreen customInputStyles =
                 (PreferenceScreen)findPreference(PREF_CUSTOM_INPUT_STYLES);
         final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
-        final String prefSubtype = SettingsValues.getPrefAdditionalSubtypes(prefs, getResources());
+        final Resources res = getResources();
+        final String prefSubtype = SettingsValues.getPrefAdditionalSubtypes(prefs, res);
         final InputMethodSubtype[] subtypes =
                 AdditionalSubtype.createAdditionalSubtypesArray(prefSubtype);
         final StringBuilder styles = new StringBuilder();
         for (final InputMethodSubtype subtype : subtypes) {
             if (styles.length() > 0) styles.append(", ");
-            styles.append(SubtypeLocale.getFullDisplayName(subtype));
+            styles.append(SubtypeLocale.getSubtypeDisplayName(subtype, res));
         }
         customInputStyles.setSummary(styles);
     }
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index 88d3c3f..d10c42c 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -45,7 +45,10 @@
     // Keyboard layout to subtype name resource id map.
     private static final HashMap<String, Integer> sKeyboardLayoutToNameIdsMap =
             new HashMap<String, Integer>();
-    private static final String SUBTYPE_RESOURCE_GENERIC_NAME_PREFIX = "string/subtype_generic_";
+    private static final String SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX =
+            "string/subtype_generic_";
+    private static final String SUBTYPE_NAME_RESOURCE_NO_LANGUAGE_PREFIX =
+            "string/subtype_no_language_";
     // Exceptional locales to display name map.
     private static final HashMap<String, String> sExceptionalDisplayNamesMap =
             new HashMap<String, String>();
@@ -64,9 +67,15 @@
         for (int i = 0; i < predefinedLayoutSet.length; i++) {
             final String layoutName = predefinedLayoutSet[i];
             sKeyboardKayoutToDisplayNameMap.put(layoutName, layoutDisplayNames[i]);
-            final String resourceName = SUBTYPE_RESOURCE_GENERIC_NAME_PREFIX + layoutName;
+            final String resourceName = SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX + layoutName;
             final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
             sKeyboardLayoutToNameIdsMap.put(layoutName, resId);
+            // Register subtype name resource id of "No language" with key "zz_<layout>"
+            final String noLanguageResName = SUBTYPE_NAME_RESOURCE_NO_LANGUAGE_PREFIX + layoutName;
+            final int noLanguageResId = res.getIdentifier(
+                    noLanguageResName, null, RESOURCE_PACKAGE_NAME);
+            final String key = getNoLanguageLayoutKey(layoutName);
+            sKeyboardLayoutToNameIdsMap.put(key, noLanguageResId);
         }
 
         final String[] exceptionalLocales = res.getStringArray(
@@ -82,65 +91,45 @@
         return sPredefinedKeyboardLayoutSet;
     }
 
-    public static int getSubtypeNameIdFromKeyboardLayoutName(String keyboardLayoutName) {
-        final Integer nameId = sKeyboardLayoutToNameIdsMap.get(keyboardLayoutName);
+    private static final String getNoLanguageLayoutKey(String keyboardLayoutName) {
+        return NO_LANGUAGE + "_" + keyboardLayoutName;
+    }
+
+    public static int getSubtypeNameId(String localeString, String keyboardLayoutName) {
+        final String key = localeString.equals(NO_LANGUAGE)
+                ? getNoLanguageLayoutKey(keyboardLayoutName)
+                : keyboardLayoutName;
+        final Integer nameId = sKeyboardLayoutToNameIdsMap.get(key);
         return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId;
     }
 
-    // Get InputMethodSubtype's display name in its locale.
-    //        isAdditionalSubtype (T=true, F=false)
-    // locale layout | Short  Middle      Full
-    // ------ ------ - ---- --------- -----------------
-    //  en_US qwerty F  En  English   English (US)      exception
-    //  en_GB qwerty F  En  English   English (UK)      exception
-    //  fr    azerty F  Fr  Français  Français
-    //  fr_CA qwerty F  Fr  Français  Français (Canada)
-    //  de    qwertz F  De  Deutsch   Deutsch
-    //  zz    qwerty F      QWERTY    QWERTY
-    //  fr    qwertz T  Fr  Français  Français (QWERTZ)
-    //  de    qwerty T  De  Deutsch   Deutsch (QWERTY)
-    //  en_US azerty T  En  English   English (US) (AZERTY)
-    //  zz    azerty T      AZERTY    AZERTY
-
-    // Get InputMethodSubtype's full display name in its locale.
-    public static String getFullDisplayName(InputMethodSubtype subtype) {
-        if (isNoLanguage(subtype)) {
-            return getKeyboardLayoutSetDisplayName(subtype);
-        }
-
-        final String exceptionalValue = sExceptionalDisplayNamesMap.get(subtype.getLocale());
-
-        final Locale locale = getSubtypeLocale(subtype);
-        if (AdditionalSubtype.isAdditionalSubtype(subtype)) {
-            final String language = (exceptionalValue != null) ? exceptionalValue
-                    : StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
-            final String layout = getKeyboardLayoutSetDisplayName(subtype);
-            return String.format("%s (%s)", language, layout);
-        }
-
+    public static String getSubtypeLocaleDisplayName(String localeString) {
+        final String exceptionalValue = sExceptionalDisplayNamesMap.get(localeString);
         if (exceptionalValue != null) {
             return exceptionalValue;
         }
-
+        final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
         return StringUtils.toTitleCase(locale.getDisplayName(locale), locale);
     }
 
-    // Get InputMethodSubtype's middle display name in its locale.
-    public static String getMiddleDisplayName(InputMethodSubtype subtype) {
-        if (isNoLanguage(subtype)) {
-            return getKeyboardLayoutSetDisplayName(subtype);
-        }
-        final Locale locale = getSubtypeLocale(subtype);
-        return StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
-    }
+    // InputMethodSubtype's display name in its locale.
+    //        isAdditionalSubtype (T=true, F=false)
+    // locale layout |  display name
+    // ------ ------ - ----------------------
+    //  en_US qwerty F  English (US)            exception
+    //  en_GB qwerty F  English (UK)            exception
+    //  fr    azerty F  Français
+    //  fr_CA qwerty F  Français (Canada)
+    //  de    qwertz F  Deutsch
+    //  zz    qwerty F  No language (QWERTY)
+    //  fr    qwertz T  Français (QWERTZ)
+    //  de    qwerty T  Deutsch (QWERTY)
+    //  en_US azerty T  English (US) (AZERTY)
+    //  zz    azerty T  No language (AZERTY)
 
-    // Get InputMethodSubtype's short display name in its locale.
-    public static String getShortDisplayName(InputMethodSubtype subtype) {
-        if (isNoLanguage(subtype)) {
-            return "";
-        }
-        final Locale locale = getSubtypeLocale(subtype);
-        return StringUtils.toTitleCase(locale.getLanguage(), locale);
+    public static String getSubtypeDisplayName(InputMethodSubtype subtype, Resources res) {
+        final String language = getSubtypeLocaleDisplayName(subtype.getLocale());
+        return res.getString(subtype.getNameResId(), language);
     }
 
     public static boolean isNoLanguage(InputMethodSubtype subtype) {
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 8042873..f2d971c 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -182,12 +182,13 @@
                     + newSubtype.getLocale() + "/" + newSubtype.getExtraValue() + ", from: "
                     + mCurrentSubtype.getLocale() + "/" + mCurrentSubtype.getExtraValue());
         }
-        if (newSubtype.equals(mCurrentSubtype)) return;
 
         final Locale newLocale = SubtypeLocale.getSubtypeLocale(newSubtype);
         mNeedsToDisplayLanguage.updateIsSystemLanguageSameAsInputLanguage(
                 mCurrentSystemLocale.equals(newLocale));
 
+        if (newSubtype.equals(mCurrentSubtype)) return;
+
         mCurrentSubtype = newSubtype;
         updateShortcutIME();
         mService.onRefreshKeyboard();
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 3e72ce6..de9dbf9 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -137,13 +137,15 @@
     int *frequencies = env->GetIntArrayElements(frequencyArray, 0);
     int *inputCodes = env->GetIntArrayElements(inputArray, 0);
     jchar *outputChars = env->GetCharArrayElements(outputArray, 0);
-    // Deactivated to prevent unused variable errors.
-    // TODO: use the following variables.
-    // jint *prevWordChars = prevWordForBigrams
-    //         ? env->GetIntArrayElements(prevWordForBigrams, 0) : NULL;
-    // jsize prevWordLength = prevWordChars ? env->GetArrayLength(prevWordForBigrams) : 0;
+    jint *prevWordChars = prevWordForBigrams
+            ? env->GetIntArrayElements(prevWordForBigrams, 0) : 0;
+    jsize prevWordLength = prevWordChars ? env->GetArrayLength(prevWordForBigrams) : 0;
     int count = dictionary->getSuggestions(pInfo, xCoordinates, yCoordinates, inputCodes,
-            arraySize, useFullEditDistance, (unsigned short*) outputChars, frequencies);
+            arraySize, prevWordChars, prevWordLength, useFullEditDistance,
+            (unsigned short*) outputChars, frequencies);
+    if (prevWordChars) {
+        env->ReleaseIntArrayElements(prevWordForBigrams, prevWordChars, JNI_ABORT);
+    }
     env->ReleaseCharArrayElements(outputArray, outputChars, 0);
     env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
     env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
diff --git a/native/jni/src/bigram_dictionary.cpp b/native/jni/src/bigram_dictionary.cpp
index 927381f..e05e9d6 100644
--- a/native/jni/src/bigram_dictionary.cpp
+++ b/native/jni/src/bigram_dictionary.cpp
@@ -107,8 +107,8 @@
     mMaxBigrams = maxBigrams;
 
     const uint8_t* const root = DICT;
-    int pos = getBigramListForWord(root, prevWord, prevWordLength);
-    // getBigramListForWord returns 0 if this word is not in the dictionary or has no bigrams
+    int pos = getBigramListPositionForWord(prevWord, prevWordLength);
+    // getBigramListPositionForWord returns 0 if this word isn't in the dictionary or has no bigrams
     if (0 == pos) return 0;
     int bigramFlags;
     int bigramCount = 0;
@@ -133,8 +133,9 @@
 
 // Returns a pointer to the start of the bigram list.
 // If the word is not found or has no bigrams, this function returns 0.
-int BigramDictionary::getBigramListForWord(const uint8_t* const root,
-        const int32_t *prevWord, const int prevWordLength) {
+int BigramDictionary::getBigramListPositionForWord(const int32_t *prevWord,
+        const int prevWordLength) {
+    const uint8_t* const root = DICT;
     int pos = BinaryFormat::getTerminalPosition(root, prevWord, prevWordLength);
 
     if (NOT_VALID_WORD == pos) return 0;
diff --git a/native/jni/src/bigram_dictionary.h b/native/jni/src/bigram_dictionary.h
index 07e47f0..76f9039 100644
--- a/native/jni/src/bigram_dictionary.h
+++ b/native/jni/src/bigram_dictionary.h
@@ -27,8 +27,7 @@
     BigramDictionary(const unsigned char *dict, int maxWordLength, Dictionary *parentDictionary);
     int getBigrams(const int32_t *word, int length, int *codes, int codesSize,
             unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams);
-    int getBigramListForWord(const uint8_t* const root,
-        const int32_t *prevWord, const int prevWordLength);
+    int getBigramListPositionForWord(const int32_t *prevWord, const int prevWordLength);
     ~BigramDictionary();
  private:
     bool addWordBigram(unsigned short *word, int length, int frequency);
diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h
index 5b9ddb3..e0feeaf 100644
--- a/native/jni/src/dictionary.h
+++ b/native/jni/src/dictionary.h
@@ -33,12 +33,12 @@
             int fullWordMultiplier, int maxWordLength, int maxWords);
 
     int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates,
-            int *codes, int codesSize, bool useFullEditDistance, unsigned short *outWords,
-            int *frequencies) {
+            int *codes, int codesSize, const int32_t* prevWordChars, const int prevWordLength,
+            bool useFullEditDistance, unsigned short *outWords, int *frequencies) {
         // bigramListPosition is, as an int, the offset of the bigram list in the file.
         // If none, it's zero.
-        // TODO: get this from the bigram dictionary instance
-        const int bigramListPosition = 0;
+        const int bigramListPosition = !prevWordChars ? 0
+                : mBigramDictionary->getBigramListPositionForWord(prevWordChars, prevWordLength);
         return mUnigramDictionary->getSuggestions(proximityInfo, mWordsPriorityQueuePool,
                 mCorrection, xcoordinates, ycoordinates, codes, codesSize, bigramListPosition,
                 useFullEditDistance, outWords, frequencies);
diff --git a/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java b/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java
new file mode 100644
index 0000000..663f708
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2012 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.keyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.test.AndroidTestCase;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
+import com.android.inputmethod.latin.AdditionalSubtype;
+import com.android.inputmethod.latin.ImfUtils;
+import com.android.inputmethod.latin.StringUtils;
+import com.android.inputmethod.latin.SubtypeLocale;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class SpacebarTextTests extends AndroidTestCase {
+    // Locale to subtypes list.
+    private final ArrayList<InputMethodSubtype> mSubtypesList = new ArrayList<InputMethodSubtype>();
+
+    private Resources mRes;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final Context context = getContext();
+        mRes = context.getResources();
+        InputMethodManagerCompatWrapper.init(context);
+        SubtypeLocale.init(context);
+    }
+
+    public void testAllFullDisplayName() {
+        for (final InputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype, mRes);
+            final String spacebarText = LatinKeyboardView.getFullDisplayName(subtype, mRes);
+            final String languageName =
+                    SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale());
+            if (SubtypeLocale.isNoLanguage(subtype)) {
+                assertFalse(subtypeName, spacebarText.contains(languageName));
+            } else {
+                assertTrue(subtypeName, spacebarText.contains(languageName));
+            }
+        }
+    }
+
+   public void testAllMiddleDisplayName() {
+        for (final InputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype, mRes);
+            final String spacebarText = LatinKeyboardView.getMiddleDisplayName(subtype);
+            if (SubtypeLocale.isNoLanguage(subtype)) {
+                assertEquals(subtypeName,
+                        SubtypeLocale.getKeyboardLayoutSetName(subtype), spacebarText);
+            } else {
+                assertEquals(subtypeName,
+                        SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale()),
+                        spacebarText);
+            }
+        }
+    }
+
+    public void testAllShortDisplayName() {
+        for (final InputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype, mRes);
+            final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+            final String spacebarText = LatinKeyboardView.getShortDisplayName(subtype);
+            final String languageCode = StringUtils.toTitleCase(locale.getLanguage(), locale);
+            if (SubtypeLocale.isNoLanguage(subtype)) {
+                assertEquals(subtypeName, "", spacebarText);
+            } else {
+                assertEquals(subtypeName, languageCode, spacebarText);
+            }
+        }
+    }
+
+    // InputMethodSubtype's display name for spacebar text in its locale.
+    //        isAdditionalSubtype (T=true, F=false)
+    // locale layout | Short  Middle      Full
+    // ------ ------ - ---- --------- ----------------------
+    //  en_US qwerty F  En  English   English (US)           exception
+    //  en_GB qwerty F  En  English   English (UK)           exception
+    //  fr    azerty F  Fr  Français  Français
+    //  fr_CA qwerty F  Fr  Français  Français (Canada)
+    //  de    qwertz F  De  Deutsch   Deutsch
+    //  zz    qwerty F      QWERTY    QWERTY
+    //  fr    qwertz T  Fr  Français  Français (QWERTZ)
+    //  de    qwerty T  De  Deutsch   Deutsch (QWERTY)
+    //  en_US azerty T  En  English   English (US) (AZERTY)
+    //  zz    azerty T      AZERTY    AZERTY
+
+    public void testPredefinedSubtypes() {
+        final Context context = getContext();
+        final InputMethodSubtype EN_US = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, Locale.US.toString(), "qwerty");
+        final InputMethodSubtype EN_GB = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, Locale.UK.toString(), "qwerty");
+        final InputMethodSubtype FR = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, Locale.FRENCH.toString(), "azerty");
+        final InputMethodSubtype FR_CA = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, Locale.CANADA_FRENCH.toString(), "qwerty");
+        final InputMethodSubtype DE = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, Locale.GERMAN.toString(), "qwertz");
+        final InputMethodSubtype ZZ = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, SubtypeLocale.NO_LANGUAGE, "qwerty");
+
+        assertEquals("en_US", "English (US)",
+                LatinKeyboardView.getFullDisplayName(EN_US, mRes));
+        assertEquals("en_GB", "English (UK)",
+                LatinKeyboardView.getFullDisplayName(EN_GB, mRes));
+        assertEquals("fr   ", "Français",
+                LatinKeyboardView.getFullDisplayName(FR, mRes));
+        assertEquals("fr_CA", "Français (Canada)",
+                LatinKeyboardView.getFullDisplayName(FR_CA, mRes));
+        assertEquals("de   ", "Deutsch",
+                LatinKeyboardView.getFullDisplayName(DE, mRes));
+        assertEquals("zz   ", "QWERTY",
+                LatinKeyboardView.getFullDisplayName(ZZ, mRes));
+
+        assertEquals("en_US", "English",  LatinKeyboardView.getMiddleDisplayName(EN_US));
+        assertEquals("en_GB", "English",  LatinKeyboardView.getMiddleDisplayName(EN_GB));
+        assertEquals("fr   ", "Français", LatinKeyboardView.getMiddleDisplayName(FR));
+        assertEquals("fr_CA", "Français", LatinKeyboardView.getMiddleDisplayName(FR_CA));
+        assertEquals("de   ", "Deutsch",  LatinKeyboardView.getMiddleDisplayName(DE));
+        assertEquals("zz   ", "QWERTY",   LatinKeyboardView.getMiddleDisplayName(ZZ));
+
+        assertEquals("en_US", "En", LatinKeyboardView.getShortDisplayName(EN_US));
+        assertEquals("en_GB", "En", LatinKeyboardView.getShortDisplayName(EN_GB));
+        assertEquals("fr   ", "Fr", LatinKeyboardView.getShortDisplayName(FR));
+        assertEquals("fr_CA", "Fr", LatinKeyboardView.getShortDisplayName(FR_CA));
+        assertEquals("de   ", "De", LatinKeyboardView.getShortDisplayName(DE));
+        assertEquals("zz   ", "",   LatinKeyboardView.getShortDisplayName(ZZ));
+    }
+
+    public void testAdditionalSubtype() {
+        final InputMethodSubtype DE_QWERTY = AdditionalSubtype.createAdditionalSubtype(
+                Locale.GERMAN.toString(), "qwerty", null);
+        final InputMethodSubtype FR_QWERTZ = AdditionalSubtype.createAdditionalSubtype(
+                Locale.FRENCH.toString(), "qwertz", null);
+        final InputMethodSubtype US_AZERTY = AdditionalSubtype.createAdditionalSubtype(
+                Locale.US.toString(), "azerty", null);
+        final InputMethodSubtype ZZ_AZERTY = AdditionalSubtype.createAdditionalSubtype(
+                SubtypeLocale.NO_LANGUAGE, "azerty", null);
+
+        assertEquals("fr qwertz",    "Français (QWERTZ)",
+                LatinKeyboardView.getFullDisplayName(FR_QWERTZ, mRes));
+        assertEquals("de qwerty",    "Deutsch (QWERTY)",
+                LatinKeyboardView.getFullDisplayName(DE_QWERTY, mRes));
+        assertEquals("en_US azerty", "English (US) (AZERTY)",
+                LatinKeyboardView.getFullDisplayName(US_AZERTY, mRes));
+        assertEquals("zz azerty",    "AZERTY",
+                LatinKeyboardView.getFullDisplayName(ZZ_AZERTY, mRes));
+
+        assertEquals("fr qwertz",    "Français", LatinKeyboardView.getMiddleDisplayName(FR_QWERTZ));
+        assertEquals("de qwerty",    "Deutsch",  LatinKeyboardView.getMiddleDisplayName(DE_QWERTY));
+        assertEquals("en_US azerty", "English",  LatinKeyboardView.getMiddleDisplayName(US_AZERTY));
+        assertEquals("zz azerty",    "AZERTY",   LatinKeyboardView.getMiddleDisplayName(ZZ_AZERTY));
+
+        assertEquals("fr qwertz",    "Fr", LatinKeyboardView.getShortDisplayName(FR_QWERTZ));
+        assertEquals("de qwerty",    "De", LatinKeyboardView.getShortDisplayName(DE_QWERTY));
+        assertEquals("en_US azerty", "En", LatinKeyboardView.getShortDisplayName(US_AZERTY));
+        assertEquals("zz azerty",    "",  LatinKeyboardView.getShortDisplayName(ZZ_AZERTY));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
index 16b5441..5393b23 100644
--- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
+++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
@@ -17,10 +17,12 @@
 package com.android.inputmethod.latin;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.test.AndroidTestCase;
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
+import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
 
 import java.util.ArrayList;
 import java.util.Locale;
@@ -29,91 +31,47 @@
     // Locale to subtypes list.
     private final ArrayList<InputMethodSubtype> mSubtypesList = new ArrayList<InputMethodSubtype>();
 
+    private Resources mRes;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         final Context context = getContext();
+        mRes = context.getResources();
         InputMethodManagerCompatWrapper.init(context);
         SubtypeLocale.init(context);
     }
 
     public void testAllFullDisplayName() {
-        final StringBuilder messages = new StringBuilder();
-        int failedCount = 0;
         for (final InputMethodSubtype subtype : mSubtypesList) {
-            final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype, mRes);
             if (SubtypeLocale.isNoLanguage(subtype)) {
-                // This is special language name for language agnostic usage.
-                continue;
-            }
-            final String keyboardName = SubtypeLocale.getFullDisplayName(subtype);
-            final String languageName = StringUtils.toTitleCase(
-                    locale.getDisplayLanguage(locale), locale);
-            if (!keyboardName.contains(languageName)) {
-                failedCount++;
-                messages.append(String.format(
-                        "locale %s: keyboard name '%s' should contain language name '%s'\n",
-                        locale, keyboardName, languageName));
+                final String noLanguage = mRes.getString(R.string.subtype_no_language);
+                assertTrue(subtypeName, subtypeName.contains(noLanguage));
+            } else {
+                final String languageName =
+                        SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale());
+                assertTrue(subtypeName, subtypeName.contains(languageName));
             }
         }
-        assertEquals(messages.toString(), 0, failedCount);
     }
 
-   public void testAllMiddleDisplayName() {
-        final StringBuilder messages = new StringBuilder();
-        int failedCount = 0;
-        for (final InputMethodSubtype subtype : mSubtypesList) {
-            final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
-            if (SubtypeLocale.isNoLanguage(subtype)) {
-                // This is special language name for language agnostic usage.
-                continue;
-            }
-            final String keyboardName = SubtypeLocale.getMiddleDisplayName(subtype);
-            final String languageName = StringUtils.toTitleCase(
-                    locale.getDisplayLanguage(locale), locale);
-            if (!keyboardName.equals(languageName)) {
-                failedCount++;
-                messages.append(String.format(
-                        "locale %s: keyboard name '%s' should be equals to language name '%s'\n",
-                        locale, keyboardName, languageName));
-            }
-        }
-        assertEquals(messages.toString(), 0, failedCount);
-    }
+    // InputMethodSubtype's display name in its locale.
+    //        isAdditionalSubtype (T=true, F=false)
+    // locale layout |  display name
+    // ------ ------ - ----------------------
+    //  en_US qwerty F  English (US)            exception
+    //  en_GB qwerty F  English (UK)            exception
+    //  fr    azerty F  Français
+    //  fr_CA qwerty F  Français (Canada)
+    //  de    qwertz F  Deutsch
+    //  zz    qwerty F  No language (QWERTY)
+    //  fr    qwertz T  Français (QWERTZ)
+    //  de    qwerty T  Deutsch (QWERTY)
+    //  en_US azerty T  English (US) (AZERTY)
+    //  zz    azerty T  No language (AZERTY)
 
-    public void testAllShortDisplayName() {
-        final StringBuilder messages = new StringBuilder();
-        int failedCount = 0;
-        for (final InputMethodSubtype subtype : mSubtypesList) {
-            final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
-            final String keyboardName = SubtypeLocale.getShortDisplayName(subtype);
-            final String languageCode = StringUtils.toTitleCase(locale.getLanguage(), locale);
-            if (!keyboardName.equals(languageCode)) {
-                failedCount++;
-                messages.append(String.format(
-                        "locale %s: keyboard name '%s' should be equals to language code '%s'\n",
-                        locale, keyboardName, languageCode));
-            }
-        }
-        assertEquals(messages.toString(), 0, failedCount);
-    }
-
-    // Get InputMethodSubtype's display name in its locale.
-    //            additional
-    // locale layout  Short  Middle      Full
-    // ------ ------ - ---- --------- -----------------
-    //  en_US qwerty F  En  English   English (US)      exception
-    //  en_GB qwerty F  En  English   English (UK)      exception
-    //  fr    azerty F  Fr  Français  Français
-    //  fr_CA qwerty F  Fr  Français  Français (Canada)
-    //  de    qwertz F  De  Deutsch   Deutsch
-    //  zz    qwerty F      QWERTY    QWERTY
-    //  fr    qwertz T  Fr  Français  Français (QWERTZ)
-    //  de    qwerty T  De  Deutsch   Deutsch (QWERTY)
-    //  en_US azerty T  En  English   English (US) (AZERTY)
-    //  zz    azerty T      AZERTY    AZERTY
-
-    public void testSampleSubtypes() {
+    public void testPredefinedSubtypes() {
         final Context context = getContext();
         final InputMethodSubtype EN_US = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 context, Locale.US.toString(), "qwerty");
@@ -128,13 +86,6 @@
         final InputMethodSubtype ZZ = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 context, SubtypeLocale.NO_LANGUAGE, "qwerty");
 
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(EN_US));
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(EN_GB));
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(FR));
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(FR_CA));
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(DE));
-        assertFalse(AdditionalSubtype.isAdditionalSubtype(ZZ));
-
         assertEquals("en_US", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_US));
         assertEquals("en_GB", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_GB));
         assertEquals("fr   ", "azerty", SubtypeLocale.getKeyboardLayoutSetName(FR));
@@ -142,26 +93,18 @@
         assertEquals("de   ", "qwertz", SubtypeLocale.getKeyboardLayoutSetName(DE));
         assertEquals("zz   ", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ));
 
-        assertEquals("en_US", "English (US)",      SubtypeLocale.getFullDisplayName(EN_US));
-        assertEquals("en_GB", "English (UK)",      SubtypeLocale.getFullDisplayName(EN_GB));
-        assertEquals("fr   ", "Français",          SubtypeLocale.getFullDisplayName(FR));
-        assertEquals("fr_CA", "Français (Canada)", SubtypeLocale.getFullDisplayName(FR_CA));
-        assertEquals("de   ", "Deutsch",           SubtypeLocale.getFullDisplayName(DE));
-        assertEquals("zz   ", "QWERTY",            SubtypeLocale.getFullDisplayName(ZZ));
-
-        assertEquals("en_US", "English",  SubtypeLocale.getMiddleDisplayName(EN_US));
-        assertEquals("en_GB", "English",  SubtypeLocale.getMiddleDisplayName(EN_GB));
-        assertEquals("fr   ", "Français", SubtypeLocale.getMiddleDisplayName(FR));
-        assertEquals("fr_CA", "Français", SubtypeLocale.getMiddleDisplayName(FR_CA));
-        assertEquals("de   ", "Deutsch",  SubtypeLocale.getMiddleDisplayName(DE));
-        assertEquals("zz   ", "QWERTY",   SubtypeLocale.getMiddleDisplayName(ZZ));
-
-        assertEquals("en_US", "En", SubtypeLocale.getShortDisplayName(EN_US));
-        assertEquals("en_GB", "En", SubtypeLocale.getShortDisplayName(EN_GB));
-        assertEquals("fr   ", "Fr", SubtypeLocale.getShortDisplayName(FR));
-        assertEquals("fr_CA", "Fr", SubtypeLocale.getShortDisplayName(FR_CA));
-        assertEquals("de   ", "De", SubtypeLocale.getShortDisplayName(DE));
-        assertEquals("zz   ", "", SubtypeLocale.getShortDisplayName(ZZ));
+        assertEquals("en_US", "English (US)",
+                SubtypeLocale.getSubtypeDisplayName(EN_US, mRes));
+        assertEquals("en_GB", "English (UK)",
+                SubtypeLocale.getSubtypeDisplayName(EN_GB, mRes));
+        assertEquals("fr   ", "Français",
+                SubtypeLocale.getSubtypeDisplayName(FR, mRes));
+        assertEquals("fr_CA", "Français (Canada)",
+                SubtypeLocale.getSubtypeDisplayName(FR_CA, mRes));
+        assertEquals("de   ", "Deutsch",
+                SubtypeLocale.getSubtypeDisplayName(DE, mRes));
+        assertEquals("zz   ", "No language (QWERTY)",
+                SubtypeLocale.getSubtypeDisplayName(ZZ, mRes));
     }
 
     public void testAdditionalSubtype() {
@@ -174,28 +117,36 @@
         final InputMethodSubtype ZZ_AZERTY = AdditionalSubtype.createAdditionalSubtype(
                 SubtypeLocale.NO_LANGUAGE, "azerty", null);
 
-        assertTrue(AdditionalSubtype.isAdditionalSubtype(FR_QWERTZ));
-        assertTrue(AdditionalSubtype.isAdditionalSubtype(DE_QWERTY));
-        assertTrue(AdditionalSubtype.isAdditionalSubtype(US_AZERTY));
-        assertTrue(AdditionalSubtype.isAdditionalSubtype(ZZ_AZERTY));
-
         assertEquals("fr qwertz",    "Français (QWERTZ)",
-                SubtypeLocale.getFullDisplayName(FR_QWERTZ));
+                SubtypeLocale.getSubtypeDisplayName(FR_QWERTZ, mRes));
         assertEquals("de qwerty",    "Deutsch (QWERTY)",
-                SubtypeLocale.getFullDisplayName(DE_QWERTY));
+                SubtypeLocale.getSubtypeDisplayName(DE_QWERTY, mRes));
         assertEquals("en_US azerty", "English (US) (AZERTY)",
-                SubtypeLocale.getFullDisplayName(US_AZERTY));
-        assertEquals("zz azerty",    "AZERTY",
-                SubtypeLocale.getFullDisplayName(ZZ_AZERTY));
+                SubtypeLocale.getSubtypeDisplayName(US_AZERTY, mRes));
+        assertEquals("zz azerty",    "No language (AZERTY)",
+                SubtypeLocale.getSubtypeDisplayName(ZZ_AZERTY, mRes));
+    }
 
-        assertEquals("fr qwertz",    "Français", SubtypeLocale.getMiddleDisplayName(FR_QWERTZ));
-        assertEquals("de qwerty",    "Deutsch",  SubtypeLocale.getMiddleDisplayName(DE_QWERTY));
-        assertEquals("en_US azerty", "English",  SubtypeLocale.getMiddleDisplayName(US_AZERTY));
-        assertEquals("zz azerty",    "AZERTY",   SubtypeLocale.getMiddleDisplayName(ZZ_AZERTY));
+    public void testNoLanguageInFrench() {
+        final Context context = getContext();
+        final InputMethodSubtype ZZ = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+                context, SubtypeLocale.NO_LANGUAGE, "qwerty");
+        final InputMethodSubtype ZZ_AZERTY = AdditionalSubtype.createAdditionalSubtype(
+                SubtypeLocale.NO_LANGUAGE, "azerty", null);
 
-        assertEquals("fr qwertz",    "Fr", SubtypeLocale.getShortDisplayName(FR_QWERTZ));
-        assertEquals("de qwerty",    "De", SubtypeLocale.getShortDisplayName(DE_QWERTY));
-        assertEquals("en_US azerty", "En", SubtypeLocale.getShortDisplayName(US_AZERTY));
-        assertEquals("zz azerty",    "", SubtypeLocale.getShortDisplayName(ZZ_AZERTY));
+        final RunInLocale<Void> tests = new RunInLocale<Void>() {
+            @Override
+            protected Void job(Resources res) {
+                assertEquals("zz   ", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ));
+                assertEquals("zz   ", "azerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ_AZERTY));
+
+                assertEquals("zz   ",     "Pas de langue (QWERTY)",
+                        SubtypeLocale.getSubtypeDisplayName(ZZ, res));
+                assertEquals("zz azerty", "Pas de langue (AZERTY)",
+                        SubtypeLocale.getSubtypeDisplayName(ZZ_AZERTY, res));
+                return null;
+            }
+        };
+        tests.runInLocale(mRes, Locale.FRENCH);
     }
 }