Loading services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java +149 −231 Original line number Diff line number Diff line Loading @@ -614,19 +614,18 @@ final class InputMethodSubtypeSwitchingController { } } @VisibleForTesting public static class ControllerImpl { @NonNull private final DynamicRotationList mSwitchingAwareRotationList; private DynamicRotationList mSwitchingAwareRotationList = new DynamicRotationList(Collections.emptyList()); @NonNull private final StaticRotationList mSwitchingUnawareRotationList; private StaticRotationList mSwitchingUnawareRotationList = new StaticRotationList(Collections.emptyList()); /** List of input methods and subtypes. */ @Nullable private final RotationList mRotationList; @NonNull private RotationList mRotationList = new RotationList(Collections.emptyList()); /** List of input methods and subtypes suitable for hardware keyboards. */ @Nullable private final RotationList mHardwareRotationList; @NonNull private RotationList mHardwareRotationList = new RotationList(Collections.emptyList()); /** * Whether there was a user action since the last input method and subtype switch. Loading @@ -634,81 +633,65 @@ final class InputMethodSubtypeSwitchingController { */ private boolean mUserActionSinceSwitch; @NonNull public static ControllerImpl createFrom(@Nullable ControllerImpl currentInstance, @NonNull List<ImeSubtypeListItem> sortedEnabledItems, /** * Updates the list of input methods and subtypes used for switching. If the given items are * equal to the existing ones (regardless of recency order), the update is skipped and the * current recency order is kept. Otherwise, the recency order is reset. * * @param sortedEnabledItems the sorted list of enabled input methods and subtypes. * @param hardwareKeyboardItems the unsorted list of enabled input method and subtypes * suitable for hardware keyboards. */ @VisibleForTesting void update(@NonNull List<ImeSubtypeListItem> sortedEnabledItems, @NonNull List<ImeSubtypeListItem> hardwareKeyboardItems) { final var switchingAwareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, true /* supportsSwitchingToNextInputMethod */); final var switchingUnawareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */); final DynamicRotationList switchingAwareRotationList; if (currentInstance != null && Objects.equals( currentInstance.mSwitchingAwareRotationList.mImeSubtypeList, if (!Objects.equals(mSwitchingAwareRotationList.mImeSubtypeList, switchingAwareImeSubtypes)) { // Can reuse the current instance. switchingAwareRotationList = currentInstance.mSwitchingAwareRotationList; } else { switchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes); mSwitchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes); } final StaticRotationList switchingUnawareRotationList; if (currentInstance != null && Objects.equals( currentInstance.mSwitchingUnawareRotationList.mImeSubtypeList, if (!Objects.equals(mSwitchingUnawareRotationList.mImeSubtypeList, switchingUnawareImeSubtypes)) { // Can reuse the current instance. switchingUnawareRotationList = currentInstance.mSwitchingUnawareRotationList; } else { switchingUnawareRotationList = new StaticRotationList(switchingUnawareImeSubtypes); mSwitchingUnawareRotationList = new StaticRotationList(switchingUnawareImeSubtypes); } final RotationList rotationList; if (!Flags.imeSwitcherRevamp()) { rotationList = null; } else if (currentInstance != null && currentInstance.mRotationList != null && Objects.equals( currentInstance.mRotationList.mItems, sortedEnabledItems)) { // Can reuse the current instance. rotationList = currentInstance.mRotationList; } else { rotationList = new RotationList(sortedEnabledItems); if (Flags.imeSwitcherRevamp() && !Objects.equals(mRotationList.mItems, sortedEnabledItems)) { mRotationList = new RotationList(sortedEnabledItems); } final RotationList hardwareRotationList; if (!Flags.imeSwitcherRevamp()) { hardwareRotationList = null; } else if (currentInstance != null && currentInstance.mHardwareRotationList != null && Objects.equals( currentInstance.mHardwareRotationList.mItems, hardwareKeyboardItems)) { // Can reuse the current instance. hardwareRotationList = currentInstance.mHardwareRotationList; } else { hardwareRotationList = new RotationList(hardwareKeyboardItems); if (Flags.imeSwitcherRevamp() && !Objects.equals(mHardwareRotationList.mItems, hardwareKeyboardItems)) { mHardwareRotationList = new RotationList(hardwareKeyboardItems); } return new ControllerImpl(switchingAwareRotationList, switchingUnawareRotationList, rotationList, hardwareRotationList); } private ControllerImpl(@NonNull DynamicRotationList switchingAwareRotationList, @NonNull StaticRotationList switchingUnawareRotationList, @Nullable RotationList rotationList, @Nullable RotationList hardwareRotationList) { mSwitchingAwareRotationList = switchingAwareRotationList; mSwitchingUnawareRotationList = switchingUnawareRotationList; mRotationList = rotationList; mHardwareRotationList = hardwareRotationList; } /** * Gets the next input method and subtype, starting from the given ones, in the given direction. * * <p>If the given input method and subtype are not found, this returns the most recent * input method and subtype.</p> * * @param onlyCurrentIme whether to consider only subtypes of the current input method. * @param imi the input method to find the next value from. * @param subtype the input method subtype to find the next value from, if any. * @param mode the switching mode. * @param forward whether to search search forwards or backwards in the list. * @return the next input method and subtype if found, otherwise {@code null}. */ @Nullable public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, @Nullable InputMethodInfo imi, @Nullable InputMethodSubtype subtype, @SwitchMode int mode, boolean forward) { if (imi == null) { return null; } if (Flags.imeSwitcherRevamp() && mRotationList != null) { if (Flags.imeSwitcherRevamp()) { return mRotationList.next(imi, subtype, onlyCurrentIme, isRecency(mode, forward), forward); } else if (imi.supportsSwitchingToNextInputMethod()) { Loading @@ -720,11 +703,25 @@ final class InputMethodSubtypeSwitchingController { } } /** * Gets the next input method and subtype suitable for hardware keyboards, starting from the * given ones, in the given direction. * * <p>If the given input method and subtype are not found, this returns the most recent * input method and subtype.</p> * * @param onlyCurrentIme whether to consider only subtypes of the current input method. * @param imi the input method to find the next value from. * @param subtype the input method subtype to find the next value from, if any. * @param mode the switching mode * @param forward whether to search search forwards or backwards in the list. * @return the next input method and subtype if found, otherwise {@code null}. */ @Nullable public ImeSubtypeListItem getNextInputMethodForHardware(boolean onlyCurrentIme, @NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype, @SwitchMode int mode, boolean forward) { if (Flags.imeSwitcherRevamp() && mHardwareRotationList != null) { if (Flags.imeSwitcherRevamp()) { return mHardwareRotationList.next(imi, subtype, onlyCurrentIme, isRecency(mode, forward), forward); } Loading @@ -744,12 +741,8 @@ final class InputMethodSubtypeSwitchingController { @Nullable InputMethodSubtype subtype) { boolean recencyUpdated = false; if (Flags.imeSwitcherRevamp()) { if (mRotationList != null) { recencyUpdated |= mRotationList.setMostRecent(imi, subtype); } if (mHardwareRotationList != null) { recencyUpdated |= mHardwareRotationList.setMostRecent(imi, subtype); } if (recencyUpdated) { mUserActionSinceSwitch = true; } Loading Loading @@ -798,103 +791,28 @@ final class InputMethodSubtypeSwitchingController { return result; } protected void dump(@NonNull Printer pw, @NonNull String prefix) { void dump(@NonNull Printer pw, @NonNull String prefix) { pw.println(prefix + "mSwitchingAwareRotationList:"); mSwitchingAwareRotationList.dump(pw, prefix + " "); pw.println(prefix + "mSwitchingUnawareRotationList:"); mSwitchingUnawareRotationList.dump(pw, prefix + " "); if (Flags.imeSwitcherRevamp()) { if (mRotationList != null) { pw.println(prefix + "mRotationList:"); mRotationList.dump(pw, prefix + " "); } if (mHardwareRotationList != null) { pw.println(prefix + "mHardwareRotationList:"); mHardwareRotationList.dump(pw, prefix + " "); } pw.println(prefix + "User action since last switch: " + mUserActionSinceSwitch); } } } @NonNull private ControllerImpl mController; InputMethodSubtypeSwitchingController() { mController = ControllerImpl.createFrom(null, Collections.emptyList(), Collections.emptyList()); } /** * Called when the user took an action that should update the recency of the current * input method and subtype in the switching list. * * @param imi the currently selected input method. * @param subtype the currently selected input method subtype, if any. * @see android.inputmethodservice.InputMethodServiceInternal#notifyUserActionIfNecessary() */ public void onUserActionLocked(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { mController.onUserActionLocked(imi, subtype); } /** Called when the input method and subtype was changed. */ public void onInputMethodSubtypeChanged() { mController.onInputMethodSubtypeChanged(); } public void resetCircularListLocked(@NonNull Context context, @NonNull InputMethodSettings settings) { mController = ControllerImpl.createFrom(mController, getSortedInputMethodAndSubtypeList( update(getSortedInputMethodAndSubtypeList( false /* includeAuxiliarySubtypes */, false /* isScreenLocked */, false /* forImeMenu */, context, settings), getInputMethodAndSubtypeListForHardwareKeyboard(context, settings)); } /** * Gets the next input method and subtype, starting from the given ones, in the given direction. * * <p>If the given input method and subtype are not found, this returns the most recent * input method and subtype.</p> * * @param onlyCurrentIme whether to consider only subtypes of the current input method. * @param imi the input method to find the next value from. * @param subtype the input method subtype to find the next value from, if any. * @param mode the switching mode. * @param forward whether to search search forwards or backwards in the list. * @return the next input method and subtype if found, otherwise {@code null}. */ @Nullable public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, @Nullable InputMethodInfo imi, @Nullable InputMethodSubtype subtype, @SwitchMode int mode, boolean forward) { return mController.getNextInputMethod(onlyCurrentIme, imi, subtype, mode, forward); } /** * Gets the next input method and subtype suitable for hardware keyboards, starting from the * given ones, in the given direction. * * <p>If the given input method and subtype are not found, this returns the most recent * input method and subtype.</p> * * @param onlyCurrentIme whether to consider only subtypes of the current input method. * @param imi the input method to find the next value from. * @param subtype the input method subtype to find the next value from, if any. * @param mode the switching mode * @param forward whether to search search forwards or backwards in the list. * @return the next input method and subtype if found, otherwise {@code null}. */ @Nullable public ImeSubtypeListItem getNextInputMethodForHardware(boolean onlyCurrentIme, @NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype, @SwitchMode int mode, boolean forward) { return mController.getNextInputMethodForHardware(onlyCurrentIme, imi, subtype, mode, forward); } public void dump(@NonNull Printer pw, @NonNull String prefix) { mController.dump(pw, prefix); } } services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java +73 −92 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java +149 −231 Original line number Diff line number Diff line Loading @@ -614,19 +614,18 @@ final class InputMethodSubtypeSwitchingController { } } @VisibleForTesting public static class ControllerImpl { @NonNull private final DynamicRotationList mSwitchingAwareRotationList; private DynamicRotationList mSwitchingAwareRotationList = new DynamicRotationList(Collections.emptyList()); @NonNull private final StaticRotationList mSwitchingUnawareRotationList; private StaticRotationList mSwitchingUnawareRotationList = new StaticRotationList(Collections.emptyList()); /** List of input methods and subtypes. */ @Nullable private final RotationList mRotationList; @NonNull private RotationList mRotationList = new RotationList(Collections.emptyList()); /** List of input methods and subtypes suitable for hardware keyboards. */ @Nullable private final RotationList mHardwareRotationList; @NonNull private RotationList mHardwareRotationList = new RotationList(Collections.emptyList()); /** * Whether there was a user action since the last input method and subtype switch. Loading @@ -634,81 +633,65 @@ final class InputMethodSubtypeSwitchingController { */ private boolean mUserActionSinceSwitch; @NonNull public static ControllerImpl createFrom(@Nullable ControllerImpl currentInstance, @NonNull List<ImeSubtypeListItem> sortedEnabledItems, /** * Updates the list of input methods and subtypes used for switching. If the given items are * equal to the existing ones (regardless of recency order), the update is skipped and the * current recency order is kept. Otherwise, the recency order is reset. * * @param sortedEnabledItems the sorted list of enabled input methods and subtypes. * @param hardwareKeyboardItems the unsorted list of enabled input method and subtypes * suitable for hardware keyboards. */ @VisibleForTesting void update(@NonNull List<ImeSubtypeListItem> sortedEnabledItems, @NonNull List<ImeSubtypeListItem> hardwareKeyboardItems) { final var switchingAwareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, true /* supportsSwitchingToNextInputMethod */); final var switchingUnawareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */); final DynamicRotationList switchingAwareRotationList; if (currentInstance != null && Objects.equals( currentInstance.mSwitchingAwareRotationList.mImeSubtypeList, if (!Objects.equals(mSwitchingAwareRotationList.mImeSubtypeList, switchingAwareImeSubtypes)) { // Can reuse the current instance. switchingAwareRotationList = currentInstance.mSwitchingAwareRotationList; } else { switchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes); mSwitchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes); } final StaticRotationList switchingUnawareRotationList; if (currentInstance != null && Objects.equals( currentInstance.mSwitchingUnawareRotationList.mImeSubtypeList, if (!Objects.equals(mSwitchingUnawareRotationList.mImeSubtypeList, switchingUnawareImeSubtypes)) { // Can reuse the current instance. switchingUnawareRotationList = currentInstance.mSwitchingUnawareRotationList; } else { switchingUnawareRotationList = new StaticRotationList(switchingUnawareImeSubtypes); mSwitchingUnawareRotationList = new StaticRotationList(switchingUnawareImeSubtypes); } final RotationList rotationList; if (!Flags.imeSwitcherRevamp()) { rotationList = null; } else if (currentInstance != null && currentInstance.mRotationList != null && Objects.equals( currentInstance.mRotationList.mItems, sortedEnabledItems)) { // Can reuse the current instance. rotationList = currentInstance.mRotationList; } else { rotationList = new RotationList(sortedEnabledItems); if (Flags.imeSwitcherRevamp() && !Objects.equals(mRotationList.mItems, sortedEnabledItems)) { mRotationList = new RotationList(sortedEnabledItems); } final RotationList hardwareRotationList; if (!Flags.imeSwitcherRevamp()) { hardwareRotationList = null; } else if (currentInstance != null && currentInstance.mHardwareRotationList != null && Objects.equals( currentInstance.mHardwareRotationList.mItems, hardwareKeyboardItems)) { // Can reuse the current instance. hardwareRotationList = currentInstance.mHardwareRotationList; } else { hardwareRotationList = new RotationList(hardwareKeyboardItems); if (Flags.imeSwitcherRevamp() && !Objects.equals(mHardwareRotationList.mItems, hardwareKeyboardItems)) { mHardwareRotationList = new RotationList(hardwareKeyboardItems); } return new ControllerImpl(switchingAwareRotationList, switchingUnawareRotationList, rotationList, hardwareRotationList); } private ControllerImpl(@NonNull DynamicRotationList switchingAwareRotationList, @NonNull StaticRotationList switchingUnawareRotationList, @Nullable RotationList rotationList, @Nullable RotationList hardwareRotationList) { mSwitchingAwareRotationList = switchingAwareRotationList; mSwitchingUnawareRotationList = switchingUnawareRotationList; mRotationList = rotationList; mHardwareRotationList = hardwareRotationList; } /** * Gets the next input method and subtype, starting from the given ones, in the given direction. * * <p>If the given input method and subtype are not found, this returns the most recent * input method and subtype.</p> * * @param onlyCurrentIme whether to consider only subtypes of the current input method. * @param imi the input method to find the next value from. * @param subtype the input method subtype to find the next value from, if any. * @param mode the switching mode. * @param forward whether to search search forwards or backwards in the list. * @return the next input method and subtype if found, otherwise {@code null}. */ @Nullable public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, @Nullable InputMethodInfo imi, @Nullable InputMethodSubtype subtype, @SwitchMode int mode, boolean forward) { if (imi == null) { return null; } if (Flags.imeSwitcherRevamp() && mRotationList != null) { if (Flags.imeSwitcherRevamp()) { return mRotationList.next(imi, subtype, onlyCurrentIme, isRecency(mode, forward), forward); } else if (imi.supportsSwitchingToNextInputMethod()) { Loading @@ -720,11 +703,25 @@ final class InputMethodSubtypeSwitchingController { } } /** * Gets the next input method and subtype suitable for hardware keyboards, starting from the * given ones, in the given direction. * * <p>If the given input method and subtype are not found, this returns the most recent * input method and subtype.</p> * * @param onlyCurrentIme whether to consider only subtypes of the current input method. * @param imi the input method to find the next value from. * @param subtype the input method subtype to find the next value from, if any. * @param mode the switching mode * @param forward whether to search search forwards or backwards in the list. * @return the next input method and subtype if found, otherwise {@code null}. */ @Nullable public ImeSubtypeListItem getNextInputMethodForHardware(boolean onlyCurrentIme, @NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype, @SwitchMode int mode, boolean forward) { if (Flags.imeSwitcherRevamp() && mHardwareRotationList != null) { if (Flags.imeSwitcherRevamp()) { return mHardwareRotationList.next(imi, subtype, onlyCurrentIme, isRecency(mode, forward), forward); } Loading @@ -744,12 +741,8 @@ final class InputMethodSubtypeSwitchingController { @Nullable InputMethodSubtype subtype) { boolean recencyUpdated = false; if (Flags.imeSwitcherRevamp()) { if (mRotationList != null) { recencyUpdated |= mRotationList.setMostRecent(imi, subtype); } if (mHardwareRotationList != null) { recencyUpdated |= mHardwareRotationList.setMostRecent(imi, subtype); } if (recencyUpdated) { mUserActionSinceSwitch = true; } Loading Loading @@ -798,103 +791,28 @@ final class InputMethodSubtypeSwitchingController { return result; } protected void dump(@NonNull Printer pw, @NonNull String prefix) { void dump(@NonNull Printer pw, @NonNull String prefix) { pw.println(prefix + "mSwitchingAwareRotationList:"); mSwitchingAwareRotationList.dump(pw, prefix + " "); pw.println(prefix + "mSwitchingUnawareRotationList:"); mSwitchingUnawareRotationList.dump(pw, prefix + " "); if (Flags.imeSwitcherRevamp()) { if (mRotationList != null) { pw.println(prefix + "mRotationList:"); mRotationList.dump(pw, prefix + " "); } if (mHardwareRotationList != null) { pw.println(prefix + "mHardwareRotationList:"); mHardwareRotationList.dump(pw, prefix + " "); } pw.println(prefix + "User action since last switch: " + mUserActionSinceSwitch); } } } @NonNull private ControllerImpl mController; InputMethodSubtypeSwitchingController() { mController = ControllerImpl.createFrom(null, Collections.emptyList(), Collections.emptyList()); } /** * Called when the user took an action that should update the recency of the current * input method and subtype in the switching list. * * @param imi the currently selected input method. * @param subtype the currently selected input method subtype, if any. * @see android.inputmethodservice.InputMethodServiceInternal#notifyUserActionIfNecessary() */ public void onUserActionLocked(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { mController.onUserActionLocked(imi, subtype); } /** Called when the input method and subtype was changed. */ public void onInputMethodSubtypeChanged() { mController.onInputMethodSubtypeChanged(); } public void resetCircularListLocked(@NonNull Context context, @NonNull InputMethodSettings settings) { mController = ControllerImpl.createFrom(mController, getSortedInputMethodAndSubtypeList( update(getSortedInputMethodAndSubtypeList( false /* includeAuxiliarySubtypes */, false /* isScreenLocked */, false /* forImeMenu */, context, settings), getInputMethodAndSubtypeListForHardwareKeyboard(context, settings)); } /** * Gets the next input method and subtype, starting from the given ones, in the given direction. * * <p>If the given input method and subtype are not found, this returns the most recent * input method and subtype.</p> * * @param onlyCurrentIme whether to consider only subtypes of the current input method. * @param imi the input method to find the next value from. * @param subtype the input method subtype to find the next value from, if any. * @param mode the switching mode. * @param forward whether to search search forwards or backwards in the list. * @return the next input method and subtype if found, otherwise {@code null}. */ @Nullable public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, @Nullable InputMethodInfo imi, @Nullable InputMethodSubtype subtype, @SwitchMode int mode, boolean forward) { return mController.getNextInputMethod(onlyCurrentIme, imi, subtype, mode, forward); } /** * Gets the next input method and subtype suitable for hardware keyboards, starting from the * given ones, in the given direction. * * <p>If the given input method and subtype are not found, this returns the most recent * input method and subtype.</p> * * @param onlyCurrentIme whether to consider only subtypes of the current input method. * @param imi the input method to find the next value from. * @param subtype the input method subtype to find the next value from, if any. * @param mode the switching mode * @param forward whether to search search forwards or backwards in the list. * @return the next input method and subtype if found, otherwise {@code null}. */ @Nullable public ImeSubtypeListItem getNextInputMethodForHardware(boolean onlyCurrentIme, @NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype, @SwitchMode int mode, boolean forward) { return mController.getNextInputMethodForHardware(onlyCurrentIme, imi, subtype, mode, forward); } public void dump(@NonNull Printer pw, @NonNull String prefix) { mController.dump(pw, prefix); } }
services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java +73 −92 File changed.Preview size limit exceeded, changes collapsed. Show changes