Merge "Allow 3 letter language codes in InputMethodUtils."
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 63d018f..68260d2 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -262,6 +262,7 @@
         final List<InputMethodSubtype> subtypes = InputMethodUtils.getSubtypes(imi);
         final String systemLocale = res.getConfiguration().locale.toString();
         if (TextUtils.isEmpty(systemLocale)) return new ArrayList<InputMethodSubtype>();
+        final String systemLanguage = res.getConfiguration().locale.getLanguage();
         final HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap =
                 new HashMap<String, InputMethodSubtype>();
         final int N = subtypes.size();
@@ -282,15 +283,22 @@
             final InputMethodSubtype subtype = subtypes.get(i);
             final String locale = subtype.getLocale();
             final String mode = subtype.getMode();
+            final String language = getLanguageFromLocaleString(locale);
             // When system locale starts with subtype's locale, that subtype will be applicable
-            // for system locale
+            // for system locale. We need to make sure the languages are the same, to prevent
+            // locales like "fil" (Filipino) being matched by "fi" (Finnish).
+            //
             // For instance, it's clearly applicable for cases like system locale = en_US and
             // subtype = en, but it is not necessarily considered applicable for cases like system
             // locale = en and subtype = en_US.
+            //
             // We just call systemLocale.startsWith(locale) in this function because there is no
             // need to find applicable subtypes aggressively unlike
             // findLastResortApplicableSubtypeLocked.
-            if (systemLocale.startsWith(locale)) {
+            //
+            // TODO: This check is broken. It won't take scripts into account and doesn't
+            // account for the mandatory conversions performed by Locale#toString.
+            if (language.equals(systemLanguage) && systemLocale.startsWith(locale)) {
                 final InputMethodSubtype applicableSubtype = applicableModeAndSubtypesMap.get(mode);
                 // If more applicable subtypes are contained, skip.
                 if (applicableSubtype != null) {
@@ -335,6 +343,18 @@
     }
 
     /**
+     * Returns the language component of a given locale string.
+     */
+    private static String getLanguageFromLocaleString(String locale) {
+        final int idx = locale.indexOf('_');
+        if (idx < 0) {
+            return locale;
+        } else {
+            return locale.substring(0, idx);
+        }
+    }
+
+    /**
      * If there are no selected subtypes, tries finding the most applicable one according to the
      * given locale.
      * @param subtypes this function will search the most applicable subtype in subtypes
@@ -353,7 +373,7 @@
         if (TextUtils.isEmpty(locale)) {
             locale = res.getConfiguration().locale.toString();
         }
-        final String language = locale.substring(0, 2);
+        final String language = getLanguageFromLocaleString(locale);
         boolean partialMatchFound = false;
         InputMethodSubtype applicableSubtype = null;
         InputMethodSubtype firstMatchedModeSubtype = null;
@@ -361,6 +381,7 @@
         for (int i = 0; i < N; ++i) {
             InputMethodSubtype subtype = subtypes.get(i);
             final String subtypeLocale = subtype.getLocale();
+            final String subtypeLanguage = getLanguageFromLocaleString(subtypeLocale);
             // An applicable subtype should match "mode". If mode is null, mode will be ignored,
             // and all subtypes with all modes can be candidates.
             if (mode == null || subtypes.get(i).getMode().equalsIgnoreCase(mode)) {
@@ -371,7 +392,7 @@
                     // Exact match (e.g. system locale is "en_US" and subtype locale is "en_US")
                     applicableSubtype = subtype;
                     break;
-                } else if (!partialMatchFound && subtypeLocale.startsWith(language)) {
+                } else if (!partialMatchFound && language.equals(subtypeLanguage)) {
                     // Partial match (e.g. system locale is "en_US" and subtype locale is "en")
                     applicableSubtype = subtype;
                     partialMatchFound = true;