Fix NPE in SubtypeLocale.getSubtypeDisplayName

This change moves the methods that create the subtype display name for
spacebar from MainKeyboardView to SubtypeLocale class, and
consolidates SpacebarTextTests with SubtypeLocaleTests.

Bug: 9962955
Change-Id: Ifa0a08ff80bc30753a213c2feb471599ca63fa66
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 190c596..834ff0a 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -67,13 +67,11 @@
 import com.android.inputmethod.latin.utils.CollectionUtils;
 import com.android.inputmethod.latin.utils.CoordinateUtils;
 import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper;
-import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.TypefaceUtils;
 import com.android.inputmethod.latin.utils.UsabilityStudyLogUtils;
 import com.android.inputmethod.latin.utils.ViewLayoutUtils;
 import com.android.inputmethod.research.ResearchLogger;
 
-import java.util.Locale;
 import java.util.WeakHashMap;
 
 /**
@@ -1344,17 +1342,17 @@
     private static String layoutLanguageOnSpacebar(final Paint paint,
             final InputMethodSubtype subtype, final int width) {
         // Choose appropriate language name to fit into the width.
-        final String fullText = getFullDisplayName(subtype);
+        final String fullText = SubtypeLocale.getFullDisplayName(subtype);
         if (fitsTextIntoWidth(width, fullText, paint)) {
             return fullText;
         }
 
-        final String middleText = getMiddleDisplayName(subtype);
+        final String middleText = SubtypeLocale.getMiddleDisplayName(subtype);
         if (fitsTextIntoWidth(width, middleText, paint)) {
             return middleText;
         }
 
-        final String shortText = getShortDisplayName(subtype);
+        final String shortText = SubtypeLocale.getShortDisplayName(subtype);
         if (fitsTextIntoWidth(width, shortText, paint)) {
             return shortText;
         }
@@ -1400,46 +1398,4 @@
             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
-    //  es_US spanish F  Es  Español   Español (EE.UU.)       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
-    //  de    qwerty  T  De  Deutsch   Deutsch
-    //  en_US azerty  T  En  English   English (US)
-    //  zz    azerty  T      AZERTY    AZERTY
-
-    // Get InputMethodSubtype's full display name in its locale.
-    static String getFullDisplayName(final InputMethodSubtype subtype) {
-        if (SubtypeLocale.isNoLanguage(subtype)) {
-            return SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype);
-        }
-        return SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale());
-    }
-
-    // Get InputMethodSubtype's short display name in its locale.
-    static String getShortDisplayName(final InputMethodSubtype subtype) {
-        if (SubtypeLocale.isNoLanguage(subtype)) {
-            return "";
-        }
-        final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
-        return StringUtils.capitalizeFirstCodePoint(locale.getLanguage(), locale);
-    }
-
-    // Get InputMethodSubtype's middle display name in its locale.
-    static String getMiddleDisplayName(final InputMethodSubtype subtype) {
-        if (SubtypeLocale.isNoLanguage(subtype)) {
-            return SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype);
-        }
-        final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
-        return SubtypeLocale.getSubtypeLocaleDisplayName(locale.getLanguage());
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index b096858..56b1e3f 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -134,7 +134,7 @@
         final int currentIndex = getSubtypeIndexInList(currentSubtype, enabledSubtypes);
         if (currentIndex == INDEX_NOT_FOUND) {
             Log.w(TAG, "Can't find current subtype in enabled subtypes: subtype="
-                    + SubtypeLocale.getSubtypeDisplayName(currentSubtype));
+                    + SubtypeLocale.getSubtypeNameForLogging(currentSubtype));
             return false;
         }
         final int nextIndex = (currentIndex + 1) % enabledSubtypes.size();
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index 30df2eb..683211c 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -221,9 +221,11 @@
         return getSubtypeDisplayNameInternal(subtype, displayLocale);
     }
 
-    public static String getSubtypeDisplayName(final InputMethodSubtype subtype) {
-        final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(subtype.getLocale());
-        return getSubtypeDisplayNameInternal(subtype, displayLocale);
+    public static String getSubtypeNameForLogging(final InputMethodSubtype subtype) {
+        if (subtype == null) {
+            return "<null subtype>";
+        }
+        return getSubtypeLocale(subtype) + "/" + getKeyboardLayoutSetName(subtype);
     }
 
     private static String getSubtypeDisplayNameInternal(final InputMethodSubtype subtype,
@@ -288,4 +290,46 @@
         }
         return keyboardLayoutSet;
     }
+
+    // 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
+    //  es_US spanish F  Es  Español   Español (EE.UU.)       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
+    //  de    qwerty  T  De  Deutsch   Deutsch
+    //  en_US azerty  T  En  English   English (US)
+    //  zz    azerty  T      AZERTY    AZERTY
+
+    // Get InputMethodSubtype's full display name in its locale.
+    public static String getFullDisplayName(final InputMethodSubtype subtype) {
+        if (isNoLanguage(subtype)) {
+            return getKeyboardLayoutSetDisplayName(subtype);
+        }
+        return getSubtypeLocaleDisplayName(subtype.getLocale());
+    }
+
+    // Get InputMethodSubtype's middle display name in its locale.
+    public static String getMiddleDisplayName(final InputMethodSubtype subtype) {
+        if (isNoLanguage(subtype)) {
+            return getKeyboardLayoutSetDisplayName(subtype);
+        }
+        final Locale locale = getSubtypeLocale(subtype);
+        return getSubtypeLocaleDisplayName(locale.getLanguage());
+    }
+
+    // Get InputMethodSubtype's short display name in its locale.
+    public static String getShortDisplayName(final InputMethodSubtype subtype) {
+        if (isNoLanguage(subtype)) {
+            return "";
+        }
+        final Locale locale = getSubtypeLocale(subtype);
+        return StringUtils.capitalizeFirstCodePoint(locale.getLanguage(), locale);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 1eca68a..dfa4a86 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -153,7 +153,7 @@
     // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
     public void onSubtypeChanged(final InputMethodSubtype newSubtype) {
         if (DBG) {
-            Log.w(TAG, "onSubtypeChanged: " + SubtypeLocale.getSubtypeDisplayName(newSubtype));
+            Log.w(TAG, "onSubtypeChanged: " + SubtypeLocale.getSubtypeNameForLogging(newSubtype));
         }
 
         final Locale newLocale = SubtypeLocale.getSubtypeLocale(newSubtype);
diff --git a/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java b/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java
deleted file mode 100644
index 057a0c0..0000000
--- a/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * 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.test.suitebuilder.annotation.SmallTest;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.AdditionalSubtype;
-import com.android.inputmethod.latin.RichInputMethodManager;
-import com.android.inputmethod.latin.SubtypeLocale;
-import com.android.inputmethod.latin.utils.CollectionUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils.RunInLocale;
-import com.android.inputmethod.latin.utils.StringUtils;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-@SmallTest
-public class SpacebarTextTests extends AndroidTestCase {
-    // Locale to subtypes list.
-    private final ArrayList<InputMethodSubtype> mSubtypesList = CollectionUtils.newArrayList();
-
-    private RichInputMethodManager mRichImm;
-    private Resources mRes;
-
-    InputMethodSubtype EN_US;
-    InputMethodSubtype EN_GB;
-    InputMethodSubtype ES_US;
-    InputMethodSubtype FR;
-    InputMethodSubtype FR_CA;
-    InputMethodSubtype DE;
-    InputMethodSubtype ZZ;
-    InputMethodSubtype DE_QWERTY;
-    InputMethodSubtype FR_QWERTZ;
-    InputMethodSubtype US_AZERTY;
-    InputMethodSubtype ZZ_AZERTY;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        final Context context = getContext();
-        RichInputMethodManager.init(context);
-        mRichImm = RichInputMethodManager.getInstance();
-        mRes = context.getResources();
-        SubtypeLocale.init(context);
-
-        EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(Locale.US.toString(), "qwerty");
-        EN_GB = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(Locale.UK.toString(), "qwerty");
-        ES_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet("es_US", "spanish");
-        FR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(Locale.FRENCH.toString(), "azerty");
-        FR_CA = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.CANADA_FRENCH.toString(), "qwerty");
-        DE = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(Locale.GERMAN.toString(), "qwertz");
-        ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(SubtypeLocale.NO_LANGUAGE, "qwerty");
-        DE_QWERTY = AdditionalSubtype.createAdditionalSubtype(
-                Locale.GERMAN.toString(), "qwerty", null);
-        FR_QWERTZ = AdditionalSubtype.createAdditionalSubtype(
-                Locale.FRENCH.toString(), "qwertz", null);
-        US_AZERTY = AdditionalSubtype.createAdditionalSubtype(
-                Locale.US.toString(), "azerty", null);
-        ZZ_AZERTY = AdditionalSubtype.createAdditionalSubtype(
-                SubtypeLocale.NO_LANGUAGE, "azerty", null);
-    }
-
-    public void testAllFullDisplayName() {
-        for (final InputMethodSubtype subtype : mSubtypesList) {
-            final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype);
-            final String spacebarText = MainKeyboardView.getFullDisplayName(subtype);
-            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);
-            final String spacebarText = MainKeyboardView.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);
-            final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
-            final String spacebarText = MainKeyboardView.getShortDisplayName(subtype);
-            final String languageCode = StringUtils.capitalizeFirstCodePoint(
-                    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
-    //  es_US spanish F  Es  Español   Español (EE.UU.)       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
-    //  de    qwerty  T  De  Deutsch   Deutsch
-    //  en_US azerty  T  En  English   English (US)
-    //  zz    azerty  T      AZERTY    AZERTY
-
-    private final RunInLocale<Void> testsPredefinedSubtypes = new RunInLocale<Void>() {
-        @Override
-        protected Void job(Resources res) {
-            assertEquals("en_US", "English (US)",      MainKeyboardView.getFullDisplayName(EN_US));
-            assertEquals("en_GB", "English (UK)",      MainKeyboardView.getFullDisplayName(EN_GB));
-            assertEquals("es_US", "Español (EE.UU.)",  MainKeyboardView.getFullDisplayName(ES_US));
-            assertEquals("fr   ", "Français",          MainKeyboardView.getFullDisplayName(FR));
-            assertEquals("fr_CA", "Français (Canada)", MainKeyboardView.getFullDisplayName(FR_CA));
-            assertEquals("de   ", "Deutsch",           MainKeyboardView.getFullDisplayName(DE));
-            assertEquals("zz   ", "QWERTY",            MainKeyboardView.getFullDisplayName(ZZ));
-
-            assertEquals("en_US", "English",  MainKeyboardView.getMiddleDisplayName(EN_US));
-            assertEquals("en_GB", "English",  MainKeyboardView.getMiddleDisplayName(EN_GB));
-            assertEquals("es_US", "Español",  MainKeyboardView.getMiddleDisplayName(ES_US));
-            assertEquals("fr   ", "Français", MainKeyboardView.getMiddleDisplayName(FR));
-            assertEquals("fr_CA", "Français", MainKeyboardView.getMiddleDisplayName(FR_CA));
-            assertEquals("de   ", "Deutsch",  MainKeyboardView.getMiddleDisplayName(DE));
-            assertEquals("zz   ", "QWERTY",   MainKeyboardView.getMiddleDisplayName(ZZ));
-
-            assertEquals("en_US", "En", MainKeyboardView.getShortDisplayName(EN_US));
-            assertEquals("en_GB", "En", MainKeyboardView.getShortDisplayName(EN_GB));
-            assertEquals("es_US", "Es", MainKeyboardView.getShortDisplayName(ES_US));
-            assertEquals("fr   ", "Fr", MainKeyboardView.getShortDisplayName(FR));
-            assertEquals("fr_CA", "Fr", MainKeyboardView.getShortDisplayName(FR_CA));
-            assertEquals("de   ", "De", MainKeyboardView.getShortDisplayName(DE));
-            assertEquals("zz   ", "",   MainKeyboardView.getShortDisplayName(ZZ));
-            return null;
-        }
-    };
-
-    private final RunInLocale<Void> testsAdditionalSubtypes = new RunInLocale<Void>() {
-        @Override
-        protected Void job(Resources res) {
-            assertEquals("fr qwertz",    "Français",
-                    MainKeyboardView.getFullDisplayName(FR_QWERTZ));
-            assertEquals("de qwerty",    "Deutsch",
-                    MainKeyboardView.getFullDisplayName(DE_QWERTY));
-            assertEquals("en_US azerty", "English (US)",
-                    MainKeyboardView.getFullDisplayName(US_AZERTY));
-            assertEquals("zz azerty",    "AZERTY",
-                    MainKeyboardView.getFullDisplayName(ZZ_AZERTY));
-
-            assertEquals("fr qwertz",    "Français",
-                    MainKeyboardView.getMiddleDisplayName(FR_QWERTZ));
-            assertEquals("de qwerty",    "Deutsch",
-                    MainKeyboardView.getMiddleDisplayName(DE_QWERTY));
-            assertEquals("en_US azerty", "English",
-                    MainKeyboardView.getMiddleDisplayName(US_AZERTY));
-            assertEquals("zz azerty",    "AZERTY",
-                    MainKeyboardView.getMiddleDisplayName(ZZ_AZERTY));
-
-            assertEquals("fr qwertz",    "Fr", MainKeyboardView.getShortDisplayName(FR_QWERTZ));
-            assertEquals("de qwerty",    "De", MainKeyboardView.getShortDisplayName(DE_QWERTY));
-            assertEquals("en_US azerty", "En", MainKeyboardView.getShortDisplayName(US_AZERTY));
-            assertEquals("zz azerty",    "",   MainKeyboardView.getShortDisplayName(ZZ_AZERTY));
-            return null;
-        }
-    };
-
-    public void testPredefinedSubtypesInEnglish() {
-        testsPredefinedSubtypes.runInLocale(mRes, Locale.ENGLISH);
-    }
-
-    public void testAdditionalSubtypeInEnglish() {
-        testsAdditionalSubtypes.runInLocale(mRes, Locale.ENGLISH);
-    }
-
-    public void testPredefinedSubtypesInFrench() {
-        testsPredefinedSubtypes.runInLocale(mRes, Locale.FRENCH);
-    }
-
-    public void testAdditionalSubtypeInFrench() {
-        testsAdditionalSubtypes.runInLocale(mRes, Locale.FRENCH);
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
index b64013e..0548720 100644
--- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
+++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
@@ -24,6 +24,7 @@
 
 import com.android.inputmethod.latin.utils.CollectionUtils;
 import com.android.inputmethod.latin.utils.LocaleUtils.RunInLocale;
+import com.android.inputmethod.latin.utils.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Locale;
@@ -48,6 +49,7 @@
     InputMethodSubtype EN_US_AZERTY;
     InputMethodSubtype EN_UK_DVORAK;
     InputMethodSubtype ES_US_COLEMAK;
+    InputMethodSubtype ZZ_AZERTY;
     InputMethodSubtype ZZ_PC;
 
     @Override
@@ -83,6 +85,8 @@
                 Locale.UK.toString(), "dvorak", null);
         ES_US_COLEMAK = AdditionalSubtype.createAdditionalSubtype(
                 "es_US", "colemak", null);
+        ZZ_AZERTY = AdditionalSubtype.createAdditionalSubtype(
+                SubtypeLocale.NO_LANGUAGE, "azerty", null);
         ZZ_PC = AdditionalSubtype.createAdditionalSubtype(
                 SubtypeLocale.NO_LANGUAGE, "pcqwerty", null);
 
@@ -90,7 +94,7 @@
 
     public void testAllFullDisplayName() {
         for (final InputMethodSubtype subtype : mSubtypesList) {
-            final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype);
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayNameInSystemLocale(subtype);
             if (SubtypeLocale.isNoLanguage(subtype)) {
                 final String noLanguage = mRes.getString(R.string.subtype_no_language);
                 assertTrue(subtypeName, subtypeName.contains(noLanguage));
@@ -102,25 +106,7 @@
         }
     }
 
-    // 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
-    //  es_US spanish F  Español (EE.UU.)        exception
-    //  fr    azerty  F  Français
-    //  fr_CA qwerty  F  Français (Canada)
-    //  de    qwertz  F  Deutsch
-    //  zz    qwerty  F  No language (QWERTY)    in system locale
-    //  fr    qwertz  T  Français (QWERTZ)
-    //  de    qwerty  T  Deutsch (QWERTY)
-    //  en_US azerty  T  English (US) (AZERTY)   exception
-    //  en_UK dvorak  T  English (UK) (Dvorak)   exception
-    //  es_US colemak T  Español (EE.UU.) (Colemak)  exception
-    //  zz    pc      T  No language (PC)        in system locale
-
-    public void testPredefinedSubtypesInEnglish() {
+    public void testKeyboardLayoutSetName() {
         assertEquals("en_US", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_US));
         assertEquals("en_GB", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_GB));
         assertEquals("es_US", "spanish", SubtypeLocale.getKeyboardLayoutSetName(ES_US));
@@ -128,96 +114,6 @@
         assertEquals("fr_CA", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(FR_CA));
         assertEquals("de   ", "qwertz", SubtypeLocale.getKeyboardLayoutSetName(DE));
         assertEquals("zz   ", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ));
-
-        final RunInLocale<Void> tests = new RunInLocale<Void>() {
-            @Override
-            protected Void job(Resources res) {
-                assertEquals("en_US", "English (US)",
-                        SubtypeLocale.getSubtypeDisplayName(EN_US));
-                assertEquals("en_GB", "English (UK)",
-                        SubtypeLocale.getSubtypeDisplayName(EN_GB));
-                assertEquals("es_US", "Español (EE.UU.)",
-                        SubtypeLocale.getSubtypeDisplayName(ES_US));
-                assertEquals("fr   ", "Français",
-                        SubtypeLocale.getSubtypeDisplayName(FR));
-                assertEquals("fr_CA", "Français (Canada)",
-                        SubtypeLocale.getSubtypeDisplayName(FR_CA));
-                assertEquals("de   ", "Deutsch",
-                        SubtypeLocale.getSubtypeDisplayName(DE));
-                assertEquals("zz   ", "No language (QWERTY)",
-                        SubtypeLocale.getSubtypeDisplayName(ZZ));
-                return null;
-            }
-        };
-        tests.runInLocale(mRes, Locale.ENGLISH);
-    }
-
-    public void testAdditionalSubtypesInEnglish() {
-        final RunInLocale<Void> tests = new RunInLocale<Void>() {
-            @Override
-            protected Void job(Resources res) {
-                assertEquals("fr qwertz",    "Français (QWERTZ)",
-                        SubtypeLocale.getSubtypeDisplayName(FR_QWERTZ));
-                assertEquals("de qwerty",    "Deutsch (QWERTY)",
-                        SubtypeLocale.getSubtypeDisplayName(DE_QWERTY));
-                assertEquals("en_US azerty", "English (US) (AZERTY)",
-                        SubtypeLocale.getSubtypeDisplayName(EN_US_AZERTY));
-                assertEquals("en_UK dvorak", "English (UK) (Dvorak)",
-                        SubtypeLocale.getSubtypeDisplayName(EN_UK_DVORAK));
-                assertEquals("es_US colemak","Español (EE.UU.) (Colemak)",
-                        SubtypeLocale.getSubtypeDisplayName(ES_US_COLEMAK));
-                assertEquals("zz pc",        "No language (PC)",
-                        SubtypeLocale.getSubtypeDisplayName(ZZ_PC));
-                return null;
-            }
-        };
-        tests.runInLocale(mRes, Locale.ENGLISH);
-    }
-
-    public void testPredefinedSubtypesInFrench() {
-        final RunInLocale<Void> tests = new RunInLocale<Void>() {
-            @Override
-            protected Void job(Resources res) {
-                assertEquals("en_US", "English (US)",
-                        SubtypeLocale.getSubtypeDisplayName(EN_US));
-                assertEquals("en_GB", "English (UK)",
-                        SubtypeLocale.getSubtypeDisplayName(EN_GB));
-                assertEquals("es_US", "Español (EE.UU.)",
-                        SubtypeLocale.getSubtypeDisplayName(ES_US));
-                assertEquals("fr   ", "Français",
-                        SubtypeLocale.getSubtypeDisplayName(FR));
-                assertEquals("fr_CA", "Français (Canada)",
-                        SubtypeLocale.getSubtypeDisplayName(FR_CA));
-                assertEquals("de   ", "Deutsch",
-                        SubtypeLocale.getSubtypeDisplayName(DE));
-                assertEquals("zz   ", "Aucune langue (QWERTY)",
-                        SubtypeLocale.getSubtypeDisplayName(ZZ));
-                return null;
-            }
-        };
-        tests.runInLocale(mRes, Locale.FRENCH);
-    }
-
-    public void testAdditionalSubtypesInFrench() {
-        final RunInLocale<Void> tests = new RunInLocale<Void>() {
-            @Override
-            protected Void job(Resources res) {
-                assertEquals("fr qwertz",    "Français (QWERTZ)",
-                        SubtypeLocale.getSubtypeDisplayName(FR_QWERTZ));
-                assertEquals("de qwerty",    "Deutsch (QWERTY)",
-                        SubtypeLocale.getSubtypeDisplayName(DE_QWERTY));
-                assertEquals("en_US azerty", "English (US) (AZERTY)",
-                        SubtypeLocale.getSubtypeDisplayName(EN_US_AZERTY));
-                assertEquals("en_UK dvorak", "English (UK) (Dvorak)",
-                        SubtypeLocale.getSubtypeDisplayName(EN_UK_DVORAK));
-                assertEquals("es_US colemak","Español (EE.UU.) (Colemak)",
-                        SubtypeLocale.getSubtypeDisplayName(ES_US_COLEMAK));
-                assertEquals("zz azerty",    "Aucune langue (PC)",
-                        SubtypeLocale.getSubtypeDisplayName(ZZ_PC));
-                return null;
-            }
-        };
-        tests.runInLocale(mRes, Locale.FRENCH);
     }
 
     // InputMethodSubtype's display name in system locale (en_US).
@@ -239,14 +135,6 @@
     //  zz    pc      T  No language (PC)
 
     public void testPredefinedSubtypesInEnglishSystemLocale() {
-        assertEquals("en_US", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_US));
-        assertEquals("en_GB", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_GB));
-        assertEquals("es_US", "spanish", SubtypeLocale.getKeyboardLayoutSetName(ES_US));
-        assertEquals("fr   ", "azerty", SubtypeLocale.getKeyboardLayoutSetName(FR));
-        assertEquals("fr_CA", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(FR_CA));
-        assertEquals("de   ", "qwertz", SubtypeLocale.getKeyboardLayoutSetName(DE));
-        assertEquals("zz   ", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ));
-
         final RunInLocale<Void> tests = new RunInLocale<Void>() {
             @Override
             protected Void job(Resources res) {
@@ -355,4 +243,139 @@
         };
         tests.runInLocale(mRes, Locale.FRENCH);
     }
+
+    public void testAllFullDisplayNameForSpacebar() {
+        for (final InputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayNameInSystemLocale(subtype);
+            final String spacebarText = SubtypeLocale.getFullDisplayName(subtype);
+            final String languageName =
+                    SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale());
+            if (SubtypeLocale.isNoLanguage(subtype)) {
+                assertFalse(subtypeName, spacebarText.contains(languageName));
+            } else {
+                assertTrue(subtypeName, spacebarText.contains(languageName));
+            }
+        }
+    }
+
+   public void testAllMiddleDisplayNameForSpacebar() {
+        for (final InputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayNameInSystemLocale(subtype);
+            final String spacebarText = SubtypeLocale.getMiddleDisplayName(subtype);
+            if (SubtypeLocale.isNoLanguage(subtype)) {
+                assertEquals(subtypeName,
+                        SubtypeLocale.getKeyboardLayoutSetName(subtype), spacebarText);
+            } else {
+                assertEquals(subtypeName,
+                        SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale()),
+                        spacebarText);
+            }
+        }
+    }
+
+    public void testAllShortDisplayNameForSpacebar() {
+        for (final InputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocale.getSubtypeDisplayNameInSystemLocale(subtype);
+            final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+            final String spacebarText = SubtypeLocale.getShortDisplayName(subtype);
+            final String languageCode = StringUtils.capitalizeFirstCodePoint(
+                    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
+    //  es_US spanish F  Es  Español   Español (EE.UU.)       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
+    //  de    qwerty  T  De  Deutsch   Deutsch
+    //  en_US azerty  T  En  English   English (US)
+    //  zz    azerty  T      AZERTY    AZERTY
+
+    private final RunInLocale<Void> testsPredefinedSubtypesForSpacebar = new RunInLocale<Void>() {
+        @Override
+        protected Void job(Resources res) {
+            assertEquals("en_US", "English (US)",      SubtypeLocale.getFullDisplayName(EN_US));
+            assertEquals("en_GB", "English (UK)",      SubtypeLocale.getFullDisplayName(EN_GB));
+            assertEquals("es_US", "Español (EE.UU.)",  SubtypeLocale.getFullDisplayName(ES_US));
+            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("es_US", "Español",  SubtypeLocale.getMiddleDisplayName(ES_US));
+            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("es_US", "Es", SubtypeLocale.getShortDisplayName(ES_US));
+            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));
+            return null;
+        }
+    };
+
+    private final RunInLocale<Void> testsAdditionalSubtypesForSpacebar = new RunInLocale<Void>() {
+        @Override
+        protected Void job(Resources res) {
+            assertEquals("fr qwertz",    "Français",
+                    SubtypeLocale.getFullDisplayName(FR_QWERTZ));
+            assertEquals("de qwerty",    "Deutsch",
+                    SubtypeLocale.getFullDisplayName(DE_QWERTY));
+            assertEquals("en_US azerty", "English (US)",
+                    SubtypeLocale.getFullDisplayName(EN_US_AZERTY));
+            assertEquals("zz azerty",    "AZERTY",
+                    SubtypeLocale.getFullDisplayName(ZZ_AZERTY));
+
+            assertEquals("fr qwertz",    "Français",
+                    SubtypeLocale.getMiddleDisplayName(FR_QWERTZ));
+            assertEquals("de qwerty",    "Deutsch",
+                    SubtypeLocale.getMiddleDisplayName(DE_QWERTY));
+            assertEquals("en_US azerty", "English",
+                    SubtypeLocale.getMiddleDisplayName(EN_US_AZERTY));
+            assertEquals("zz azerty",    "AZERTY",
+                    SubtypeLocale.getMiddleDisplayName(ZZ_AZERTY));
+
+            assertEquals("fr qwertz",    "Fr", SubtypeLocale.getShortDisplayName(FR_QWERTZ));
+            assertEquals("de qwerty",    "De", SubtypeLocale.getShortDisplayName(DE_QWERTY));
+            assertEquals("en_US azerty", "En", SubtypeLocale.getShortDisplayName(EN_US_AZERTY));
+            assertEquals("zz azerty",    "",   SubtypeLocale.getShortDisplayName(ZZ_AZERTY));
+            return null;
+        }
+    };
+
+    public void testPredefinedSubtypesForSpacebarInEnglish() {
+        testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
+    }
+
+    public void testAdditionalSubtypeForSpacebarInEnglish() {
+        testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
+    }
+
+    public void testPredefinedSubtypesForSpacebarInFrench() {
+        testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
+    }
+
+    public void testAdditionalSubtypeForSpacebarInFrench() {
+        testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
+    }
 }