Cleanup IME subtype switching controller and tests

This adds annotations for the nullability of parameters, values and
return values of methods in the IME subtype switching controller, as
well as simplifying the existing logic with an equivalent one.
Additionally fixes the testImeSubtypeListItem to check the
isSystemLanguage of all items, as well as add the missing item_en_uk.
Lastly, replaces the non-inclusive language from the test class.

Test: atest InputMethodSubtypeSwitchingControllerTest
Bug: 347693610
Change-Id: I6292fd34f016d7a1635994a364d91eb071c5d5b5
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3f296ca..39262c5 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1300,9 +1300,8 @@
 
             final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
 
-            mSwitchingController =
-                    InputMethodSubtypeSwitchingController.createInstanceLocked(context,
-                            settings.getMethodMap(), settings.getUserId());
+            mSwitchingController = new InputMethodSubtypeSwitchingController(context,
+                    settings.getMethodMap(), settings.getUserId());
             mHardwareKeyboardShortcutController =
                     new HardwareKeyboardShortcutController(settings.getMethodMap(),
                             settings.getUserId());
@@ -3049,8 +3048,8 @@
         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()) {
@@ -5320,8 +5319,8 @@
         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()) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
index 770e3b2..bf9621f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -48,15 +48,20 @@
     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;
@@ -69,7 +74,6 @@
                 if (mIsSystemLocale) {
                     mIsSystemLanguage = true;
                 } else {
-                    // TODO: Use Locale#getLanguage or Locale#toLanguageTag
                     final String systemLanguage = LocaleUtils.getLanguageFromLocaleString(
                             systemLocale);
                     final String subtypeLanguage = LocaleUtils.getLanguageFromLocaleString(
@@ -101,8 +105,9 @@
          *   <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
@@ -155,6 +160,7 @@
         }
     }
 
+    @NonNull
     static List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList(
             boolean includeAuxiliarySubtypes, boolean isScreenLocked, boolean forImeMenu,
             @NonNull Context context, @NonNull InputMethodMap methodMap,
@@ -190,7 +196,7 @@
                 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());
@@ -223,14 +229,18 @@
         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;
         }
 
@@ -242,24 +252,22 @@
          *                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;
             }
@@ -282,22 +290,24 @@
             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();
@@ -314,7 +324,8 @@
          *
          * @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++) {
@@ -330,7 +341,8 @@
             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) {
@@ -342,8 +354,9 @@
             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) {
@@ -366,7 +379,7 @@
             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);
@@ -377,58 +390,52 @@
 
     @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,
-                                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);
-                }
+        @NonNull
+        public static ControllerImpl createFrom(@Nullable ControllerImpl currentInstance,
+                @NonNull List<ImeSubtypeListItem> sortedEnabledItems) {
+            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,
+                    switchingAwareImeSubtypes)) {
+                // Can reuse the current instance.
+                switchingAwareRotationList = currentInstance.mSwitchingAwareRotationList;
+            } else {
+                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);
-                }
+            final StaticRotationList switchingUnawareRotationList;
+            if (currentInstance != null && Objects.equals(
+                    currentInstance.mSwitchingUnawareRotationList.mImeSubtypeList,
+                    switchingUnawareImeSubtypes)) {
+                // Can reuse the current instance.
+                switchingUnawareRotationList = currentInstance.mSwitchingUnawareRotationList;
+            } 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;
             }
@@ -441,18 +448,17 @@
             }
         }
 
-        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++) {
@@ -473,12 +479,14 @@
         }
     }
 
+    @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;
@@ -488,26 +496,14 @@
                         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);
     }
 
@@ -518,22 +514,13 @@
                         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");
-        }
+        mController.dump(pw, prefix);
     }
 }
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
index fbe384a..02b7291 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 
 import android.content.ComponentName;
@@ -28,6 +29,9 @@
 import android.view.inputmethod.InputMethodSubtype;
 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ControllerImpl;
 import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
 
@@ -38,50 +42,51 @@
 import java.util.List;
 
 public final class InputMethodSubtypeSwitchingControllerTest {
-    private static final String DUMMY_PACKAGE_NAME = "dummy package name";
-    private static final String DUMMY_IME_LABEL = "dummy ime label";
-    private static final String DUMMY_SETTING_ACTIVITY_NAME = "";
-    private static final boolean DUMMY_IS_AUX_IME = false;
-    private static final boolean DUMMY_FORCE_DEFAULT = false;
-    private static final boolean DUMMY_IS_VR_IME = false;
-    private static final int DUMMY_IS_DEFAULT_RES_ID = 0;
+    private static final String TEST_PACKAGE_NAME = "test package name";
+    private static final String TEST_IME_LABEL = "test ime label";
+    private static final String TEST_SETTING_ACTIVITY_NAME = "";
+    private static final boolean TEST_IS_AUX_IME = false;
+    private static final boolean TEST_FORCE_DEFAULT = false;
+    private static final boolean TEST_IS_VR_IME = false;
+    private static final int TEST_IS_DEFAULT_RES_ID = 0;
     private static final String SYSTEM_LOCALE = "en_US";
     private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
 
-    private static InputMethodSubtype createDummySubtype(final String locale) {
-        final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder();
-        return builder.setSubtypeNameResId(0)
+    @NonNull
+    private static InputMethodSubtype createTestSubtype(@NonNull String locale) {
+        return new InputMethodSubtypeBuilder()
+                .setSubtypeNameResId(0)
                 .setSubtypeIconResId(0)
                 .setSubtypeLocale(locale)
                 .setIsAsciiCapable(true)
                 .build();
     }
 
-    private static void addDummyImeSubtypeListItems(List<ImeSubtypeListItem> items,
-            String imeName, String imeLabel, List<String> subtypeLocales,
-            boolean supportsSwitchingToNextInputMethod) {
+    private static void addTestImeSubtypeListItems(@NonNull List<ImeSubtypeListItem> items,
+            @NonNull String imeName, @NonNull String imeLabel,
+            @Nullable List<String> subtypeLocales, boolean supportsSwitchingToNextInputMethod) {
         final ResolveInfo ri = new ResolveInfo();
         final ServiceInfo si = new ServiceInfo();
         final ApplicationInfo ai = new ApplicationInfo();
-        ai.packageName = DUMMY_PACKAGE_NAME;
+        ai.packageName = TEST_PACKAGE_NAME;
         ai.enabled = true;
         si.applicationInfo = ai;
         si.enabled = true;
-        si.packageName = DUMMY_PACKAGE_NAME;
+        si.packageName = TEST_PACKAGE_NAME;
         si.name = imeName;
         si.exported = true;
         si.nonLocalizedLabel = imeLabel;
         ri.serviceInfo = si;
         List<InputMethodSubtype> subtypes = null;
         if (subtypeLocales != null) {
-            subtypes = new ArrayList<InputMethodSubtype>();
+            subtypes = new ArrayList<>();
             for (String subtypeLocale : subtypeLocales) {
-                subtypes.add(createDummySubtype(subtypeLocale));
+                subtypes.add(createTestSubtype(subtypeLocale));
             }
         }
-        final InputMethodInfo imi = new InputMethodInfo(ri, DUMMY_IS_AUX_IME,
-                DUMMY_SETTING_ACTIVITY_NAME, subtypes, DUMMY_IS_DEFAULT_RES_ID,
-                DUMMY_FORCE_DEFAULT, supportsSwitchingToNextInputMethod, DUMMY_IS_VR_IME);
+        final InputMethodInfo imi = new InputMethodInfo(ri, TEST_IS_AUX_IME,
+                TEST_SETTING_ACTIVITY_NAME, subtypes, TEST_IS_DEFAULT_RES_ID,
+                TEST_FORCE_DEFAULT, supportsSwitchingToNextInputMethod, TEST_IS_VR_IME);
         if (subtypes == null) {
             items.add(new ImeSubtypeListItem(imeName, null /* variableName */, imi,
                     NOT_A_SUBTYPE_ID, null, SYSTEM_LOCALE));
@@ -94,105 +99,105 @@
         }
     }
 
-    private static ImeSubtypeListItem createDummyItem(ComponentName imeComponentName,
-            String imeName, String subtypeName, String subtypeLocale, int subtypeIndex,
-            String systemLocale) {
-        final ResolveInfo ri = new ResolveInfo();
-        final ServiceInfo si = new ServiceInfo();
-        final ApplicationInfo ai = new ApplicationInfo();
+    @NonNull
+    private static ImeSubtypeListItem createTestItem(@NonNull ComponentName imeComponentName,
+            @NonNull String imeName, @NonNull String subtypeName,
+            @NonNull String subtypeLocale, int subtypeIndex,
+            @NonNull String systemLocale) {
+        final var ai = new ApplicationInfo();
         ai.packageName = imeComponentName.getPackageName();
         ai.enabled = true;
+        final var si = new ServiceInfo();
         si.applicationInfo = ai;
         si.enabled = true;
         si.packageName = imeComponentName.getPackageName();
         si.name = imeComponentName.getClassName();
         si.exported = true;
-        si.nonLocalizedLabel = DUMMY_IME_LABEL;
+        si.nonLocalizedLabel = TEST_IME_LABEL;
+        final var ri = new ResolveInfo();
         ri.serviceInfo = si;
-        ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+        final var subtypes = new ArrayList<InputMethodSubtype>();
         subtypes.add(new InputMethodSubtypeBuilder()
                 .setSubtypeNameResId(0)
                 .setSubtypeIconResId(0)
                 .setSubtypeLocale(subtypeLocale)
                 .setIsAsciiCapable(true)
                 .build());
-        final InputMethodInfo imi = new InputMethodInfo(ri, DUMMY_IS_AUX_IME,
-                DUMMY_SETTING_ACTIVITY_NAME, subtypes, DUMMY_IS_DEFAULT_RES_ID,
-                DUMMY_FORCE_DEFAULT, true /* supportsSwitchingToNextInputMethod */,
-                DUMMY_IS_VR_IME);
+        final InputMethodInfo imi = new InputMethodInfo(ri, TEST_IS_AUX_IME,
+                TEST_SETTING_ACTIVITY_NAME, subtypes, TEST_IS_DEFAULT_RES_ID,
+                TEST_FORCE_DEFAULT, true /* supportsSwitchingToNextInputMethod */,
+                TEST_IS_VR_IME);
         return new ImeSubtypeListItem(imeName, subtypeName, imi, subtypeIndex, subtypeLocale,
                 systemLocale);
     }
 
+    @NonNull
     private static List<ImeSubtypeListItem> createEnabledImeSubtypes() {
-        final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
-        addDummyImeSubtypeListItems(items, "LatinIme", "LatinIme", Arrays.asList("en_US", "fr"),
+        final var items = new ArrayList<ImeSubtypeListItem>();
+        addTestImeSubtypeListItems(items, "LatinIme", "LatinIme", Arrays.asList("en_US", "fr"),
                 true /* supportsSwitchingToNextInputMethod*/);
-        addDummyImeSubtypeListItems(items, "switchUnawareLatinIme", "switchUnawareLatinIme",
+        addTestImeSubtypeListItems(items, "switchUnawareLatinIme", "switchUnawareLatinIme",
                 Arrays.asList("en_UK", "hi"),
                 false /* supportsSwitchingToNextInputMethod*/);
-        addDummyImeSubtypeListItems(items, "subtypeUnawareIme", "subtypeUnawareIme", null,
+        addTestImeSubtypeListItems(items, "subtypeUnawareIme", "subtypeUnawareIme", null,
                 false /* supportsSwitchingToNextInputMethod*/);
-        addDummyImeSubtypeListItems(items, "JapaneseIme", "JapaneseIme", Arrays.asList("ja_JP"),
+        addTestImeSubtypeListItems(items, "JapaneseIme", "JapaneseIme", Arrays.asList("ja_JP"),
                 true /* supportsSwitchingToNextInputMethod*/);
-        addDummyImeSubtypeListItems(items, "switchUnawareJapaneseIme", "switchUnawareJapaneseIme",
+        addTestImeSubtypeListItems(items, "switchUnawareJapaneseIme", "switchUnawareJapaneseIme",
                 Arrays.asList("ja_JP"), false /* supportsSwitchingToNextInputMethod*/);
         return items;
     }
 
+    @NonNull
     private static List<ImeSubtypeListItem> createDisabledImeSubtypes() {
-        final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
-        addDummyImeSubtypeListItems(items,
+        final var items = new ArrayList<ImeSubtypeListItem>();
+        addTestImeSubtypeListItems(items,
                 "UnknownIme", "UnknownIme",
                 Arrays.asList("en_US", "hi"),
                 true /* supportsSwitchingToNextInputMethod*/);
-        addDummyImeSubtypeListItems(items,
+        addTestImeSubtypeListItems(items,
                 "UnknownSwitchingUnawareIme", "UnknownSwitchingUnawareIme",
                 Arrays.asList("en_US"),
                 false /* supportsSwitchingToNextInputMethod*/);
-        addDummyImeSubtypeListItems(items, "UnknownSubtypeUnawareIme",
+        addTestImeSubtypeListItems(items, "UnknownSubtypeUnawareIme",
                 "UnknownSubtypeUnawareIme", null,
                 false /* supportsSwitchingToNextInputMethod*/);
         return items;
     }
 
-    private void assertNextInputMethod(final ControllerImpl controller,
-            final boolean onlyCurrentIme,
-            final ImeSubtypeListItem currentItem, final ImeSubtypeListItem nextItem) {
+    private void assertNextInputMethod(@NonNull ControllerImpl controller, boolean onlyCurrentIme,
+            @NonNull ImeSubtypeListItem currentItem, @Nullable ImeSubtypeListItem nextItem) {
         InputMethodSubtype subtype = null;
         if (currentItem.mSubtypeName != null) {
-            subtype = createDummySubtype(currentItem.mSubtypeName.toString());
+            subtype = createTestSubtype(currentItem.mSubtypeName.toString());
         }
         final ImeSubtypeListItem nextIme = controller.getNextInputMethod(onlyCurrentIme,
                 currentItem.mImi, subtype);
         assertEquals(nextItem, nextIme);
     }
 
-    private void assertRotationOrder(final ControllerImpl controller,
-            final boolean onlyCurrentIme,
-            final ImeSubtypeListItem... expectedRotationOrderOfImeSubtypeList) {
+    private void assertRotationOrder(@NonNull ControllerImpl controller, boolean onlyCurrentIme,
+            ImeSubtypeListItem... expectedRotationOrderOfImeSubtypeList) {
         final int numItems = expectedRotationOrderOfImeSubtypeList.length;
         for (int i = 0; i < numItems; i++) {
-            final int currentIndex = i;
-            final int nextIndex = (currentIndex + 1) % numItems;
-            final ImeSubtypeListItem currentItem =
-                    expectedRotationOrderOfImeSubtypeList[currentIndex];
+            final int nextIndex = (i + 1) % numItems;
+            final ImeSubtypeListItem currentItem = expectedRotationOrderOfImeSubtypeList[i];
             final ImeSubtypeListItem nextItem = expectedRotationOrderOfImeSubtypeList[nextIndex];
             assertNextInputMethod(controller, onlyCurrentIme, currentItem, nextItem);
         }
     }
 
-    private void onUserAction(final ControllerImpl controller,
-            final ImeSubtypeListItem subtypeListItem) {
+    private void onUserAction(@NonNull ControllerImpl controller,
+            @NonNull ImeSubtypeListItem subtypeListItem) {
         InputMethodSubtype subtype = null;
         if (subtypeListItem.mSubtypeName != null) {
-            subtype = createDummySubtype(subtypeListItem.mSubtypeName.toString());
+            subtype = createTestSubtype(subtypeListItem.mSubtypeName.toString());
         }
         controller.onUserActionLocked(subtypeListItem.mImi, subtype);
     }
 
     @Test
-    public void testControllerImpl() throws Exception {
+    public void testControllerImpl() {
         final List<ImeSubtypeListItem> disabledItems = createDisabledImeSubtypes();
         final ImeSubtypeListItem disabledIme_en_us = disabledItems.get(0);
         final ImeSubtypeListItem disabledIme_hi = disabledItems.get(1);
@@ -252,7 +257,7 @@
     }
 
     @Test
-    public void testControllerImplWithUserAction() throws Exception {
+    public void testControllerImplWithUserAction() {
         final List<ImeSubtypeListItem> enabledItems = createEnabledImeSubtypes();
         final ImeSubtypeListItem latinIme_en_us = enabledItems.get(0);
         final ImeSubtypeListItem latinIme_fr = enabledItems.get(1);
@@ -333,22 +338,23 @@
     }
 
     @Test
-    public void testImeSubtypeListItem() throws Exception {
-        final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
-        addDummyImeSubtypeListItems(items, "LatinIme", "LatinIme",
+    public void testImeSubtypeListItem() {
+        final var items = new ArrayList<ImeSubtypeListItem>();
+        addTestImeSubtypeListItems(items, "LatinIme", "LatinIme",
                 Arrays.asList("en_US", "fr", "en", "en_uk", "enn", "e", "EN_US"),
                 true /* supportsSwitchingToNextInputMethod*/);
         final ImeSubtypeListItem item_en_us = items.get(0);
         final ImeSubtypeListItem item_fr = items.get(1);
         final ImeSubtypeListItem item_en = items.get(2);
-        final ImeSubtypeListItem item_enn = items.get(3);
-        final ImeSubtypeListItem item_e = items.get(4);
-        final ImeSubtypeListItem item_en_us_allcaps = items.get(5);
+        final ImeSubtypeListItem item_en_uk = items.get(3);
+        final ImeSubtypeListItem item_enn = items.get(4);
+        final ImeSubtypeListItem item_e = items.get(5);
+        final ImeSubtypeListItem item_en_us_allcaps = items.get(6);
 
         assertTrue(item_en_us.mIsSystemLocale);
         assertFalse(item_fr.mIsSystemLocale);
         assertFalse(item_en.mIsSystemLocale);
-        assertFalse(item_en.mIsSystemLocale);
+        assertFalse(item_en_uk.mIsSystemLocale);
         assertFalse(item_enn.mIsSystemLocale);
         assertFalse(item_e.mIsSystemLocale);
         assertFalse(item_en_us_allcaps.mIsSystemLocale);
@@ -356,14 +362,15 @@
         assertTrue(item_en_us.mIsSystemLanguage);
         assertFalse(item_fr.mIsSystemLanguage);
         assertTrue(item_en.mIsSystemLanguage);
-        assertFalse(item_enn.mIsSystemLocale);
-        assertFalse(item_e.mIsSystemLocale);
-        assertFalse(item_en_us_allcaps.mIsSystemLocale);
+        assertTrue(item_en_uk.mIsSystemLanguage);
+        assertFalse(item_enn.mIsSystemLanguage);
+        assertFalse(item_e.mIsSystemLanguage);
+        assertFalse(item_en_us_allcaps.mIsSystemLanguage);
     }
 
     @SuppressWarnings("SelfComparison")
     @Test
-    public void testImeSubtypeListComparator() throws Exception {
+    public void testImeSubtypeListComparator() {
         final ComponentName imeX1 = new ComponentName("com.example.imeX", "Ime1");
         final ComponentName imeX2 = new ComponentName("com.example.imeX", "Ime2");
         final ComponentName imeY1 = new ComponentName("com.example.imeY", "Ime1");
@@ -372,64 +379,64 @@
             final List<ImeSubtypeListItem> items = Arrays.asList(
                     // Subtypes of two IMEs that have the same display name "X".
                     // Subtypes that has the same locale of the system's.
-                    createDummyItem(imeX1, "X", "E", "en_US", 0, "en_US"),
-                    createDummyItem(imeX2, "X", "E", "en_US", 0, "en_US"),
-                    createDummyItem(imeX1, "X", "Z", "en_US", 3, "en_US"),
-                    createDummyItem(imeX2, "X", "Z", "en_US", 3, "en_US"),
-                    createDummyItem(imeX1, "X", "", "en_US", 6, "en_US"),
-                    createDummyItem(imeX2, "X", "", "en_US", 6, "en_US"),
+                    createTestItem(imeX1, "X", "E", "en_US", 0, "en_US"),
+                    createTestItem(imeX2, "X", "E", "en_US", 0, "en_US"),
+                    createTestItem(imeX1, "X", "Z", "en_US", 3, "en_US"),
+                    createTestItem(imeX2, "X", "Z", "en_US", 3, "en_US"),
+                    createTestItem(imeX1, "X", "", "en_US", 6, "en_US"),
+                    createTestItem(imeX2, "X", "", "en_US", 6, "en_US"),
                     // Subtypes that has the same language of the system's.
-                    createDummyItem(imeX1, "X", "E", "en", 1, "en_US"),
-                    createDummyItem(imeX2, "X", "E", "en", 1, "en_US"),
-                    createDummyItem(imeX1, "X", "Z", "en", 4, "en_US"),
-                    createDummyItem(imeX2, "X", "Z", "en", 4, "en_US"),
-                    createDummyItem(imeX1, "X", "", "en", 7, "en_US"),
-                    createDummyItem(imeX2, "X", "", "en", 7, "en_US"),
+                    createTestItem(imeX1, "X", "E", "en", 1, "en_US"),
+                    createTestItem(imeX2, "X", "E", "en", 1, "en_US"),
+                    createTestItem(imeX1, "X", "Z", "en", 4, "en_US"),
+                    createTestItem(imeX2, "X", "Z", "en", 4, "en_US"),
+                    createTestItem(imeX1, "X", "", "en", 7, "en_US"),
+                    createTestItem(imeX2, "X", "", "en", 7, "en_US"),
                     // Subtypes that has different language than the system's.
-                    createDummyItem(imeX1, "X", "A", "hi_IN", 27, "en_US"),
-                    createDummyItem(imeX2, "X", "A", "hi_IN", 27, "en_US"),
-                    createDummyItem(imeX1, "X", "E", "ja", 2, "en_US"),
-                    createDummyItem(imeX2, "X", "E", "ja", 2, "en_US"),
-                    createDummyItem(imeX1, "X", "Z", "ja", 5, "en_US"),
-                    createDummyItem(imeX2, "X", "Z", "ja", 5, "en_US"),
-                    createDummyItem(imeX1, "X", "", "ja", 8, "en_US"),
-                    createDummyItem(imeX2, "X", "", "ja", 8, "en_US"),
+                    createTestItem(imeX1, "X", "A", "hi_IN", 27, "en_US"),
+                    createTestItem(imeX2, "X", "A", "hi_IN", 27, "en_US"),
+                    createTestItem(imeX1, "X", "E", "ja", 2, "en_US"),
+                    createTestItem(imeX2, "X", "E", "ja", 2, "en_US"),
+                    createTestItem(imeX1, "X", "Z", "ja", 5, "en_US"),
+                    createTestItem(imeX2, "X", "Z", "ja", 5, "en_US"),
+                    createTestItem(imeX1, "X", "", "ja", 8, "en_US"),
+                    createTestItem(imeX2, "X", "", "ja", 8, "en_US"),
 
                     // Subtypes of IME "Y".
                     // Subtypes that has the same locale of the system's.
-                    createDummyItem(imeY1, "Y", "E", "en_US", 9, "en_US"),
-                    createDummyItem(imeY1, "Y", "Z", "en_US", 12, "en_US"),
-                    createDummyItem(imeY1, "Y", "", "en_US", 15, "en_US"),
+                    createTestItem(imeY1, "Y", "E", "en_US", 9, "en_US"),
+                    createTestItem(imeY1, "Y", "Z", "en_US", 12, "en_US"),
+                    createTestItem(imeY1, "Y", "", "en_US", 15, "en_US"),
                     // Subtypes that has the same language of the system's.
-                    createDummyItem(imeY1, "Y", "E", "en", 10, "en_US"),
-                    createDummyItem(imeY1, "Y", "Z", "en", 13, "en_US"),
-                    createDummyItem(imeY1, "Y", "", "en", 16, "en_US"),
+                    createTestItem(imeY1, "Y", "E", "en", 10, "en_US"),
+                    createTestItem(imeY1, "Y", "Z", "en", 13, "en_US"),
+                    createTestItem(imeY1, "Y", "", "en", 16, "en_US"),
                     // Subtypes that has different language than the system's.
-                    createDummyItem(imeY1, "Y", "A", "hi_IN", 28, "en_US"),
-                    createDummyItem(imeY1, "Y", "E", "ja", 11, "en_US"),
-                    createDummyItem(imeY1, "Y", "Z", "ja", 14, "en_US"),
-                    createDummyItem(imeY1, "Y", "", "ja", 17, "en_US"),
+                    createTestItem(imeY1, "Y", "A", "hi_IN", 28, "en_US"),
+                    createTestItem(imeY1, "Y", "E", "ja", 11, "en_US"),
+                    createTestItem(imeY1, "Y", "Z", "ja", 14, "en_US"),
+                    createTestItem(imeY1, "Y", "", "ja", 17, "en_US"),
 
                     // Subtypes of IME Z.
                     // Subtypes that has the same locale of the system's.
-                    createDummyItem(imeZ1, "", "E", "en_US", 18, "en_US"),
-                    createDummyItem(imeZ1, "", "Z", "en_US", 21, "en_US"),
-                    createDummyItem(imeZ1, "", "", "en_US", 24, "en_US"),
+                    createTestItem(imeZ1, "", "E", "en_US", 18, "en_US"),
+                    createTestItem(imeZ1, "", "Z", "en_US", 21, "en_US"),
+                    createTestItem(imeZ1, "", "", "en_US", 24, "en_US"),
                     // Subtypes that has the same language of the system's.
-                    createDummyItem(imeZ1, "", "E", "en", 19, "en_US"),
-                    createDummyItem(imeZ1, "", "Z", "en", 22, "en_US"),
-                    createDummyItem(imeZ1, "", "", "en", 25, "en_US"),
+                    createTestItem(imeZ1, "", "E", "en", 19, "en_US"),
+                    createTestItem(imeZ1, "", "Z", "en", 22, "en_US"),
+                    createTestItem(imeZ1, "", "", "en", 25, "en_US"),
                     // Subtypes that has different language than the system's.
-                    createDummyItem(imeZ1, "", "A", "hi_IN", 29, "en_US"),
-                    createDummyItem(imeZ1, "", "E", "ja", 20, "en_US"),
-                    createDummyItem(imeZ1, "", "Z", "ja", 23, "en_US"),
-                    createDummyItem(imeZ1, "", "", "ja", 26, "en_US"));
+                    createTestItem(imeZ1, "", "A", "hi_IN", 29, "en_US"),
+                    createTestItem(imeZ1, "", "E", "ja", 20, "en_US"),
+                    createTestItem(imeZ1, "", "Z", "ja", 23, "en_US"),
+                    createTestItem(imeZ1, "", "", "ja", 26, "en_US"));
 
             // Ensure {@link java.lang.Comparable#compareTo} contracts are satisfied.
             for (int i = 0; i < items.size(); ++i) {
                 final ImeSubtypeListItem item1 = items.get(i);
                 // Ensures sgn(x.compareTo(y)) == -sgn(y.compareTo(x)).
-                assertTrue(item1 + " has the same order of itself", item1.compareTo(item1) == 0);
+                assertEquals(item1 + " has the same order of itself", 0, item1.compareTo(item1));
                 // Ensures (x.compareTo(y) > 0 && y.compareTo(z) > 0) implies x.compareTo(z) > 0.
                 for (int j = i + 1; j < items.size(); ++j) {
                     final ImeSubtypeListItem item2 = items.get(j);
@@ -443,25 +450,25 @@
         {
             // Following two items have the same priority.
             final ImeSubtypeListItem nonSystemLocale1 =
-                    createDummyItem(imeX1, "X", "A", "ja_JP", 0, "en_US");
+                    createTestItem(imeX1, "X", "A", "ja_JP", 0, "en_US");
             final ImeSubtypeListItem nonSystemLocale2 =
-                    createDummyItem(imeX1, "X", "A", "hi_IN", 1, "en_US");
-            assertTrue(nonSystemLocale1.compareTo(nonSystemLocale2) == 0);
-            assertTrue(nonSystemLocale2.compareTo(nonSystemLocale1) == 0);
+                    createTestItem(imeX1, "X", "A", "hi_IN", 1, "en_US");
+            assertEquals(0, nonSystemLocale1.compareTo(nonSystemLocale2));
+            assertEquals(0, nonSystemLocale2.compareTo(nonSystemLocale1));
             // But those aren't equal to each other.
-            assertFalse(nonSystemLocale1.equals(nonSystemLocale2));
-            assertFalse(nonSystemLocale2.equals(nonSystemLocale1));
+            assertNotEquals(nonSystemLocale1, nonSystemLocale2);
+            assertNotEquals(nonSystemLocale2, nonSystemLocale1);
         }
 
         {
             // Check if ComponentName is also taken into account when comparing two items.
-            final ImeSubtypeListItem ime1 = createDummyItem(imeX1, "X", "A", "ja_JP", 0, "en_US");
-            final ImeSubtypeListItem ime2 = createDummyItem(imeX2, "X", "A", "ja_JP", 0, "en_US");
+            final ImeSubtypeListItem ime1 = createTestItem(imeX1, "X", "A", "ja_JP", 0, "en_US");
+            final ImeSubtypeListItem ime2 = createTestItem(imeX2, "X", "A", "ja_JP", 0, "en_US");
             assertTrue(ime1.compareTo(ime2) < 0);
             assertTrue(ime2.compareTo(ime1) > 0);
             // But those aren't equal to each other.
-            assertFalse(ime1.equals(ime2));
-            assertFalse(ime2.equals(ime1));
+            assertNotEquals(ime1, ime2);
+            assertNotEquals(ime2, ime1);
         }
     }
 }