Loading core/java/com/android/internal/inputmethod/InputMethodUtils.java +76 −2 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.content.res.Resources; import android.provider.Settings; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.provider.Settings.SettingNotFoundException; Loading @@ -28,6 +29,8 @@ import android.util.Pair; import android.util.Slog; import android.util.Slog; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype; import android.view.textservice.SpellCheckerInfo; import android.view.textservice.TextServicesManager; import java.util.ArrayList; import java.util.ArrayList; import java.util.HashMap; import java.util.HashMap; Loading Loading @@ -357,6 +360,78 @@ public class InputMethodUtils { return !subtype.isAuxiliary(); return !subtype.isAuxiliary(); } } public static void setNonSelectedSystemImesDisabledUntilUsed( PackageManager packageManager, List<InputMethodInfo> enabledImis) { if (DEBUG) { Slog.d(TAG, "setNonSelectedSystemImesDisabledUntilUsed"); } final String[] systemImesDisabledUntilUsed = Resources.getSystem().getStringArray( com.android.internal.R.array.config_disabledUntilUsedPreinstalledImes); if (systemImesDisabledUntilUsed == null || systemImesDisabledUntilUsed.length == 0) { return; } // Only the current spell checker should be treated as an enabled one. final SpellCheckerInfo currentSpellChecker = TextServicesManager.getInstance().getCurrentSpellChecker(); for (final String packageName : systemImesDisabledUntilUsed) { if (DEBUG) { Slog.d(TAG, "check " + packageName); } boolean enabledIme = false; for (int j = 0; j < enabledImis.size(); ++j) { final InputMethodInfo imi = enabledImis.get(j); if (packageName.equals(imi.getPackageName())) { enabledIme = true; break; } } if (enabledIme) { // enabled ime. skip continue; } if (currentSpellChecker != null && packageName.equals(currentSpellChecker.getPackageName())) { // enabled spell checker. skip if (DEBUG) { Slog.d(TAG, packageName + " is the current spell checker. skip"); } continue; } ApplicationInfo ai = null; try { ai = packageManager.getApplicationInfo(packageName, PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS); } catch (NameNotFoundException e) { Slog.w(TAG, "NameNotFoundException: " + packageName, e); } if (ai == null) { // No app found for packageName continue; } final boolean isSystemPackage = (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0; if (!isSystemPackage) { continue; } setDisabledUntilUsed(packageManager, packageName); } } private static void setDisabledUntilUsed(PackageManager packageManager, String packageName) { final int state = packageManager.getApplicationEnabledSetting(packageName); if (state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT || state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { if (DEBUG) { Slog.d(TAG, "Update state(" + packageName + "): DISABLED_UNTIL_USED"); } packageManager.setApplicationEnabledSetting(packageName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED, 0); } else { if (DEBUG) { Slog.d(TAG, packageName + " is already DISABLED_UNTIL_USED"); } } } /** /** * Utility class for putting and getting settings for InputMethod * Utility class for putting and getting settings for InputMethod * TODO: Move all putters and getters of settings to this class. * TODO: Move all putters and getters of settings to this class. Loading Loading @@ -405,8 +480,7 @@ public class InputMethodUtils { public void setCurrentUserId(int userId) { public void setCurrentUserId(int userId) { if (DEBUG) { if (DEBUG) { Slog.d(TAG, "--- Swtich the current user from " + mCurrentUserId + " to " Slog.d(TAG, "--- Swtich the current user from " + mCurrentUserId + " to " + userId); + userId + ", new ime = " + getSelectedInputMethod()); } } // IMMS settings are kept per user, so keep track of current user // IMMS settings are kept per user, so keep track of current user mCurrentUserId = userId; mCurrentUserId = userId; Loading core/res/res/values/config.xml +16 −0 Original line number Original line Diff line number Diff line Loading @@ -1108,4 +1108,20 @@ stream or master volumes. --> stream or master volumes. --> <bool name="config_useFixedVolume">false</bool> <bool name="config_useFixedVolume">false</bool> <!-- The list of IMEs which should be disabled until used. This function suppresses update notifications for these pre-installed apps. We need to set this configuration carefully that they should not have functionarities other than "IME" or "Spell Checker". In InputMethodManagerService, the listed IMEs are disabled until used when all of the following conditions are met. 1. Not selected as an enabled IME in the Settings 2. Not selected as a spell checker in the Settings 3. Installed 4. A pre-installed IME 5. Not enabled And the disabled_until_used state for an IME is released by InputMethodManagerService when the IME is selected as an enabled IME. --> <string-array name="config_disabledUntilUsedPreinstalledImes" translatable="false"> <item>com.android.inputmethod.latin</item> </string-array> </resources> </resources> core/res/res/values/symbols.xml +1 −0 Original line number Original line Diff line number Diff line Loading @@ -919,6 +919,7 @@ <java-symbol type="array" name="special_locale_names" /> <java-symbol type="array" name="special_locale_names" /> <java-symbol type="array" name="config_masterVolumeRamp" /> <java-symbol type="array" name="config_masterVolumeRamp" /> <java-symbol type="array" name="config_cdma_dun_supported_types" /> <java-symbol type="array" name="config_cdma_dun_supported_types" /> <java-symbol type="array" name="config_disabledUntilUsedPreinstalledImes" /> <java-symbol type="drawable" name="default_wallpaper" /> <java-symbol type="drawable" name="default_wallpaper" /> <java-symbol type="drawable" name="indicator_input_error" /> <java-symbol type="drawable" name="indicator_input_error" /> Loading services/java/com/android/server/InputMethodManagerService.java +16 −5 Original line number Original line Diff line number Diff line Loading @@ -705,7 +705,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @Override @Override public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) { synchronized(mMethodMap) { synchronized(mMethodMap) { checkCurrentLocaleChangedLocked(); resetStateIfCurrentLocaleChangedLocked(); } } } } }, filter); }, filter); Loading Loading @@ -781,7 +781,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } } } private void checkCurrentLocaleChangedLocked() { private void resetStateIfCurrentLocaleChangedLocked() { resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */, resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */, true /* resetDefaultImeLocked */); true /* resetDefaultImeLocked */); } } Loading @@ -791,12 +791,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // InputMethodFileManager should be reset when the user is changed // InputMethodFileManager should be reset when the user is changed mFileManager = new InputMethodFileManager(mMethodMap, newUserId); mFileManager = new InputMethodFileManager(mMethodMap, newUserId); final String defaultImiId = mSettings.getSelectedInputMethod(); final String defaultImiId = mSettings.getSelectedInputMethod(); final boolean needsToResetDefaultIme = TextUtils.isEmpty(defaultImiId); final boolean initialUserSwitch = TextUtils.isEmpty(defaultImiId); if (DEBUG) { if (DEBUG) { Slog.d(TAG, "Switch user: " + newUserId + " current ime = " + defaultImiId); Slog.d(TAG, "Switch user: " + newUserId + " current ime = " + defaultImiId); } } resetAllInternalStateLocked(false /* updateOnlyWhenLocaleChanged */, resetAllInternalStateLocked(false /* updateOnlyWhenLocaleChanged */, needsToResetDefaultIme); initialUserSwitch /* needsToResetDefaultIme */); if (initialUserSwitch) { InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mContext.getPackageManager(), mSettings.getEnabledInputMethodListLocked()); } } } @Override @Override Loading Loading @@ -838,7 +842,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub !mImeSelectedOnBoot /* resetDefaultEnabledIme */); !mImeSelectedOnBoot /* resetDefaultEnabledIme */); if (!mImeSelectedOnBoot) { if (!mImeSelectedOnBoot) { Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here."); Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here."); checkCurrentLocaleChangedLocked(); resetStateIfCurrentLocaleChangedLocked(); InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed( mContext.getPackageManager(), mSettings.getEnabledInputMethodListLocked()); } } mLastSystemLocale = mRes.getConfiguration().locale; mLastSystemLocale = mRes.getConfiguration().locale; try { try { Loading Loading @@ -1599,6 +1606,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mSettings.getCurrentUserId()); mSettings.getCurrentUserId()); if (ai != null && ai.enabledSetting if (ai != null && ai.enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { if (DEBUG) { Slog.d(TAG, "Update state(" + imm.getId() + "): DISABLED_UNTIL_USED -> DEFAULT"); } mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(), mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(), PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(), PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(), Loading Loading
core/java/com/android/internal/inputmethod/InputMethodUtils.java +76 −2 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.content.res.Resources; import android.provider.Settings; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.provider.Settings.SettingNotFoundException; Loading @@ -28,6 +29,8 @@ import android.util.Pair; import android.util.Slog; import android.util.Slog; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype; import android.view.textservice.SpellCheckerInfo; import android.view.textservice.TextServicesManager; import java.util.ArrayList; import java.util.ArrayList; import java.util.HashMap; import java.util.HashMap; Loading Loading @@ -357,6 +360,78 @@ public class InputMethodUtils { return !subtype.isAuxiliary(); return !subtype.isAuxiliary(); } } public static void setNonSelectedSystemImesDisabledUntilUsed( PackageManager packageManager, List<InputMethodInfo> enabledImis) { if (DEBUG) { Slog.d(TAG, "setNonSelectedSystemImesDisabledUntilUsed"); } final String[] systemImesDisabledUntilUsed = Resources.getSystem().getStringArray( com.android.internal.R.array.config_disabledUntilUsedPreinstalledImes); if (systemImesDisabledUntilUsed == null || systemImesDisabledUntilUsed.length == 0) { return; } // Only the current spell checker should be treated as an enabled one. final SpellCheckerInfo currentSpellChecker = TextServicesManager.getInstance().getCurrentSpellChecker(); for (final String packageName : systemImesDisabledUntilUsed) { if (DEBUG) { Slog.d(TAG, "check " + packageName); } boolean enabledIme = false; for (int j = 0; j < enabledImis.size(); ++j) { final InputMethodInfo imi = enabledImis.get(j); if (packageName.equals(imi.getPackageName())) { enabledIme = true; break; } } if (enabledIme) { // enabled ime. skip continue; } if (currentSpellChecker != null && packageName.equals(currentSpellChecker.getPackageName())) { // enabled spell checker. skip if (DEBUG) { Slog.d(TAG, packageName + " is the current spell checker. skip"); } continue; } ApplicationInfo ai = null; try { ai = packageManager.getApplicationInfo(packageName, PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS); } catch (NameNotFoundException e) { Slog.w(TAG, "NameNotFoundException: " + packageName, e); } if (ai == null) { // No app found for packageName continue; } final boolean isSystemPackage = (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0; if (!isSystemPackage) { continue; } setDisabledUntilUsed(packageManager, packageName); } } private static void setDisabledUntilUsed(PackageManager packageManager, String packageName) { final int state = packageManager.getApplicationEnabledSetting(packageName); if (state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT || state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { if (DEBUG) { Slog.d(TAG, "Update state(" + packageName + "): DISABLED_UNTIL_USED"); } packageManager.setApplicationEnabledSetting(packageName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED, 0); } else { if (DEBUG) { Slog.d(TAG, packageName + " is already DISABLED_UNTIL_USED"); } } } /** /** * Utility class for putting and getting settings for InputMethod * Utility class for putting and getting settings for InputMethod * TODO: Move all putters and getters of settings to this class. * TODO: Move all putters and getters of settings to this class. Loading Loading @@ -405,8 +480,7 @@ public class InputMethodUtils { public void setCurrentUserId(int userId) { public void setCurrentUserId(int userId) { if (DEBUG) { if (DEBUG) { Slog.d(TAG, "--- Swtich the current user from " + mCurrentUserId + " to " Slog.d(TAG, "--- Swtich the current user from " + mCurrentUserId + " to " + userId); + userId + ", new ime = " + getSelectedInputMethod()); } } // IMMS settings are kept per user, so keep track of current user // IMMS settings are kept per user, so keep track of current user mCurrentUserId = userId; mCurrentUserId = userId; Loading
core/res/res/values/config.xml +16 −0 Original line number Original line Diff line number Diff line Loading @@ -1108,4 +1108,20 @@ stream or master volumes. --> stream or master volumes. --> <bool name="config_useFixedVolume">false</bool> <bool name="config_useFixedVolume">false</bool> <!-- The list of IMEs which should be disabled until used. This function suppresses update notifications for these pre-installed apps. We need to set this configuration carefully that they should not have functionarities other than "IME" or "Spell Checker". In InputMethodManagerService, the listed IMEs are disabled until used when all of the following conditions are met. 1. Not selected as an enabled IME in the Settings 2. Not selected as a spell checker in the Settings 3. Installed 4. A pre-installed IME 5. Not enabled And the disabled_until_used state for an IME is released by InputMethodManagerService when the IME is selected as an enabled IME. --> <string-array name="config_disabledUntilUsedPreinstalledImes" translatable="false"> <item>com.android.inputmethod.latin</item> </string-array> </resources> </resources>
core/res/res/values/symbols.xml +1 −0 Original line number Original line Diff line number Diff line Loading @@ -919,6 +919,7 @@ <java-symbol type="array" name="special_locale_names" /> <java-symbol type="array" name="special_locale_names" /> <java-symbol type="array" name="config_masterVolumeRamp" /> <java-symbol type="array" name="config_masterVolumeRamp" /> <java-symbol type="array" name="config_cdma_dun_supported_types" /> <java-symbol type="array" name="config_cdma_dun_supported_types" /> <java-symbol type="array" name="config_disabledUntilUsedPreinstalledImes" /> <java-symbol type="drawable" name="default_wallpaper" /> <java-symbol type="drawable" name="default_wallpaper" /> <java-symbol type="drawable" name="indicator_input_error" /> <java-symbol type="drawable" name="indicator_input_error" /> Loading
services/java/com/android/server/InputMethodManagerService.java +16 −5 Original line number Original line Diff line number Diff line Loading @@ -705,7 +705,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @Override @Override public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) { synchronized(mMethodMap) { synchronized(mMethodMap) { checkCurrentLocaleChangedLocked(); resetStateIfCurrentLocaleChangedLocked(); } } } } }, filter); }, filter); Loading Loading @@ -781,7 +781,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } } } private void checkCurrentLocaleChangedLocked() { private void resetStateIfCurrentLocaleChangedLocked() { resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */, resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */, true /* resetDefaultImeLocked */); true /* resetDefaultImeLocked */); } } Loading @@ -791,12 +791,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // InputMethodFileManager should be reset when the user is changed // InputMethodFileManager should be reset when the user is changed mFileManager = new InputMethodFileManager(mMethodMap, newUserId); mFileManager = new InputMethodFileManager(mMethodMap, newUserId); final String defaultImiId = mSettings.getSelectedInputMethod(); final String defaultImiId = mSettings.getSelectedInputMethod(); final boolean needsToResetDefaultIme = TextUtils.isEmpty(defaultImiId); final boolean initialUserSwitch = TextUtils.isEmpty(defaultImiId); if (DEBUG) { if (DEBUG) { Slog.d(TAG, "Switch user: " + newUserId + " current ime = " + defaultImiId); Slog.d(TAG, "Switch user: " + newUserId + " current ime = " + defaultImiId); } } resetAllInternalStateLocked(false /* updateOnlyWhenLocaleChanged */, resetAllInternalStateLocked(false /* updateOnlyWhenLocaleChanged */, needsToResetDefaultIme); initialUserSwitch /* needsToResetDefaultIme */); if (initialUserSwitch) { InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mContext.getPackageManager(), mSettings.getEnabledInputMethodListLocked()); } } } @Override @Override Loading Loading @@ -838,7 +842,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub !mImeSelectedOnBoot /* resetDefaultEnabledIme */); !mImeSelectedOnBoot /* resetDefaultEnabledIme */); if (!mImeSelectedOnBoot) { if (!mImeSelectedOnBoot) { Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here."); Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here."); checkCurrentLocaleChangedLocked(); resetStateIfCurrentLocaleChangedLocked(); InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed( mContext.getPackageManager(), mSettings.getEnabledInputMethodListLocked()); } } mLastSystemLocale = mRes.getConfiguration().locale; mLastSystemLocale = mRes.getConfiguration().locale; try { try { Loading Loading @@ -1599,6 +1606,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mSettings.getCurrentUserId()); mSettings.getCurrentUserId()); if (ai != null && ai.enabledSetting if (ai != null && ai.enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { if (DEBUG) { Slog.d(TAG, "Update state(" + imm.getId() + "): DISABLED_UNTIL_USED -> DEFAULT"); } mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(), mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(), PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(), PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(), Loading