diff options
3 files changed, 56 insertions, 43 deletions
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java index efa3167..495d5c6 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java +++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java @@ -37,6 +37,10 @@ import java.util.TreeMap; /** * InputMethodSubtypeSwitchingController controls the switching behavior of the subtypes. + * <p> + * This class is designed to be used from and only from {@link InputMethodManagerService} by using + * {@link InputMethodManagerService#mMethodMap} as a global lock. + * </p> */ public class InputMethodSubtypeSwitchingController { private static final String TAG = InputMethodSubtypeSwitchingController.class.getSimpleName(); @@ -207,12 +211,11 @@ public class InputMethodSubtypeSwitchingController { } } - private final Object mLock = new Object(); private final InputMethodSettings mSettings; private InputMethodAndSubtypeList mSubtypeList; @VisibleForTesting - public static ImeSubtypeListItem getNextInputMethodImpl(List<ImeSubtypeListItem> imList, + public static ImeSubtypeListItem getNextInputMethodLockedImpl(List<ImeSubtypeListItem> imList, boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { if (imi == null) { return null; @@ -256,34 +259,34 @@ public class InputMethodSubtypeSwitchingController { return null; } - public InputMethodSubtypeSwitchingController(InputMethodSettings settings) { + private InputMethodSubtypeSwitchingController(InputMethodSettings settings, Context context) { mSettings = settings; + resetCircularListLocked(context); + } + + public static InputMethodSubtypeSwitchingController createInstanceLocked( + InputMethodSettings settings, Context context) { + return new InputMethodSubtypeSwitchingController(settings, context); } // TODO: write unit tests for this method and the logic that determines the next subtype - public void onCommitText(InputMethodInfo imi, InputMethodSubtype subtype) { + public void onCommitTextLocked(InputMethodInfo imi, InputMethodSubtype subtype) { // TODO: Implement this. } public void resetCircularListLocked(Context context) { - synchronized(mLock) { - mSubtypeList = new InputMethodAndSubtypeList(context, mSettings); - } + mSubtypeList = new InputMethodAndSubtypeList(context, mSettings); } - public ImeSubtypeListItem getNextInputMethod( + public ImeSubtypeListItem getNextInputMethodLocked( boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { - synchronized(mLock) { - return getNextInputMethodImpl(mSubtypeList.getSortedInputMethodAndSubtypeList(), - onlyCurrentIme, imi, subtype); - } + return getNextInputMethodLockedImpl(mSubtypeList.getSortedInputMethodAndSubtypeList(), + onlyCurrentIme, imi, subtype); } - public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList(boolean showSubtypes, + public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeListLocked(boolean showSubtypes, boolean inputShown, boolean isScreenLocked) { - synchronized(mLock) { - return mSubtypeList.getSortedInputMethodAndSubtypeList( - showSubtypes, inputShown, isScreenLocked); - } + return mSubtypeList.getSortedInputMethodAndSubtypeList( + showSubtypes, inputShown, isScreenLocked); } } diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java index 2a4d921..0f343b1 100644 --- a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java +++ b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java @@ -105,44 +105,44 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe // "switchAwareLatinIme/en_US" -> "switchAwareLatinIme/es_US" currentIme = imList.get(0); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(1), nextIme); // "switchAwareLatinIme/es_US" -> "switchAwareLatinIme/fr" currentIme = imList.get(1); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(2), nextIme); // "switchAwareLatinIme/fr" -> "switchAwareJapaneseIme/ja_JP" currentIme = imList.get(2); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(5), nextIme); // "switchAwareJapaneseIme/ja_JP" -> "switchAwareLatinIme/en_US" currentIme = imList.get(5); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(0), nextIme); // "nonSwitchAwareLatinIme/en_UK" -> "nonSwitchAwareLatinIme/hi" currentIme = imList.get(3); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(4), nextIme); // "nonSwitchAwareLatinIme/hi" -> "nonSwitchAwareJapaneseIme/ja_JP" currentIme = imList.get(4); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(6), nextIme); // "nonSwitchAwareJapaneseIme/ja_JP" -> "nonSwitchAwareLatinIme/en_UK" currentIme = imList.get(6); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(3), nextIme); @@ -158,46 +158,46 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe // "switchAwareLatinIme/en_US" -> "switchAwareLatinIme/es_US" currentIme = imList.get(0); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(1), nextIme); // "switchAwareLatinIme/es_US" -> "switchAwareLatinIme/fr" currentIme = imList.get(1); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(2), nextIme); // "switchAwareLatinIme/fr" -> "switchAwareLatinIme/en_US" currentIme = imList.get(2); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(0), nextIme); // "nonSwitchAwareLatinIme/en_UK" -> "nonSwitchAwareLatinIme/hi" currentIme = imList.get(3); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(4), nextIme); // "nonSwitchAwareLatinIme/hi" -> "switchAwareLatinIme/en_UK" currentIme = imList.get(4); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertEquals(imList.get(3), nextIme); // "switchAwareJapaneseIme/ja_JP" -> null currentIme = imList.get(5); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertNull(nextIme); // "nonSwitchAwareJapaneseIme/ja_JP" -> null currentIme = imList.get(6); - nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl( + nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodLockedImpl( imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype( currentIme.mSubtypeName.toString())); assertNull(nextIme); diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 2d270e7..fb69c86 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -692,8 +692,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mRes, context.getContentResolver(), mMethodMap, mMethodList, userId); updateCurrentProfileIds(); mFileManager = new InputMethodFileManager(mMethodMap, userId); - mSwitchingController = new InputMethodSubtypeSwitchingController(mSettings); - mSwitchingController.resetCircularListLocked(context); + synchronized (mMethodMap) { + mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( + mSettings, context); + } // Just checking if defaultImiId is empty or not final String defaultImiId = mSettings.getSelectedInputMethod(); @@ -702,17 +704,23 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId); - buildInputMethodListLocked(mMethodList, mMethodMap, - !mImeSelectedOnBoot /* resetDefaultEnabledIme */); + synchronized (mMethodMap) { + buildInputMethodListLocked(mMethodList, mMethodMap, + !mImeSelectedOnBoot /* resetDefaultEnabledIme */); + } mSettings.enableAllIMEsIfThereIsNoEnabledIME(); if (!mImeSelectedOnBoot) { Slog.w(TAG, "No IME selected. Choose the most applicable IME."); - resetDefaultImeLocked(context); + synchronized (mMethodMap) { + resetDefaultImeLocked(context); + } } mSettingsObserver = new SettingsObserver(mHandler); - updateFromSettingsLocked(true); + synchronized (mMethodMap) { + updateFromSettingsLocked(true); + } // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME // according to the new system locale. @@ -2174,7 +2182,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return false; } synchronized (mMethodMap) { - final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethod( + final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked( onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype); if (nextSubtype == null) { return false; @@ -2190,7 +2198,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return false; } synchronized (mMethodMap) { - final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethod( + final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked( false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype); if (nextSubtype == null) { return false; @@ -2273,9 +2281,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) { Slog.d(TAG, "Got the notification of commitText"); } - final InputMethodInfo imi = mMethodMap.get(mCurMethodId); - if (imi != null) { - mSwitchingController.onCommitText(imi, mCurrentSubtype); + synchronized (mMethodMap) { + final InputMethodInfo imi = mMethodMap.get(mCurMethodId); + if (imi != null) { + mSwitchingController.onCommitTextLocked(imi, mCurrentSubtype); + } } } @@ -2698,7 +2708,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub hideInputMethodMenuLocked(); final List<ImeSubtypeListItem> imList = - mSwitchingController.getSortedInputMethodAndSubtypeList( + mSwitchingController.getSortedInputMethodAndSubtypeListLocked( showSubtypes, mInputShown, isScreenLocked); if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) { |