Add Hinglish (hi_ZZ) subtype

Bug: 17169632
Change-Id: Ibee088d76c2b19f1d62a3c9c119452726e856ec8
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index b25a208..d4d6385 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -37,6 +37,12 @@
         <item>en_US</item>
         <item>en_GB</item>
         <item>es_US</item>
+        <item>hi_ZZ</item>
+    </string-array>
+
+    <!-- Subtype locale whose name should be displayed in Locale.ROOT. -->
+    <string-array name="subtype_locale_displayed_in_root_locale">
+        <item>hi_ZZ</item>
     </string-array>
 
     <!-- Generic subtype label -->
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index cb03260..c3f5cf4 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -184,6 +184,8 @@
     <!-- Description for Spanish (US) keyboard subtype [CHAR LIMIT=25]
          (US) should be an abbreviation of United States to fit in the CHAR LIMIT. -->
     <string name="subtype_es_US">Spanish (US)</string>
+    <!-- Description for Hinglish (https://en.wikipedia.org/wiki/Hinglish) keyboard subtype [CHAR LIMIT=25] -->
+    <string name="subtype_hi_ZZ">Hinglish</string>
     <!-- Description for English (UK) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
          (UK) should be an abbreviation of United Kingdom to fit in the CHAR LIMIT.
          This should be identical to subtype_en_GB aside from the trailing (%s). -->
@@ -196,6 +198,9 @@
          (US) should be an abbreviation of United Statesn to fit in the CHAR LIMIT.
          This should be identical to subtype_es_US aside from the trailing (%s). -->
     <string name="subtype_with_layout_es_US">Spanish (US) (<xliff:g id="KEYBOARD_LAYOUT" example="QWERTY">%s</xliff:g>)</string>
+    <!-- Description for Hinglish (https://en.wikipedia.org/wiki/Hinglish) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
+         This should be identical to subtype_hi_ZZ aside from the trailing (%s). -->
+    <string name="subtype_with_layout_hi_ZZ">Hinglish (<xliff:g id="KEYBOARD_LAYOUT" example="QWERTY">%s</xliff:g>)</string>
     <!-- Description for "LANGUAGE_NAME" (Traditional) keyboard subtype [CHAR LIMIT=25]
          (Traditional) can be an abbreviation to fit in the CHAR LIMIT. -->
     <string name="subtype_generic_traditional"><xliff:g id="LANGUAGE_NAME" example="Nepali">%s</xliff:g> (Traditional)</string>
diff --git a/java/res/xml/key_styles_currency.xml b/java/res/xml/key_styles_currency.xml
index cfe9a90..2ce6318 100644
--- a/java/res/xml/key_styles_currency.xml
+++ b/java/res/xml/key_styles_currency.xml
@@ -80,6 +80,7 @@
         </case>
         <!-- fa: Persian (Rial and Afgahni)
              hi: Hindi (Indian Rupee)
+             hi_ZZ: Hinglish (Indian Rupee)
              iw: Hebrew (New Sheqel)
              lo: Lao (Kip)
              mn: Mongolian (Tugrik)
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index d71e88b..74ac79f 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -52,6 +52,7 @@
     gl_ES: Galician (Spain)/spanish
     hi: Hindi/hindi
     hi: Hindi/hindi_compact
+    (hi_ZZ: Hinglish/qwerty)  # This is a preliminary keyboard layout.
     hr: Croatian/qwertz
     hu: Hungarian/qwertz
     hy_AM: Armenian (Armenia) Phonetic/armenian_phonetic
@@ -354,6 +355,16 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=hindi_compact,EmojiCapable"
             android:isAsciiCapable="false"
     />
+    <!-- TODO: This Hinglish keyboard is a preliminary layout.
+               This isn't based on the final specification. -->
+    <subtype android:icon="@drawable/ic_ime_switcher_dark"
+            android:label="@string/subtype_hi_ZZ"
+            android:subtypeId="0x352eb37c"
+            android:imeSubtypeLocale="hi_ZZ"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="AsciiCapable,KeyboardLayoutSet=qwerty,EmojiCapable"
+            android:isAsciiCapable="true"
+    />
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x35b7526a"
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
index 31bc549..0e3acff 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
@@ -94,7 +94,7 @@
         /*   8:22 */ "morekeys_n",
         /*   9:22 */ "single_quotes",
         /*  10:20 */ "morekeys_s",
-        /*  11:17 */ "keyspec_currency",
+        /*  11:18 */ "keyspec_currency",
         /*  12:14 */ "morekeys_y",
         /*  13:13 */ "morekeys_d",
         /*  14:12 */ "morekeys_z",
@@ -1874,6 +1874,15 @@
         /* additional_morekeys_symbols_0 */ "0",
     };
 
+    /* Locale hi_ZZ: Hindi (ZZ) */
+    private static final String[] TEXTS_hi_ZZ = {
+        /* morekeys_a ~ */
+        null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ morekeys_s */
+        // U+20B9: "₹" INDIAN RUPEE SIGN
+        /* keyspec_currency */ "\u20B9",
+    };
+
     /* Locale hr: Croatian */
     private static final String[] TEXTS_hr = {
         /* morekeys_a ~ */
@@ -3957,6 +3966,7 @@
         "fr"     , TEXTS_fr,    /*  13/ 62 French */
         "gl_ES"  , TEXTS_gl_ES, /*   7/  9 Gallegan (Spain) */
         "hi"     , TEXTS_hi,    /*  23/ 53 Hindi */
+        "hi_ZZ"  , TEXTS_hi_ZZ, /*   1/ 12 Hindi (ZZ) */
         "hr"     , TEXTS_hr,    /*   9/ 20 Croatian */
         "hu"     , TEXTS_hu,    /*   9/ 20 Hungarian */
         "hy_AM"  , TEXTS_hy_AM, /*   9/126 Armenian (Armenia) */
diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
index 351d014..0db4106 100644
--- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
@@ -30,6 +30,7 @@
 
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Locale;
 
 public final class SubtypeLocaleUtils {
@@ -52,6 +53,8 @@
     private static final HashMap<String, String> sKeyboardLayoutToDisplayNameMap = new HashMap<>();
     // Keyboard layout to subtype name resource id map.
     private static final HashMap<String, Integer> sKeyboardLayoutToNameIdsMap = new HashMap<>();
+    // Exceptional locale whose name should be displayed in Locale.ROOT.
+    static final HashSet<String> sExceptionalLocaleDisplayedInRootLocale = new HashSet<>();
     // Exceptional locale to subtype name resource id map.
     private static final HashMap<String, Integer> sExceptionalLocaleToNameIdsMap = new HashMap<>();
     // Exceptional locale to subtype name with layout resource id map.
@@ -106,6 +109,12 @@
             sKeyboardLayoutToNameIdsMap.put(key, noLanguageResId);
         }
 
+        final String[] excetionalLocaleInRootLocale = res.getStringArray(
+                R.array.subtype_locale_displayed_in_root_locale);
+        for (int i = 0; i < excetionalLocaleInRootLocale.length; i++) {
+            sExceptionalLocaleDisplayedInRootLocale.add(excetionalLocaleInRootLocale[i]);
+        }
+
         final String[] exceptionalLocales = res.getStringArray(
                 R.array.subtype_locale_exception_keys);
         for (int i = 0; i < exceptionalLocales.length; i++) {
@@ -157,6 +166,9 @@
         if (NO_LANGUAGE.equals(localeString)) {
             return sResources.getConfiguration().locale;
         }
+        if (sExceptionalLocaleDisplayedInRootLocale.contains(localeString)) {
+            return Locale.ROOT;
+        }
         return LocaleUtils.constructLocaleFromString(localeString);
     }
 
@@ -171,9 +183,15 @@
     }
 
     public static String getSubtypeLanguageDisplayName(final String localeString) {
-        final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
         final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
-        return getSubtypeLocaleDisplayNameInternal(locale.getLanguage(), displayLocale);
+        final String languageString;
+        if (sExceptionalLocaleDisplayedInRootLocale.contains(localeString)) {
+            languageString = localeString;
+        } else {
+            final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
+            languageString = locale.getLanguage();
+        }
+        return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale);
     }
 
     private static String getSubtypeLocaleDisplayNameInternal(final String localeString,