Loading services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +6 −7 Original line number Diff line number Diff line Loading @@ -1300,8 +1300,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId); mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(context, mSwitchingController = new InputMethodSubtypeSwitchingController(context, settings.getMethodMap(), settings.getUserId()); mHardwareKeyboardShortcutController = new HardwareKeyboardShortcutController(settings.getMethodMap(), Loading Loading @@ -3049,8 +3048,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (userId == mSwitchingController.getUserId()) { mSwitchingController.resetCircularListLocked(settings.getMethodMap()); } else { mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( mContext, settings.getMethodMap(), userId); mSwitchingController = new InputMethodSubtypeSwitchingController(mContext, settings.getMethodMap(), userId); } // TODO: Instantiate mHardwareKeyboardShortcutController for each user. if (userId == mHardwareKeyboardShortcutController.getUserId()) { Loading Loading @@ -5320,8 +5319,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (userId == mSwitchingController.getUserId()) { mSwitchingController.resetCircularListLocked(settings.getMethodMap()); } else { mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( mContext, settings.getMethodMap(), mCurrentUserId); mSwitchingController = new InputMethodSubtypeSwitchingController(mContext, settings.getMethodMap(), mCurrentUserId); } // TODO: Instantiate mHardwareKeyboardShortcutController for each user. if (userId == mHardwareKeyboardShortcutController.getUserId()) { Loading services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java +83 −96 Original line number Diff line number Diff line Loading @@ -48,15 +48,20 @@ final class InputMethodSubtypeSwitchingController { private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID; public static class ImeSubtypeListItem implements Comparable<ImeSubtypeListItem> { @NonNull public final CharSequence mImeName; @Nullable public final CharSequence mSubtypeName; @NonNull public final InputMethodInfo mImi; public final int mSubtypeId; public final boolean mIsSystemLocale; public final boolean mIsSystemLanguage; ImeSubtypeListItem(CharSequence imeName, CharSequence subtypeName, InputMethodInfo imi, int subtypeId, String subtypeLocale, String systemLocale) { ImeSubtypeListItem(@NonNull CharSequence imeName, @Nullable CharSequence subtypeName, @NonNull InputMethodInfo imi, int subtypeId, @Nullable String subtypeLocale, @NonNull String systemLocale) { mImeName = imeName; mSubtypeName = subtypeName; mImi = imi; Loading @@ -69,7 +74,6 @@ final class InputMethodSubtypeSwitchingController { if (mIsSystemLocale) { mIsSystemLanguage = true; } else { // TODO: Use Locale#getLanguage or Locale#toLanguageTag final String systemLanguage = LocaleUtils.getLanguageFromLocaleString( systemLocale); final String subtypeLanguage = LocaleUtils.getLanguageFromLocaleString( Loading Loading @@ -101,8 +105,9 @@ final class InputMethodSubtypeSwitchingController { * <li>{@link #mSubtypeName}</li> * <li>{@link #mImi} with {@link InputMethodInfo#getId()}</li> * </ol> * Note: this class has a natural ordering that is inconsistent with {@link #equals(Object). * This method doesn't compare {@link #mSubtypeId} but {@link #equals(Object)} does. * Note: this class has a natural ordering that is inconsistent with * {@link #equals(Object)}. This method doesn't compare {@link #mSubtypeId} but * {@link #equals(Object)} does. * * @param other the object to be compared. * @return a negative integer, zero, or positive integer as this object is less than, equal Loading Loading @@ -155,6 +160,7 @@ final class InputMethodSubtypeSwitchingController { } } @NonNull static List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList( boolean includeAuxiliarySubtypes, boolean isScreenLocked, boolean forImeMenu, @NonNull Context context, @NonNull InputMethodMap methodMap, Loading Loading @@ -190,7 +196,7 @@ final class InputMethodSubtypeSwitchingController { enabledSubtypeSet.add(String.valueOf(subtype.hashCode())); } final CharSequence imeLabel = imi.loadLabel(userAwareContext.getPackageManager()); if (enabledSubtypeSet.size() > 0) { if (!enabledSubtypeSet.isEmpty()) { final int subtypeCount = imi.getSubtypeCount(); if (DEBUG) { Slog.v(TAG, "Add subtypes: " + subtypeCount + ", " + imi.getId()); Loading Loading @@ -223,14 +229,18 @@ final class InputMethodSubtypeSwitchingController { return imList; } private static int calculateSubtypeId(InputMethodInfo imi, InputMethodSubtype subtype) { private static int calculateSubtypeId(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { return subtype != null ? SubtypeUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode()) : NOT_A_SUBTYPE_ID; } private static class StaticRotationList { @NonNull private final List<ImeSubtypeListItem> mImeSubtypeList; StaticRotationList(final List<ImeSubtypeListItem> imeSubtypeList) { StaticRotationList(@NonNull List<ImeSubtypeListItem> imeSubtypeList) { mImeSubtypeList = imeSubtypeList; } Loading @@ -242,24 +252,22 @@ final class InputMethodSubtypeSwitchingController { * does not have a subtype. * @return The index in the given list. -1 if not found. */ private int getIndex(InputMethodInfo imi, InputMethodSubtype subtype) { private int getIndex(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { final int currentSubtypeId = calculateSubtypeId(imi, subtype); final int numSubtypes = mImeSubtypeList.size(); for (int i = 0; i < numSubtypes; ++i) { final ImeSubtypeListItem isli = mImeSubtypeList.get(i); final ImeSubtypeListItem item = mImeSubtypeList.get(i); // Skip until the current IME/subtype is found. if (imi.equals(isli.mImi) && isli.mSubtypeId == currentSubtypeId) { if (imi.equals(item.mImi) && item.mSubtypeId == currentSubtypeId) { return i; } } return -1; } @Nullable public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { if (imi == null) { return null; } @NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { if (mImeSubtypeList.size() <= 1) { return null; } Loading @@ -282,22 +290,24 @@ final class InputMethodSubtypeSwitchingController { return null; } protected void dump(final Printer pw, final String prefix) { protected void dump(@NonNull Printer pw, @NonNull String prefix) { final int numSubtypes = mImeSubtypeList.size(); for (int i = 0; i < numSubtypes; ++i) { final int rank = i; final ImeSubtypeListItem item = mImeSubtypeList.get(i); for (int rank = 0; rank < numSubtypes; ++rank) { final ImeSubtypeListItem item = mImeSubtypeList.get(rank); pw.println(prefix + "rank=" + rank + " item=" + item); } } } private static class DynamicRotationList { private static final String TAG = DynamicRotationList.class.getSimpleName(); @NonNull private final List<ImeSubtypeListItem> mImeSubtypeList; @NonNull private final int[] mUsageHistoryOfSubtypeListItemIndex; private DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) { private DynamicRotationList(@NonNull List<ImeSubtypeListItem> imeSubtypeListItems) { mImeSubtypeList = imeSubtypeListItems; mUsageHistoryOfSubtypeListItemIndex = new int[mImeSubtypeList.size()]; final int numSubtypes = mImeSubtypeList.size(); Loading @@ -314,7 +324,8 @@ final class InputMethodSubtypeSwitchingController { * * @return -1 when the specified item doesn't belong to {@link #mImeSubtypeList} actually. */ private int getUsageRank(final InputMethodInfo imi, InputMethodSubtype subtype) { private int getUsageRank(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { final int currentSubtypeId = calculateSubtypeId(imi, subtype); final int numItems = mUsageHistoryOfSubtypeListItemIndex.length; for (int usageRank = 0; usageRank < numItems; usageRank++) { Loading @@ -330,7 +341,8 @@ final class InputMethodSubtypeSwitchingController { return -1; } public void onUserAction(InputMethodInfo imi, InputMethodSubtype subtype) { public void onUserAction(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { final int currentUsageRank = getUsageRank(imi, subtype); // Do nothing if currentUsageRank == -1 (not found), or currentUsageRank == 0 if (currentUsageRank <= 0) { Loading @@ -342,8 +354,9 @@ final class InputMethodSubtypeSwitchingController { mUsageHistoryOfSubtypeListItemIndex[0] = currentItemIndex; } @Nullable public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { @NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { int currentUsageRank = getUsageRank(imi, subtype); if (currentUsageRank < 0) { if (DEBUG) { Loading @@ -366,7 +379,7 @@ final class InputMethodSubtypeSwitchingController { return null; } protected void dump(final Printer pw, final String prefix) { protected void dump(@NonNull Printer pw, @NonNull String prefix) { for (int rank = 0; rank < mUsageHistoryOfSubtypeListItemIndex.length; ++rank) { final int index = mUsageHistoryOfSubtypeListItemIndex[rank]; final ImeSubtypeListItem item = mImeSubtypeList.get(index); Loading @@ -377,58 +390,52 @@ final class InputMethodSubtypeSwitchingController { @VisibleForTesting public static class ControllerImpl { @NonNull private final DynamicRotationList mSwitchingAwareRotationList; @NonNull private final StaticRotationList mSwitchingUnawareRotationList; public static ControllerImpl createFrom(final ControllerImpl currentInstance, final List<ImeSubtypeListItem> sortedEnabledItems) { DynamicRotationList switchingAwareRotationList = null; { final List<ImeSubtypeListItem> switchingAwareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, @NonNull public static ControllerImpl createFrom(@Nullable ControllerImpl currentInstance, @NonNull List<ImeSubtypeListItem> sortedEnabledItems) { final var switchingAwareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, true /* supportsSwitchingToNextInputMethod */); if (currentInstance != null && currentInstance.mSwitchingAwareRotationList != null && Objects.equals( final var switchingUnawareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */); final DynamicRotationList switchingAwareRotationList; if (currentInstance != null && Objects.equals( currentInstance.mSwitchingAwareRotationList.mImeSubtypeList, switchingAwareImeSubtypes)) { // Can reuse the current instance. switchingAwareRotationList = currentInstance.mSwitchingAwareRotationList; } if (switchingAwareRotationList == null) { } else { switchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes); } } StaticRotationList switchingUnawareRotationList = null; { final List<ImeSubtypeListItem> switchingUnawareImeSubtypes = filterImeSubtypeList( sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */); if (currentInstance != null && currentInstance.mSwitchingUnawareRotationList != null && Objects.equals( final StaticRotationList switchingUnawareRotationList; if (currentInstance != null && Objects.equals( currentInstance.mSwitchingUnawareRotationList.mImeSubtypeList, switchingUnawareImeSubtypes)) { // Can reuse the current instance. switchingUnawareRotationList = currentInstance.mSwitchingUnawareRotationList; } if (switchingUnawareRotationList == null) { switchingUnawareRotationList = new StaticRotationList(switchingUnawareImeSubtypes); } } else { switchingUnawareRotationList = new StaticRotationList(switchingUnawareImeSubtypes); } return new ControllerImpl(switchingAwareRotationList, switchingUnawareRotationList); } private ControllerImpl(final DynamicRotationList switchingAwareRotationList, final StaticRotationList switchingUnawareRotationList) { private ControllerImpl(@NonNull DynamicRotationList switchingAwareRotationList, @NonNull StaticRotationList switchingUnawareRotationList) { mSwitchingAwareRotationList = switchingAwareRotationList; mSwitchingUnawareRotationList = switchingUnawareRotationList; } public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { @Nullable public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, @Nullable InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { if (imi == null) { return null; } Loading @@ -441,18 +448,17 @@ final class InputMethodSubtypeSwitchingController { } } public void onUserActionLocked(InputMethodInfo imi, InputMethodSubtype subtype) { if (imi == null) { return; } public void onUserActionLocked(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { if (imi.supportsSwitchingToNextInputMethod()) { mSwitchingAwareRotationList.onUserAction(imi, subtype); } } @NonNull private static List<ImeSubtypeListItem> filterImeSubtypeList( final List<ImeSubtypeListItem> items, final boolean supportsSwitchingToNextInputMethod) { @NonNull List<ImeSubtypeListItem> items, boolean supportsSwitchingToNextInputMethod) { final ArrayList<ImeSubtypeListItem> result = new ArrayList<>(); final int numItems = items.size(); for (int i = 0; i < numItems; i++) { Loading @@ -473,12 +479,14 @@ final class InputMethodSubtypeSwitchingController { } } @NonNull private final Context mContext; @UserIdInt private final int mUserId; @NonNull private ControllerImpl mController; private InputMethodSubtypeSwitchingController(@NonNull Context context, InputMethodSubtypeSwitchingController(@NonNull Context context, @NonNull InputMethodMap methodMap, @UserIdInt int userId) { mContext = context; mUserId = userId; Loading @@ -488,26 +496,14 @@ final class InputMethodSubtypeSwitchingController { false /* forImeMenu */, context, methodMap, userId)); } @NonNull public static InputMethodSubtypeSwitchingController createInstanceLocked( @NonNull Context context, @NonNull InputMethodMap methodMap, @UserIdInt int userId) { return new InputMethodSubtypeSwitchingController(context, methodMap, userId); } @AnyThread @UserIdInt int getUserId() { return mUserId; } public void onUserActionLocked(InputMethodInfo imi, InputMethodSubtype subtype) { if (mController == null) { if (DEBUG) { Slog.e(TAG, "mController shouldn't be null."); } return; } public void onUserActionLocked(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { mController.onUserActionLocked(imi, subtype); } Loading @@ -518,22 +514,13 @@ final class InputMethodSubtypeSwitchingController { false /* forImeMenu */, mContext, methodMap, mUserId)); } public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { if (mController == null) { if (DEBUG) { Slog.e(TAG, "mController shouldn't be null."); } return null; } @Nullable public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, @Nullable InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { return mController.getNextInputMethod(onlyCurrentIme, imi, subtype); } public void dump(@NonNull Printer pw, @NonNull String prefix) { if (mController != null) { mController.dump(pw, prefix); } else { pw.println(prefix + "mController=null"); } } } services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java +127 −120 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +6 −7 Original line number Diff line number Diff line Loading @@ -1300,8 +1300,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId); mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(context, mSwitchingController = new InputMethodSubtypeSwitchingController(context, settings.getMethodMap(), settings.getUserId()); mHardwareKeyboardShortcutController = new HardwareKeyboardShortcutController(settings.getMethodMap(), Loading Loading @@ -3049,8 +3048,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (userId == mSwitchingController.getUserId()) { mSwitchingController.resetCircularListLocked(settings.getMethodMap()); } else { mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( mContext, settings.getMethodMap(), userId); mSwitchingController = new InputMethodSubtypeSwitchingController(mContext, settings.getMethodMap(), userId); } // TODO: Instantiate mHardwareKeyboardShortcutController for each user. if (userId == mHardwareKeyboardShortcutController.getUserId()) { Loading Loading @@ -5320,8 +5319,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (userId == mSwitchingController.getUserId()) { mSwitchingController.resetCircularListLocked(settings.getMethodMap()); } else { mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( mContext, settings.getMethodMap(), mCurrentUserId); mSwitchingController = new InputMethodSubtypeSwitchingController(mContext, settings.getMethodMap(), mCurrentUserId); } // TODO: Instantiate mHardwareKeyboardShortcutController for each user. if (userId == mHardwareKeyboardShortcutController.getUserId()) { Loading
services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java +83 −96 Original line number Diff line number Diff line Loading @@ -48,15 +48,20 @@ final class InputMethodSubtypeSwitchingController { private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID; public static class ImeSubtypeListItem implements Comparable<ImeSubtypeListItem> { @NonNull public final CharSequence mImeName; @Nullable public final CharSequence mSubtypeName; @NonNull public final InputMethodInfo mImi; public final int mSubtypeId; public final boolean mIsSystemLocale; public final boolean mIsSystemLanguage; ImeSubtypeListItem(CharSequence imeName, CharSequence subtypeName, InputMethodInfo imi, int subtypeId, String subtypeLocale, String systemLocale) { ImeSubtypeListItem(@NonNull CharSequence imeName, @Nullable CharSequence subtypeName, @NonNull InputMethodInfo imi, int subtypeId, @Nullable String subtypeLocale, @NonNull String systemLocale) { mImeName = imeName; mSubtypeName = subtypeName; mImi = imi; Loading @@ -69,7 +74,6 @@ final class InputMethodSubtypeSwitchingController { if (mIsSystemLocale) { mIsSystemLanguage = true; } else { // TODO: Use Locale#getLanguage or Locale#toLanguageTag final String systemLanguage = LocaleUtils.getLanguageFromLocaleString( systemLocale); final String subtypeLanguage = LocaleUtils.getLanguageFromLocaleString( Loading Loading @@ -101,8 +105,9 @@ final class InputMethodSubtypeSwitchingController { * <li>{@link #mSubtypeName}</li> * <li>{@link #mImi} with {@link InputMethodInfo#getId()}</li> * </ol> * Note: this class has a natural ordering that is inconsistent with {@link #equals(Object). * This method doesn't compare {@link #mSubtypeId} but {@link #equals(Object)} does. * Note: this class has a natural ordering that is inconsistent with * {@link #equals(Object)}. This method doesn't compare {@link #mSubtypeId} but * {@link #equals(Object)} does. * * @param other the object to be compared. * @return a negative integer, zero, or positive integer as this object is less than, equal Loading Loading @@ -155,6 +160,7 @@ final class InputMethodSubtypeSwitchingController { } } @NonNull static List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList( boolean includeAuxiliarySubtypes, boolean isScreenLocked, boolean forImeMenu, @NonNull Context context, @NonNull InputMethodMap methodMap, Loading Loading @@ -190,7 +196,7 @@ final class InputMethodSubtypeSwitchingController { enabledSubtypeSet.add(String.valueOf(subtype.hashCode())); } final CharSequence imeLabel = imi.loadLabel(userAwareContext.getPackageManager()); if (enabledSubtypeSet.size() > 0) { if (!enabledSubtypeSet.isEmpty()) { final int subtypeCount = imi.getSubtypeCount(); if (DEBUG) { Slog.v(TAG, "Add subtypes: " + subtypeCount + ", " + imi.getId()); Loading Loading @@ -223,14 +229,18 @@ final class InputMethodSubtypeSwitchingController { return imList; } private static int calculateSubtypeId(InputMethodInfo imi, InputMethodSubtype subtype) { private static int calculateSubtypeId(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { return subtype != null ? SubtypeUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode()) : NOT_A_SUBTYPE_ID; } private static class StaticRotationList { @NonNull private final List<ImeSubtypeListItem> mImeSubtypeList; StaticRotationList(final List<ImeSubtypeListItem> imeSubtypeList) { StaticRotationList(@NonNull List<ImeSubtypeListItem> imeSubtypeList) { mImeSubtypeList = imeSubtypeList; } Loading @@ -242,24 +252,22 @@ final class InputMethodSubtypeSwitchingController { * does not have a subtype. * @return The index in the given list. -1 if not found. */ private int getIndex(InputMethodInfo imi, InputMethodSubtype subtype) { private int getIndex(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { final int currentSubtypeId = calculateSubtypeId(imi, subtype); final int numSubtypes = mImeSubtypeList.size(); for (int i = 0; i < numSubtypes; ++i) { final ImeSubtypeListItem isli = mImeSubtypeList.get(i); final ImeSubtypeListItem item = mImeSubtypeList.get(i); // Skip until the current IME/subtype is found. if (imi.equals(isli.mImi) && isli.mSubtypeId == currentSubtypeId) { if (imi.equals(item.mImi) && item.mSubtypeId == currentSubtypeId) { return i; } } return -1; } @Nullable public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { if (imi == null) { return null; } @NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { if (mImeSubtypeList.size() <= 1) { return null; } Loading @@ -282,22 +290,24 @@ final class InputMethodSubtypeSwitchingController { return null; } protected void dump(final Printer pw, final String prefix) { protected void dump(@NonNull Printer pw, @NonNull String prefix) { final int numSubtypes = mImeSubtypeList.size(); for (int i = 0; i < numSubtypes; ++i) { final int rank = i; final ImeSubtypeListItem item = mImeSubtypeList.get(i); for (int rank = 0; rank < numSubtypes; ++rank) { final ImeSubtypeListItem item = mImeSubtypeList.get(rank); pw.println(prefix + "rank=" + rank + " item=" + item); } } } private static class DynamicRotationList { private static final String TAG = DynamicRotationList.class.getSimpleName(); @NonNull private final List<ImeSubtypeListItem> mImeSubtypeList; @NonNull private final int[] mUsageHistoryOfSubtypeListItemIndex; private DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) { private DynamicRotationList(@NonNull List<ImeSubtypeListItem> imeSubtypeListItems) { mImeSubtypeList = imeSubtypeListItems; mUsageHistoryOfSubtypeListItemIndex = new int[mImeSubtypeList.size()]; final int numSubtypes = mImeSubtypeList.size(); Loading @@ -314,7 +324,8 @@ final class InputMethodSubtypeSwitchingController { * * @return -1 when the specified item doesn't belong to {@link #mImeSubtypeList} actually. */ private int getUsageRank(final InputMethodInfo imi, InputMethodSubtype subtype) { private int getUsageRank(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { final int currentSubtypeId = calculateSubtypeId(imi, subtype); final int numItems = mUsageHistoryOfSubtypeListItemIndex.length; for (int usageRank = 0; usageRank < numItems; usageRank++) { Loading @@ -330,7 +341,8 @@ final class InputMethodSubtypeSwitchingController { return -1; } public void onUserAction(InputMethodInfo imi, InputMethodSubtype subtype) { public void onUserAction(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { final int currentUsageRank = getUsageRank(imi, subtype); // Do nothing if currentUsageRank == -1 (not found), or currentUsageRank == 0 if (currentUsageRank <= 0) { Loading @@ -342,8 +354,9 @@ final class InputMethodSubtypeSwitchingController { mUsageHistoryOfSubtypeListItemIndex[0] = currentItemIndex; } @Nullable public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { @NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { int currentUsageRank = getUsageRank(imi, subtype); if (currentUsageRank < 0) { if (DEBUG) { Loading @@ -366,7 +379,7 @@ final class InputMethodSubtypeSwitchingController { return null; } protected void dump(final Printer pw, final String prefix) { protected void dump(@NonNull Printer pw, @NonNull String prefix) { for (int rank = 0; rank < mUsageHistoryOfSubtypeListItemIndex.length; ++rank) { final int index = mUsageHistoryOfSubtypeListItemIndex[rank]; final ImeSubtypeListItem item = mImeSubtypeList.get(index); Loading @@ -377,58 +390,52 @@ final class InputMethodSubtypeSwitchingController { @VisibleForTesting public static class ControllerImpl { @NonNull private final DynamicRotationList mSwitchingAwareRotationList; @NonNull private final StaticRotationList mSwitchingUnawareRotationList; public static ControllerImpl createFrom(final ControllerImpl currentInstance, final List<ImeSubtypeListItem> sortedEnabledItems) { DynamicRotationList switchingAwareRotationList = null; { final List<ImeSubtypeListItem> switchingAwareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, @NonNull public static ControllerImpl createFrom(@Nullable ControllerImpl currentInstance, @NonNull List<ImeSubtypeListItem> sortedEnabledItems) { final var switchingAwareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, true /* supportsSwitchingToNextInputMethod */); if (currentInstance != null && currentInstance.mSwitchingAwareRotationList != null && Objects.equals( final var switchingUnawareImeSubtypes = filterImeSubtypeList(sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */); final DynamicRotationList switchingAwareRotationList; if (currentInstance != null && Objects.equals( currentInstance.mSwitchingAwareRotationList.mImeSubtypeList, switchingAwareImeSubtypes)) { // Can reuse the current instance. switchingAwareRotationList = currentInstance.mSwitchingAwareRotationList; } if (switchingAwareRotationList == null) { } else { switchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes); } } StaticRotationList switchingUnawareRotationList = null; { final List<ImeSubtypeListItem> switchingUnawareImeSubtypes = filterImeSubtypeList( sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */); if (currentInstance != null && currentInstance.mSwitchingUnawareRotationList != null && Objects.equals( final StaticRotationList switchingUnawareRotationList; if (currentInstance != null && Objects.equals( currentInstance.mSwitchingUnawareRotationList.mImeSubtypeList, switchingUnawareImeSubtypes)) { // Can reuse the current instance. switchingUnawareRotationList = currentInstance.mSwitchingUnawareRotationList; } if (switchingUnawareRotationList == null) { switchingUnawareRotationList = new StaticRotationList(switchingUnawareImeSubtypes); } } else { switchingUnawareRotationList = new StaticRotationList(switchingUnawareImeSubtypes); } return new ControllerImpl(switchingAwareRotationList, switchingUnawareRotationList); } private ControllerImpl(final DynamicRotationList switchingAwareRotationList, final StaticRotationList switchingUnawareRotationList) { private ControllerImpl(@NonNull DynamicRotationList switchingAwareRotationList, @NonNull StaticRotationList switchingUnawareRotationList) { mSwitchingAwareRotationList = switchingAwareRotationList; mSwitchingUnawareRotationList = switchingUnawareRotationList; } public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { @Nullable public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, @Nullable InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { if (imi == null) { return null; } Loading @@ -441,18 +448,17 @@ final class InputMethodSubtypeSwitchingController { } } public void onUserActionLocked(InputMethodInfo imi, InputMethodSubtype subtype) { if (imi == null) { return; } public void onUserActionLocked(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { if (imi.supportsSwitchingToNextInputMethod()) { mSwitchingAwareRotationList.onUserAction(imi, subtype); } } @NonNull private static List<ImeSubtypeListItem> filterImeSubtypeList( final List<ImeSubtypeListItem> items, final boolean supportsSwitchingToNextInputMethod) { @NonNull List<ImeSubtypeListItem> items, boolean supportsSwitchingToNextInputMethod) { final ArrayList<ImeSubtypeListItem> result = new ArrayList<>(); final int numItems = items.size(); for (int i = 0; i < numItems; i++) { Loading @@ -473,12 +479,14 @@ final class InputMethodSubtypeSwitchingController { } } @NonNull private final Context mContext; @UserIdInt private final int mUserId; @NonNull private ControllerImpl mController; private InputMethodSubtypeSwitchingController(@NonNull Context context, InputMethodSubtypeSwitchingController(@NonNull Context context, @NonNull InputMethodMap methodMap, @UserIdInt int userId) { mContext = context; mUserId = userId; Loading @@ -488,26 +496,14 @@ final class InputMethodSubtypeSwitchingController { false /* forImeMenu */, context, methodMap, userId)); } @NonNull public static InputMethodSubtypeSwitchingController createInstanceLocked( @NonNull Context context, @NonNull InputMethodMap methodMap, @UserIdInt int userId) { return new InputMethodSubtypeSwitchingController(context, methodMap, userId); } @AnyThread @UserIdInt int getUserId() { return mUserId; } public void onUserActionLocked(InputMethodInfo imi, InputMethodSubtype subtype) { if (mController == null) { if (DEBUG) { Slog.e(TAG, "mController shouldn't be null."); } return; } public void onUserActionLocked(@NonNull InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { mController.onUserActionLocked(imi, subtype); } Loading @@ -518,22 +514,13 @@ final class InputMethodSubtypeSwitchingController { false /* forImeMenu */, mContext, methodMap, mUserId)); } public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) { if (mController == null) { if (DEBUG) { Slog.e(TAG, "mController shouldn't be null."); } return null; } @Nullable public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, @Nullable InputMethodInfo imi, @Nullable InputMethodSubtype subtype) { return mController.getNextInputMethod(onlyCurrentIme, imi, subtype); } public void dump(@NonNull Printer pw, @NonNull String prefix) { if (mController != null) { mController.dump(pw, prefix); } else { pw.println(prefix + "mController=null"); } } }
services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java +127 −120 File changed.Preview size limit exceeded, changes collapsed. Show changes