3939import android .app .Notification ;
4040import android .app .NotificationManager ;
4141import android .app .PendingIntent ;
42+ import android .content .BroadcastReceiver ;
4243import android .content .ComponentName ;
4344import android .content .ContentResolver ;
4445import android .content .Context ;
110111import java .util .HashMap ;
111112import java .util .HashSet ;
112113import java .util .List ;
114+ import java .util .Locale ;
113115import java .util .TreeMap ;
114116
115117/**
@@ -152,6 +154,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
152154 private static final String TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE =
153155 "EnabledWhenDefaultIsNotAsciiCapable" ;
154156 private static final String TAG_ASCII_CAPABLE = "AsciiCapable" ;
157+ private static final Locale ENGLISH_LOCALE = new Locale ("en" );
155158
156159 final Context mContext ;
157160 final Resources mRes ;
@@ -371,6 +374,7 @@ public String toString() {
371374 private View mSwitchingDialogTitleView ;
372375 private InputMethodInfo [] mIms ;
373376 private int [] mSubtypeIds ;
377+ private Locale mLastSystemLocale ;
374378
375379 class SettingsObserver extends ContentObserver {
376380 SettingsObserver (Handler handler ) {
@@ -586,6 +590,7 @@ public void executeMessage(Message msg) {
586590 mImeSwitcherNotification .vibrate = null ;
587591 Intent intent = new Intent (Settings .ACTION_SHOW_INPUT_METHOD_PICKER );
588592 mImeSwitchPendingIntent = PendingIntent .getBroadcast (mContext , 0 , intent , 0 );
593+ mLastSystemLocale = mRes .getConfiguration ().locale ;
589594
590595 mShowOngoingImeSwitcherForPhones = false ;
591596
@@ -612,32 +617,102 @@ public void executeMessage(Message msg) {
612617
613618 if (TextUtils .isEmpty (Settings .Secure .getString (
614619 mContext .getContentResolver (), Settings .Secure .DEFAULT_INPUT_METHOD ))) {
615- InputMethodInfo defIm = null ;
616- for (InputMethodInfo imi : mMethodList ) {
617- if (defIm == null && imi .getIsDefaultResourceId () != 0 ) {
618- try {
619- Resources res = context .createPackageContext (
620- imi .getPackageName (), 0 ).getResources ();
621- if (res .getBoolean (imi .getIsDefaultResourceId ())) {
622- defIm = imi ;
623- Slog .i (TAG , "Selected default: " + imi .getId ());
620+ resetDefaultImeLocked (context );
621+ }
622+
623+ mSettingsObserver = new SettingsObserver (mHandler );
624+ updateFromSettingsLocked ();
625+
626+ // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME
627+ // according to the new system locale.
628+ final IntentFilter filter = new IntentFilter ();
629+ filter .addAction (Intent .ACTION_LOCALE_CHANGED );
630+ mContext .registerReceiver (
631+ new BroadcastReceiver () {
632+ @ Override
633+ public void onReceive (Context context , Intent intent ) {
634+ synchronized (mMethodMap ) {
635+ checkCurrentLocaleChangedLocked ();
624636 }
625- } catch (PackageManager .NameNotFoundException ex ) {
626- } catch (Resources .NotFoundException ex ) {
627637 }
628- }
638+ }, filter );
639+ }
640+
641+ private void checkCurrentLocaleChangedLocked () {
642+ final Locale newLocale = mRes .getConfiguration ().locale ;
643+ if (newLocale != null && !newLocale .equals (mLastSystemLocale )) {
644+ if (DEBUG ) {
645+ Slog .i (TAG , "Locale has been changed to " + newLocale );
629646 }
630- if (defIm == null && mMethodList .size () > 0 ) {
631- defIm = getMostApplicableDefaultIMELocked ();
632- Slog .i (TAG , "No default found, using " + defIm .getId ());
647+ buildInputMethodListLocked (mMethodList , mMethodMap );
648+ // Reset the current ime to the proper one
649+ resetDefaultImeLocked (mContext );
650+ mLastSystemLocale = newLocale ;
651+ }
652+ }
653+
654+ private void resetDefaultImeLocked (Context context ) {
655+ // Do not reset the default (current) IME when it is a 3rd-party IME
656+ if (mCurMethodId != null && !isSystemIme (mMethodMap .get (mCurMethodId ))) {
657+ return ;
658+ }
659+
660+ InputMethodInfo defIm = null ;
661+ for (InputMethodInfo imi : mMethodList ) {
662+ if (defIm == null ) {
663+ if (isValidSystemDefaultIme (imi , context )) {
664+ defIm = imi ;
665+ Slog .i (TAG , "Selected default: " + imi .getId ());
666+ }
633667 }
634- if (defIm != null ) {
635- setSelectedInputMethodAndSubtypeLocked (defIm , NOT_A_SUBTYPE_ID , false );
668+ }
669+ if (defIm == null && mMethodList .size () > 0 ) {
670+ defIm = getMostApplicableDefaultIMELocked ();
671+ Slog .i (TAG , "No default found, using " + defIm .getId ());
672+ }
673+ if (defIm != null ) {
674+ setSelectedInputMethodAndSubtypeLocked (defIm , NOT_A_SUBTYPE_ID , false );
675+ }
676+ }
677+
678+ private static boolean isValidSystemDefaultIme (InputMethodInfo imi , Context context ) {
679+ if (!isSystemIme (imi )) {
680+ return false ;
681+ }
682+ if (imi .getIsDefaultResourceId () != 0 ) {
683+ try {
684+ Resources res = context .createPackageContext (
685+ imi .getPackageName (), 0 ).getResources ();
686+ if (res .getBoolean (imi .getIsDefaultResourceId ())
687+ && containsSubtypeOf (imi , context .getResources ().getConfiguration ().
688+ locale .getLanguage ())) {
689+ return true ;
690+ }
691+ } catch (PackageManager .NameNotFoundException ex ) {
692+ } catch (Resources .NotFoundException ex ) {
636693 }
637694 }
695+ if (imi .getSubtypeCount () == 0 ) {
696+ Slog .w (TAG , "Found no subtypes in a system IME: " + imi .getPackageName ());
697+ }
698+ return false ;
699+ }
638700
639- mSettingsObserver = new SettingsObserver (mHandler );
640- updateFromSettingsLocked ();
701+ private static boolean isSystemImeThatHasEnglishSubtype (InputMethodInfo imi ) {
702+ if (!isSystemIme (imi )) {
703+ return false ;
704+ }
705+ return containsSubtypeOf (imi , ENGLISH_LOCALE .getLanguage ());
706+ }
707+
708+ private static boolean containsSubtypeOf (InputMethodInfo imi , String language ) {
709+ final int N = imi .getSubtypeCount ();
710+ for (int i = 0 ; i < N ; ++i ) {
711+ if (imi .getSubtypeAt (i ).getLocale ().startsWith (language )) {
712+ return true ;
713+ }
714+ }
715+ return false ;
641716 }
642717
643718 @ Override
@@ -663,6 +738,7 @@ public void systemReady(StatusBarManagerService statusBar) {
663738 mContext .getSystemService (Context .KEYGUARD_SERVICE );
664739 mNotificationManager = (NotificationManager )
665740 mContext .getSystemService (Context .NOTIFICATION_SERVICE );
741+ mLastSystemLocale = mContext .getResources ().getConfiguration ().locale ;
666742 mStatusBar = statusBar ;
667743 statusBar .setIconVisibility ("ime" , false );
668744 updateImeWindowStatusLocked ();
@@ -2043,7 +2119,7 @@ public boolean handleMessage(Message msg) {
20432119 return false ;
20442120 }
20452121
2046- private boolean isSystemIme (InputMethodInfo inputMethod ) {
2122+ private static boolean isSystemIme (InputMethodInfo inputMethod ) {
20472123 return (inputMethod .getServiceInfo ().applicationInfo .flags
20482124 & ApplicationInfo .FLAG_SYSTEM ) != 0 ;
20492125 }
@@ -2139,9 +2215,11 @@ void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
21392215 final String id = p .getId ();
21402216 map .put (id , p );
21412217
2142- // System IMEs are enabled by default, unless there's a hard keyboard
2143- // and the system IME was explicitly disabled
2144- if (isSystemIme (p ) && (!haveHardKeyboard || disabledSysImes .indexOf (id ) < 0 )) {
2218+ // Valid system default IMEs and IMEs that have English subtypes are enabled
2219+ // by default, unless there's a hard keyboard and the system IME was explicitly
2220+ // disabled
2221+ if ((isValidSystemDefaultIme (p , mContext ) || isSystemImeThatHasEnglishSubtype (p ))
2222+ && (!haveHardKeyboard || disabledSysImes .indexOf (id ) < 0 )) {
21452223 setInputMethodEnabledLocked (id , true );
21462224 }
21472225
0 commit comments