Respect user settings for spell checking language if explicitly set

Bug: 5554116
Change-Id: I8c16d732af1fe713d30d97dfe829ff16653c7f34
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 87c3e9b..ebb2604 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -76,7 +76,7 @@
         mIds = new int[size];
         mSpellCheckSpans = new SpellCheckSpan[size];
 
-        setLocale(mTextView.getLocale());
+        setLocale(mTextView.getTextServicesLocale());
 
         mCookie = hashCode();
     }
@@ -173,7 +173,7 @@
     }
 
     public void spellCheck(int start, int end) {
-        final Locale locale = mTextView.getLocale();
+        final Locale locale = mTextView.getTextServicesLocale();
         if (mCurrentLocale == null || (!(mCurrentLocale.equals(locale)))) {
             setLocale(locale);
             // Re-check the entire text
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5833afd..add1591 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -133,6 +133,8 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
+import android.view.textservice.SpellCheckerSubtype;
+import android.view.textservice.TextServicesManager;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.RemoteViews.RemoteView;
 
@@ -8904,21 +8906,18 @@
     /**
      * This is a temporary method. Future versions may support multi-locale text.
      *
-     * @return The current locale used in this TextView, based on the current IME's locale,
-     * or the system default locale if this is not defined.
+     * @return The locale that should be used for a word iterator and a spell checker
+     * in this TextView, based on the current spell checker settings,
+     * the current IME's locale, or the system default locale.
      * @hide
      */
-    public Locale getLocale() {
+    public Locale getTextServicesLocale() {
         Locale locale = Locale.getDefault();
-        final InputMethodManager imm = InputMethodManager.peekInstance();
-        if (imm != null) {
-            final InputMethodSubtype currentInputMethodSubtype = imm.getCurrentInputMethodSubtype();
-            if (currentInputMethodSubtype != null) {
-                String localeString = currentInputMethodSubtype.getLocale();
-                if (!TextUtils.isEmpty(localeString)) {
-                    locale = new Locale(localeString);
-                }
-            }
+        final TextServicesManager textServicesManager = (TextServicesManager)
+                mContext.getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
+        final SpellCheckerSubtype subtype = textServicesManager.getCurrentSpellCheckerSubtype(true);
+        if (subtype != null) {
+            locale = new Locale(subtype.getLocale());
         }
         return locale;
     }
@@ -8933,7 +8932,7 @@
      */
     public WordIterator getWordIterator() {
         if (mWordIterator == null) {
-            mWordIterator = new WordIterator(getLocale());
+            mWordIterator = new WordIterator(getTextServicesLocale());
         }
         return mWordIterator;
     }
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index b042da6..af9152d 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -40,6 +40,8 @@
 import android.service.textservice.SpellCheckerService;
 import android.text.TextUtils;
 import android.util.Slog;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
 import android.view.textservice.SpellCheckerInfo;
 import android.view.textservice.SpellCheckerSubtype;
 
@@ -222,20 +224,40 @@
             if (hashCode == 0 && !allowImplicitlySelectedSubtype) {
                 return null;
             }
-            final String systemLocale =
-                    mContext.getResources().getConfiguration().locale.toString();
+            String candidateLocale = null;
+            if (hashCode == 0) {
+                // Spell checker language settings == "auto"
+                final InputMethodManager imm =
+                        (InputMethodManager)mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+                if (imm != null) {
+                    final InputMethodSubtype currentInputMethodSubtype =
+                            imm.getCurrentInputMethodSubtype();
+                    if (currentInputMethodSubtype != null) {
+                        final String localeString = currentInputMethodSubtype.getLocale();
+                        if (!TextUtils.isEmpty(localeString)) {
+                            // 1. Use keyboard locale if available in the spell checker
+                            candidateLocale = localeString;
+                        }
+                    }
+                }
+                if (candidateLocale == null) {
+                    // 2. Use System locale if available in the spell checker
+                    candidateLocale = mContext.getResources().getConfiguration().locale.toString();
+                }
+            }
             SpellCheckerSubtype candidate = null;
             for (int i = 0; i < sci.getSubtypeCount(); ++i) {
                 final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
                 if (hashCode == 0) {
-                    if (systemLocale.equals(locale)) {
+                    if (candidateLocale.equals(locale)) {
                         return scs;
                     } else if (candidate == null) {
                         final String scsLocale = scs.getLocale();
-                        if (systemLocale.length() >= 2
+                        if (candidateLocale.length() >= 2
                                 && scsLocale.length() >= 2
-                                && systemLocale.substring(0, 2).equals(
+                                && candidateLocale.substring(0, 2).equals(
                                         scsLocale.substring(0, 2))) {
+                            // Fall back to the applicable language
                             candidate = scs;
                         }
                     }
@@ -244,9 +266,13 @@
                         Slog.w(TAG, "Return subtype " + scs.hashCode() + ", input= " + locale
                                 + ", " + scs.getLocale());
                     }
+                    // 3. Use the user specified spell check language
                     return scs;
                 }
             }
+            // 4. Fall back to the applicable language and return it if not null
+            // 5. Simply just return it even if it's null which means we could find no suitable
+            // spell check languages
             return candidate;
         }
     }