Loading core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java +74 −17 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.TreeMap; /** Loading Loading @@ -117,6 +118,24 @@ public class InputMethodSubtypeSwitchingController { + " mIsSystemLanguage=" + mIsSystemLanguage + "}"; } @Override public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof ImeSubtypeListItem) { final ImeSubtypeListItem that = (ImeSubtypeListItem)o; if (!Objects.equals(this.mImi, that.mImi)) { return false; } if (this.mSubtypeId != that.mSubtypeId) { return false; } return true; } return false; } } private static class InputMethodAndSubtypeList { Loading Loading @@ -276,7 +295,7 @@ public class InputMethodSubtypeSwitchingController { private final List<ImeSubtypeListItem> mImeSubtypeList; private final int[] mUsageHistoryOfSubtypeListItemIndex; public DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) { private DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) { mImeSubtypeList = imeSubtypeListItems; mUsageHistoryOfSubtypeListItemIndex = new int[mImeSubtypeList.size()]; final int N = mImeSubtypeList.size(); Loading Loading @@ -347,15 +366,53 @@ public class InputMethodSubtypeSwitchingController { @VisibleForTesting public static class ControllerImpl { // TODO: Switch to DynamicRotationList for smarter rotation. private final StaticRotationList mSwitchingAwareSubtypeList; private final StaticRotationList mSwitchingUnawareSubtypeList; private final DynamicRotationList mSwitchingAwareRotationList; private final StaticRotationList mSwitchingUnawareRotationList; public ControllerImpl(final List<ImeSubtypeListItem> sortedItems) { mSwitchingAwareSubtypeList = new StaticRotationList(filterImeSubtypeList(sortedItems, true /* supportsSwitchingToNextInputMethod */)); mSwitchingUnawareSubtypeList = new StaticRotationList(filterImeSubtypeList(sortedItems, false /* supportsSwitchingToNextInputMethod */)); public static ControllerImpl createFrom(final ControllerImpl currentInstance, final List<ImeSubtypeListItem> sortedEnabledItems) { DynamicRotationList switchingAwareRotationList = null; { final List<ImeSubtypeListItem> switchingAwareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, true /* supportsSwitchingToNextInputMethod */); if (currentInstance != null && currentInstance.mSwitchingAwareRotationList != null && Objects.equals(currentInstance.mSwitchingAwareRotationList.mImeSubtypeList, switchingAwareImeSubtypes)) { // Can reuse the current instance. switchingAwareRotationList = currentInstance.mSwitchingAwareRotationList; } if (switchingAwareRotationList == null) { switchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes); } } StaticRotationList switchingUnawareRotationList = null; { final List<ImeSubtypeListItem> switchingUnawareImeSubtypes = filterImeSubtypeList( sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */); if (currentInstance != null && currentInstance.mSwitchingUnawareRotationList != null && Objects.equals( currentInstance.mSwitchingUnawareRotationList.mImeSubtypeList, switchingUnawareImeSubtypes)) { // Can reuse the current instance. switchingUnawareRotationList = currentInstance.mSwitchingUnawareRotationList; } if (switchingUnawareRotationList == null) { switchingUnawareRotationList = new StaticRotationList(switchingUnawareImeSubtypes); } } return new ControllerImpl(switchingAwareRotationList, switchingUnawareRotationList); } private ControllerImpl(final DynamicRotationList switchingAwareRotationList, final StaticRotationList switchingUnawareRotationList) { mSwitchingAwareRotationList = switchingAwareRotationList; mSwitchingUnawareRotationList = switchingUnawareRotationList; } public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, InputMethodInfo imi, Loading @@ -364,10 +421,10 @@ public class InputMethodSubtypeSwitchingController { return null; } if (imi.supportsSwitchingToNextInputMethod()) { return mSwitchingAwareSubtypeList.getNextInputMethodLocked(onlyCurrentIme, imi, return mSwitchingAwareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi, subtype); } else { return mSwitchingUnawareSubtypeList.getNextInputMethodLocked(onlyCurrentIme, imi, return mSwitchingUnawareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi, subtype); } } Loading @@ -376,10 +433,9 @@ public class InputMethodSubtypeSwitchingController { if (imi == null) { return; } // TODO: Enable the following code when DynamicRotationList is enabled. // if (imi.supportsSwitchingToNextInputMethod()) { // mSwitchingAwareSubtypeList.onUserAction(imi, subtype); // } if (imi.supportsSwitchingToNextInputMethod()) { mSwitchingAwareRotationList.onUserAction(imi, subtype); } } private static List<ImeSubtypeListItem> filterImeSubtypeList( Loading Loading @@ -424,7 +480,8 @@ public class InputMethodSubtypeSwitchingController { public void resetCircularListLocked(Context context) { mSubtypeList = new InputMethodAndSubtypeList(context, mSettings); mController = new ControllerImpl(mSubtypeList.getSortedInputMethodAndSubtypeList()); mController = ControllerImpl.createFrom(mController, mSubtypeList.getSortedInputMethodAndSubtypeList()); } public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi, Loading core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java +26 −4 Original line number Diff line number Diff line Loading @@ -172,7 +172,8 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5); final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6); final ControllerImpl controller = new ControllerImpl(enabledItems); final ControllerImpl controller = ControllerImpl.createFrom( null /* currentInstance */, enabledItems); // switching-aware loop assertRotationOrder(controller, false /* onlyCurrentIme */, Loading Loading @@ -214,9 +215,8 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe disabledSubtypeUnawareIme, null); } // This test is disabled until DynamicRotationList is enabled. @SmallTest public void DISABLED_testControllerImplWithUserAction() throws Exception { public void testControllerImplWithUserAction() throws Exception { final List<ImeSubtypeListItem> enabledItems = createEnabledImeSubtypes(); final ImeSubtypeListItem latinIme_en_US = enabledItems.get(0); final ImeSubtypeListItem latinIme_fr = enabledItems.get(1); Loading @@ -226,7 +226,8 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5); final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6); final ControllerImpl controller = new ControllerImpl(enabledItems); final ControllerImpl controller = ControllerImpl.createFrom( null /* currentInstance */, enabledItems); // === switching-aware loop === assertRotationOrder(controller, false /* onlyCurrentIme */, Loading Loading @@ -272,5 +273,26 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe subtypeUnawareIme, null); assertNextInputMethod(controller, true /* onlyCurrentIme */, switchUnawareJapaneseIme_ja_JP, null); // Rotation order should be preserved when created with the same subtype list. final List<ImeSubtypeListItem> sameEnabledItems = createEnabledImeSubtypes(); final ControllerImpl newController = ControllerImpl.createFrom(controller, sameEnabledItems); assertRotationOrder(newController, false /* onlyCurrentIme */, japaneseIme_ja_JP, latinIme_fr, latinIme_en_US); assertRotationOrder(newController, false /* onlyCurrentIme */, switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme, switchUnawareJapaneseIme_ja_JP); // Rotation order should be initialized when created with a different subtype list. final List<ImeSubtypeListItem> differentEnabledItems = Arrays.asList( latinIme_en_US, latinIme_fr, switchingUnawarelatinIme_en_UK, switchUnawareJapaneseIme_ja_JP); final ControllerImpl anotherController = ControllerImpl.createFrom(controller, differentEnabledItems); assertRotationOrder(anotherController, false /* onlyCurrentIme */, latinIme_en_US, latinIme_fr); assertRotationOrder(anotherController, false /* onlyCurrentIme */, switchingUnawarelatinIme_en_UK, switchUnawareJapaneseIme_ja_JP); } } Loading
core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java +74 −17 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.TreeMap; /** Loading Loading @@ -117,6 +118,24 @@ public class InputMethodSubtypeSwitchingController { + " mIsSystemLanguage=" + mIsSystemLanguage + "}"; } @Override public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof ImeSubtypeListItem) { final ImeSubtypeListItem that = (ImeSubtypeListItem)o; if (!Objects.equals(this.mImi, that.mImi)) { return false; } if (this.mSubtypeId != that.mSubtypeId) { return false; } return true; } return false; } } private static class InputMethodAndSubtypeList { Loading Loading @@ -276,7 +295,7 @@ public class InputMethodSubtypeSwitchingController { private final List<ImeSubtypeListItem> mImeSubtypeList; private final int[] mUsageHistoryOfSubtypeListItemIndex; public DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) { private DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) { mImeSubtypeList = imeSubtypeListItems; mUsageHistoryOfSubtypeListItemIndex = new int[mImeSubtypeList.size()]; final int N = mImeSubtypeList.size(); Loading Loading @@ -347,15 +366,53 @@ public class InputMethodSubtypeSwitchingController { @VisibleForTesting public static class ControllerImpl { // TODO: Switch to DynamicRotationList for smarter rotation. private final StaticRotationList mSwitchingAwareSubtypeList; private final StaticRotationList mSwitchingUnawareSubtypeList; private final DynamicRotationList mSwitchingAwareRotationList; private final StaticRotationList mSwitchingUnawareRotationList; public ControllerImpl(final List<ImeSubtypeListItem> sortedItems) { mSwitchingAwareSubtypeList = new StaticRotationList(filterImeSubtypeList(sortedItems, true /* supportsSwitchingToNextInputMethod */)); mSwitchingUnawareSubtypeList = new StaticRotationList(filterImeSubtypeList(sortedItems, false /* supportsSwitchingToNextInputMethod */)); public static ControllerImpl createFrom(final ControllerImpl currentInstance, final List<ImeSubtypeListItem> sortedEnabledItems) { DynamicRotationList switchingAwareRotationList = null; { final List<ImeSubtypeListItem> switchingAwareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, true /* supportsSwitchingToNextInputMethod */); if (currentInstance != null && currentInstance.mSwitchingAwareRotationList != null && Objects.equals(currentInstance.mSwitchingAwareRotationList.mImeSubtypeList, switchingAwareImeSubtypes)) { // Can reuse the current instance. switchingAwareRotationList = currentInstance.mSwitchingAwareRotationList; } if (switchingAwareRotationList == null) { switchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes); } } StaticRotationList switchingUnawareRotationList = null; { final List<ImeSubtypeListItem> switchingUnawareImeSubtypes = filterImeSubtypeList( sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */); if (currentInstance != null && currentInstance.mSwitchingUnawareRotationList != null && Objects.equals( currentInstance.mSwitchingUnawareRotationList.mImeSubtypeList, switchingUnawareImeSubtypes)) { // Can reuse the current instance. switchingUnawareRotationList = currentInstance.mSwitchingUnawareRotationList; } if (switchingUnawareRotationList == null) { switchingUnawareRotationList = new StaticRotationList(switchingUnawareImeSubtypes); } } return new ControllerImpl(switchingAwareRotationList, switchingUnawareRotationList); } private ControllerImpl(final DynamicRotationList switchingAwareRotationList, final StaticRotationList switchingUnawareRotationList) { mSwitchingAwareRotationList = switchingAwareRotationList; mSwitchingUnawareRotationList = switchingUnawareRotationList; } public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, InputMethodInfo imi, Loading @@ -364,10 +421,10 @@ public class InputMethodSubtypeSwitchingController { return null; } if (imi.supportsSwitchingToNextInputMethod()) { return mSwitchingAwareSubtypeList.getNextInputMethodLocked(onlyCurrentIme, imi, return mSwitchingAwareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi, subtype); } else { return mSwitchingUnawareSubtypeList.getNextInputMethodLocked(onlyCurrentIme, imi, return mSwitchingUnawareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi, subtype); } } Loading @@ -376,10 +433,9 @@ public class InputMethodSubtypeSwitchingController { if (imi == null) { return; } // TODO: Enable the following code when DynamicRotationList is enabled. // if (imi.supportsSwitchingToNextInputMethod()) { // mSwitchingAwareSubtypeList.onUserAction(imi, subtype); // } if (imi.supportsSwitchingToNextInputMethod()) { mSwitchingAwareRotationList.onUserAction(imi, subtype); } } private static List<ImeSubtypeListItem> filterImeSubtypeList( Loading Loading @@ -424,7 +480,8 @@ public class InputMethodSubtypeSwitchingController { public void resetCircularListLocked(Context context) { mSubtypeList = new InputMethodAndSubtypeList(context, mSettings); mController = new ControllerImpl(mSubtypeList.getSortedInputMethodAndSubtypeList()); mController = ControllerImpl.createFrom(mController, mSubtypeList.getSortedInputMethodAndSubtypeList()); } public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi, Loading
core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java +26 −4 Original line number Diff line number Diff line Loading @@ -172,7 +172,8 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5); final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6); final ControllerImpl controller = new ControllerImpl(enabledItems); final ControllerImpl controller = ControllerImpl.createFrom( null /* currentInstance */, enabledItems); // switching-aware loop assertRotationOrder(controller, false /* onlyCurrentIme */, Loading Loading @@ -214,9 +215,8 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe disabledSubtypeUnawareIme, null); } // This test is disabled until DynamicRotationList is enabled. @SmallTest public void DISABLED_testControllerImplWithUserAction() throws Exception { public void testControllerImplWithUserAction() throws Exception { final List<ImeSubtypeListItem> enabledItems = createEnabledImeSubtypes(); final ImeSubtypeListItem latinIme_en_US = enabledItems.get(0); final ImeSubtypeListItem latinIme_fr = enabledItems.get(1); Loading @@ -226,7 +226,8 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5); final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6); final ControllerImpl controller = new ControllerImpl(enabledItems); final ControllerImpl controller = ControllerImpl.createFrom( null /* currentInstance */, enabledItems); // === switching-aware loop === assertRotationOrder(controller, false /* onlyCurrentIme */, Loading Loading @@ -272,5 +273,26 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe subtypeUnawareIme, null); assertNextInputMethod(controller, true /* onlyCurrentIme */, switchUnawareJapaneseIme_ja_JP, null); // Rotation order should be preserved when created with the same subtype list. final List<ImeSubtypeListItem> sameEnabledItems = createEnabledImeSubtypes(); final ControllerImpl newController = ControllerImpl.createFrom(controller, sameEnabledItems); assertRotationOrder(newController, false /* onlyCurrentIme */, japaneseIme_ja_JP, latinIme_fr, latinIme_en_US); assertRotationOrder(newController, false /* onlyCurrentIme */, switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme, switchUnawareJapaneseIme_ja_JP); // Rotation order should be initialized when created with a different subtype list. final List<ImeSubtypeListItem> differentEnabledItems = Arrays.asList( latinIme_en_US, latinIme_fr, switchingUnawarelatinIme_en_UK, switchUnawareJapaneseIme_ja_JP); final ControllerImpl anotherController = ControllerImpl.createFrom(controller, differentEnabledItems); assertRotationOrder(anotherController, false /* onlyCurrentIme */, latinIme_en_US, latinIme_fr); assertRotationOrder(anotherController, false /* onlyCurrentIme */, switchingUnawarelatinIme_en_UK, switchUnawareJapaneseIme_ja_JP); } }