Do not turn on imes unexpectedly with unit tests

Bug: 7872918

Change-Id: Ie1d74c9fac27de140e7aa85f2eaefcb89aa06ea7
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 08e30aa..54c2ba5 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -81,6 +81,11 @@
     private boolean mIsAuxIme;
 
     /**
+     * Cavert: mForceDefault must be false for production. This flag is only for test.
+     */
+    private final boolean mForceDefault;
+
+    /**
      * Constructor.
      *
      * @param context The Context in which we are parsing the input method.
@@ -108,6 +113,7 @@
         ServiceInfo si = service.serviceInfo;
         mId = new ComponentName(si.packageName, si.name).flattenToShortString();
         mIsAuxIme = true;
+        mForceDefault = false;
 
         PackageManager pm = context.getPackageManager();
         String settingsActivityComponent = null;
@@ -215,13 +221,39 @@
         mIsAuxIme = source.readInt() == 1;
         mService = ResolveInfo.CREATOR.createFromParcel(source);
         source.readTypedList(mSubtypes, InputMethodSubtype.CREATOR);
+        mForceDefault = false;
     }
 
     /**
-     * Temporary API for creating a built-in input method.
+     * Temporary API for creating a built-in input method for test.
      */
     public InputMethodInfo(String packageName, String className,
             CharSequence label, String settingsActivity) {
+        this(buildDummyResolveInfo(packageName, className, label), false, settingsActivity, null,
+                0, false);
+    }
+
+    /**
+     * Temporary API for creating a built-in input method for test.
+     * @hide
+     */
+    public InputMethodInfo(ResolveInfo ri, boolean isAuxIme,
+            String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
+            boolean forceDefault) {
+        final ServiceInfo si = ri.serviceInfo;
+        mService = ri;
+        mId = new ComponentName(si.packageName, si.name).flattenToShortString();
+        mSettingsActivityName = settingsActivity;
+        mIsDefaultResId = isDefaultResId;
+        mIsAuxIme = isAuxIme;
+        if (subtypes != null) {
+            mSubtypes.addAll(subtypes);
+        }
+        mForceDefault = forceDefault;
+    }
+
+    private static ResolveInfo buildDummyResolveInfo(String packageName, String className,
+            CharSequence label) {
         ResolveInfo ri = new ResolveInfo();
         ServiceInfo si = new ServiceInfo();
         ApplicationInfo ai = new ApplicationInfo();
@@ -234,11 +266,7 @@
         si.exported = true;
         si.nonLocalizedLabel = label;
         ri.serviceInfo = si;
-        mService = ri;
-        mId = new ComponentName(si.packageName, si.name).flattenToShortString();
-        mSettingsActivityName = settingsActivity;
-        mIsDefaultResId = 0;
-        mIsAuxIme = false;
+        return ri;
     }
 
     /**
@@ -340,6 +368,22 @@
         return mIsDefaultResId;
     }
 
+    /**
+     * Return whether or not this ime is a default ime or not.
+     * @hide
+     */
+    public boolean isDefault(Context context) {
+        if (mForceDefault) {
+            return true;
+        }
+        try {
+            final Resources res = context.createPackageContext(getPackageName(), 0).getResources();
+            return res.getBoolean(getIsDefaultResourceId());
+        } catch (NameNotFoundException e) {
+            return false;
+        }
+    }
+
     public void dump(Printer pw, String prefix) {
         pw.println(prefix + "mId=" + mId
                 + " mSettingsActivityName=" + mSettingsActivityName);
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 3d7e1ff..655d148 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -59,11 +59,53 @@
                 & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
 
-    public static boolean isSystemImeThatHasEnglishSubtype(InputMethodInfo imi) {
+    public static boolean isSystemImeThatHasEnglishKeyboardSubtype(InputMethodInfo imi) {
         if (!isSystemIme(imi)) {
             return false;
         }
-        return containsSubtypeOf(imi, ENGLISH_LOCALE.getLanguage());
+        return containsSubtypeOf(imi, ENGLISH_LOCALE.getLanguage(), SUBTYPE_MODE_KEYBOARD);
+    }
+
+    private static boolean isSystemAuxilialyImeThatHashAutomaticSubtype(InputMethodInfo imi) {
+        if (!isSystemIme(imi)) {
+            return false;
+        }
+        if (!imi.isAuxiliaryIme()) {
+            return false;
+        }
+        final int subtypeCount = imi.getSubtypeCount();
+        for (int i = 0; i < subtypeCount; ++i) {
+            final InputMethodSubtype s = imi.getSubtypeAt(i);
+            if (s.overridesImplicitlyEnabledSubtype()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static ArrayList<InputMethodInfo> getDefaultEnabledImes(
+            Context context, boolean isSystemReady, ArrayList<InputMethodInfo> imis) {
+        final ArrayList<InputMethodInfo> retval = new ArrayList<InputMethodInfo>();
+        boolean auxilialyImeAdded = false;
+        for (int i = 0; i < imis.size(); ++i) {
+            final InputMethodInfo imi = imis.get(i);
+            if (isDefaultEnabledIme(isSystemReady, imi, context)) {
+                retval.add(imi);
+                if (imi.isAuxiliaryIme()) {
+                    auxilialyImeAdded = true;
+                }
+            }
+        }
+        if (auxilialyImeAdded) {
+            return retval;
+        }
+        for (int i = 0; i < imis.size(); ++i) {
+            final InputMethodInfo imi = imis.get(i);
+            if (isSystemAuxilialyImeThatHashAutomaticSubtype(imi)) {
+                retval.add(imi);
+            }
+        }
+        return retval;
     }
 
     // TODO: Rename isSystemDefaultImeThatHasCurrentLanguageSubtype
@@ -77,14 +119,11 @@
         }
         if (imi.getIsDefaultResourceId() != 0) {
             try {
-                Resources res = context.createPackageContext(
-                        imi.getPackageName(), 0).getResources();
-                if (res.getBoolean(imi.getIsDefaultResourceId())
-                        && containsSubtypeOf(imi, context.getResources().getConfiguration().
-                                locale.getLanguage())) {
+                if (imi.isDefault(context) && containsSubtypeOf(
+                        imi, context.getResources().getConfiguration().locale.getLanguage(),
+                        null /* mode */)) {
                     return true;
                 }
-            } catch (PackageManager.NameNotFoundException ex) {
             } catch (Resources.NotFoundException ex) {
             }
         }
@@ -97,15 +136,19 @@
     public static boolean isDefaultEnabledIme(
             boolean isSystemReady, InputMethodInfo imi, Context context) {
         return isValidSystemDefaultIme(isSystemReady, imi, context)
-                || isSystemImeThatHasEnglishSubtype(imi);
+                || isSystemImeThatHasEnglishKeyboardSubtype(imi);
     }
 
-    private static boolean containsSubtypeOf(InputMethodInfo imi, String language) {
+    private static boolean containsSubtypeOf(InputMethodInfo imi, String language, String mode) {
         final int N = imi.getSubtypeCount();
         for (int i = 0; i < N; ++i) {
-            if (imi.getSubtypeAt(i).getLocale().startsWith(language)) {
-                return true;
+            if (!imi.getSubtypeAt(i).getLocale().startsWith(language)) {
+                continue;
             }
+            if(!TextUtils.isEmpty(mode) && !imi.getSubtypeAt(i).getMode().equalsIgnoreCase(mode)) {
+                continue;
+            }
+            return true;
         }
         return false;
     }
@@ -141,7 +184,7 @@
             while (i > 0) {
                 i--;
                 final InputMethodInfo imi = enabledImes.get(i);
-                if (InputMethodUtils.isSystemImeThatHasEnglishSubtype(imi)
+                if (InputMethodUtils.isSystemImeThatHasEnglishKeyboardSubtype(imi)
                         && !imi.isAuxiliaryIme()) {
                     return imi;
                 }
diff --git a/core/tests/inputmethodtests/Android.mk b/core/tests/inputmethodtests/Android.mk
new file mode 100644
index 0000000..4631e65
--- /dev/null
+++ b/core/tests/inputmethodtests/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := \
+	$(call all-java-files-under, src)
+
+LOCAL_DX_FLAGS := --core-library
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests android-common frameworks-core-util-lib
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := FrameworksCoreInputMethodTests
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/inputmethodtests/AndroidManifest.xml b/core/tests/inputmethodtests/AndroidManifest.xml
new file mode 100644
index 0000000..7f0b1aa
--- /dev/null
+++ b/core/tests/inputmethodtests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          android:installLocation="internalOnly"
+          package="com.android.frameworks.coretests.inputmethod"
+          android:sharedUserId="android.uid.system">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+            android:targetPackage="com.android.frameworks.coretests.inputmethod"
+            android:label="Frameworks InputMethod Core Tests" />
+
+</manifest>
diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
new file mode 100755
index 0000000..5e123ec
--- /dev/null
+++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+  --rebuild ) echo Rebuild && rebuild=true;;
+  * ) com_opts+=($1);;
+  esac
+  shift
+done
+
+if [[ -z $ANDROID_PRODUCT_OUT && $rebuilld == true ]]; then
+  echo You must lunch before running this test.
+  exit 0
+fi
+
+if [[ $rebuild == true ]]; then
+  make -j4 FrameworksCoreInputMethodTests
+  TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreInputMethodTests.apk
+  COMMAND="adb install -r $TESTAPP"
+  echo $COMMAND
+  $COMMAND
+fi
+
+adb shell am instrument -w -e class android.os.InputMethodTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
new file mode 100644
index 0000000..0a2b50c
--- /dev/null
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2013 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 android.os;
+
+import com.android.internal.inputmethod.InputMethodUtils;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class InputMethodTest extends InstrumentationTestCase {
+    private static final boolean IS_AUX = true;
+    private static final boolean IS_DEFAULT = true;
+    private static final boolean IS_AUTO = true;
+
+    @SmallTest
+    public void testDefaultEnabledImesWithDefaultVoiceIme() throws Exception {
+        final Context context = getInstrumentation().getTargetContext();
+        final ArrayList<InputMethodInfo> imis = new ArrayList<InputMethodInfo>();
+        imis.add(createDefaultAutoDummyVoiceIme());
+        imis.add(createNonDefaultAutoDummyVoiceIme0());
+        imis.add(createNonDefaultAutoDummyVoiceIme1());
+        imis.add(createNonDefaultDummyVoiceIme2());
+        imis.add(createDefaultDummyEnUSKeyboardIme());
+        imis.add(createNonDefaultDummyJaJPKeyboardIme());
+        final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes(
+                context, true, imis);
+        assertEquals(2, enabledImis.size());
+        for (int i = 0; i < enabledImis.size(); ++i) {
+            final InputMethodInfo imi = enabledImis.get(0);
+            // "DummyDefaultAutoVoiceIme" and "DummyDefaultEnKeyboardIme"
+            if (imi.getPackageName().equals("DummyDefaultAutoVoiceIme")
+                    || imi.getPackageName().equals("DummyDefaultEnKeyboardIme")) {
+                continue;
+            } else {
+                fail("Invalid enabled subtype.");
+            }
+        }
+    }
+
+    @SmallTest
+    public void testDefaultEnabledImesWithOutDefaultVoiceIme() throws Exception {
+        final Context context = getInstrumentation().getTargetContext();
+        final ArrayList<InputMethodInfo> imis = new ArrayList<InputMethodInfo>();
+        imis.add(createNonDefaultAutoDummyVoiceIme0());
+        imis.add(createNonDefaultAutoDummyVoiceIme1());
+        imis.add(createNonDefaultDummyVoiceIme2());
+        imis.add(createDefaultDummyEnUSKeyboardIme());
+        imis.add(createNonDefaultDummyJaJPKeyboardIme());
+        final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes(
+                context, true, imis);
+        assertEquals(3, enabledImis.size());
+        for (int i = 0; i < enabledImis.size(); ++i) {
+            final InputMethodInfo imi = enabledImis.get(0);
+            // "DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1" and
+            // "DummyDefaultEnKeyboardIme"
+            if (imi.getPackageName().equals("DummyNonDefaultAutoVoiceIme0")
+                    || imi.getPackageName().equals("DummyNonDefaultAutoVoiceIme1")
+                    || imi.getPackageName().equals("DummyDefaultEnKeyboardIme")) {
+                continue;
+            } else {
+                fail("Invalid enabled subtype.");
+            }
+        }
+    }
+
+    private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name,
+            CharSequence label, boolean isAuxIme, boolean isDefault,
+            List<InputMethodSubtype> subtypes) {
+        final ResolveInfo ri = new ResolveInfo();
+        final ServiceInfo si = new ServiceInfo();
+        final ApplicationInfo ai = new ApplicationInfo();
+        ai.packageName = packageName;
+        ai.enabled = true;
+        ai.flags |= ApplicationInfo.FLAG_SYSTEM;
+        si.applicationInfo = ai;
+        si.enabled = true;
+        si.packageName = packageName;
+        si.name = name;
+        si.exported = true;
+        si.nonLocalizedLabel = label;
+        ri.serviceInfo = si;
+        return new InputMethodInfo(ri, isAuxIme, "", subtypes, 1, isDefault);
+    }
+
+    private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
+            boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
+        return new InputMethodSubtype(0, 0, locale, mode, "", isAuxiliary,
+                overridesImplicitlyEnabledSubtype);
+    }
+
+    private static InputMethodInfo createDefaultAutoDummyVoiceIme() {
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO));
+        subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
+        return createDummyInputMethodInfo("DummyDefaultAutoVoiceIme", "dummy.voice0",
+                "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes);
+    }
+
+    private static InputMethodInfo createNonDefaultAutoDummyVoiceIme0() {
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO));
+        subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
+        return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0", "dummy.voice1",
+                "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes);
+    }
+
+    private static InputMethodInfo createNonDefaultAutoDummyVoiceIme1() {
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO));
+        subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
+        return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1", "dummy.voice2",
+                "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes);
+    }
+
+    private static InputMethodInfo createNonDefaultDummyVoiceIme2() {
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
+        return createDummyInputMethodInfo("DummyNonDefaultVoiceIme2", "dummy.voice3",
+                "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes);
+    }
+
+    private static InputMethodInfo createDefaultDummyEnUSKeyboardIme() {
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        subtypes.add(createDummyInputMethodSubtype("en_US", "keyboard", !IS_AUX, !IS_AUTO));
+        return createDummyInputMethodInfo("DummyDefaultEnKeyboardIme", "dummy.keyboard0",
+                "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes);
+    }
+
+    private static InputMethodInfo createNonDefaultDummyJaJPKeyboardIme() {
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        subtypes.add(createDummyInputMethodSubtype("ja_JP", "keyboard", !IS_AUX, !IS_AUTO));
+        return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardIme", "dummy.keyboard1",
+                "DummyKeyboard1", !IS_AUX, !IS_DEFAULT, subtypes);
+    }
+}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 0f14265..1a8641b 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -511,7 +511,8 @@
                     }
                 }
 
-                buildInputMethodListLocked(mMethodList, mMethodMap);
+                buildInputMethodListLocked(
+                        mMethodList, mMethodMap, false /* resetDefaultEnabledIme */);
 
                 boolean changed = false;
 
@@ -671,9 +672,13 @@
 
         // Just checking if defaultImiId is empty or not
         final String defaultImiId = mSettings.getSelectedInputMethod();
+        if (DEBUG) {
+            Slog.d(TAG, "Initial default ime = " + defaultImiId);
+        }
         mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
 
-        buildInputMethodListLocked(mMethodList, mMethodMap);
+        buildInputMethodListLocked(mMethodList, mMethodMap,
+                !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
         mSettings.enableAllIMEsIfThereIsNoEnabledIME();
 
         if (!mImeSelectedOnBoot) {
@@ -726,7 +731,7 @@
         }
     }
 
-    private void resetAllInternalStateLocked(boolean updateOnlyWhenLocaleChanged) {
+    private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged) {
         if (!mSystemReady) {
             // not system ready
             return;
@@ -744,7 +749,8 @@
             }
             // InputMethodAndSubtypeListManager should be reset when the locale is changed.
             mImListManager = new InputMethodAndSubtypeListManager(mContext, this);
-            buildInputMethodListLocked(mMethodList, mMethodMap);
+            buildInputMethodListLocked(mMethodList, mMethodMap,
+                    updateOnlyWhenLocaleChanged /* resetDefaultEnabledIme */);
             if (!updateOnlyWhenLocaleChanged) {
                 final String selectedImiId = mSettings.getSelectedInputMethod();
                 if (TextUtils.isEmpty(selectedImiId)) {
@@ -814,7 +820,8 @@
                     mWindowManagerService.setOnHardKeyboardStatusChangeListener(
                             mHardKeyboardListener);
                 }
-                buildInputMethodListLocked(mMethodList, mMethodMap);
+                buildInputMethodListLocked(mMethodList, mMethodMap,
+                        !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
                 if (!mImeSelectedOnBoot) {
                     Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here.");
                     checkCurrentLocaleChangedLocked();
@@ -2147,7 +2154,8 @@
                         mFileManager.addInputMethodSubtypes(imi, subtypes);
                         final long ident = Binder.clearCallingIdentity();
                         try {
-                            buildInputMethodListLocked(mMethodList, mMethodMap);
+                            buildInputMethodListLocked(mMethodList, mMethodMap,
+                                    false /* resetDefaultEnabledIme */);
                         } finally {
                             Binder.restoreCallingIdentity(ident);
                         }
@@ -2397,9 +2405,10 @@
     }
 
     void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
-            HashMap<String, InputMethodInfo> map) {
+            HashMap<String, InputMethodInfo> map, boolean resetDefaultEnabledIme) {
         if (DEBUG) {
-            Slog.d(TAG, "--- re-buildInputMethodList " + ", \n ------ \n" + getStackTrace());
+            Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme
+                    + " \n ------ \n" + getStackTrace());
         }
         list.clear();
         map.clear();
@@ -2436,14 +2445,8 @@
                 final String id = p.getId();
                 map.put(id, p);
 
-                // Valid system default IMEs and IMEs that have English subtypes are enabled
-                // by default
-                if (InputMethodUtils.isDefaultEnabledIme(mSystemReady, p, mContext)) {
-                    setInputMethodEnabledLocked(id, true);
-                }
-
                 if (DEBUG) {
-                    Slog.d(TAG, "Found a third-party input method " + p);
+                    Slog.d(TAG, "Found an input method " + p);
                 }
 
             } catch (XmlPullParserException e) {
@@ -2453,6 +2456,18 @@
             }
         }
 
+        if (resetDefaultEnabledIme) {
+            final ArrayList<InputMethodInfo> defaultEnabledIme =
+                    InputMethodUtils.getDefaultEnabledImes(mContext, mSystemReady, list);
+            for (int i = 0; i < defaultEnabledIme.size(); ++i) {
+                final InputMethodInfo imi =  defaultEnabledIme.get(i);
+                if (DEBUG) {
+                    Slog.d(TAG, "--- enable ime = " + imi);
+                }
+                setInputMethodEnabledLocked(imi.getId(), true);
+            }
+        }
+
         final String defaultImiId = mSettings.getSelectedInputMethod();
         if (!TextUtils.isEmpty(defaultImiId)) {
             if (!map.containsKey(defaultImiId)) {