diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java index a94b1612e8a3d..dfc06968c42d6 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java +++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java @@ -42,8 +42,9 @@ import java.util.TreeMap; /** * InputMethodSubtypeSwitchingController controls the switching behavior of the subtypes. *

- * This class is designed to be used from and only from {@link InputMethodManagerService} by using - * {@link InputMethodManagerService#mMethodMap} as a global lock. + * This class is designed to be used from and only from + * {@link com.android.server.InputMethodManagerService} by using + * {@link com.android.server.InputMethodManagerService#mMethodMap} as a global lock. *

*/ public class InputMethodSubtypeSwitchingController { @@ -106,21 +107,39 @@ public class InputMethodSubtypeSwitchingController { return c1.toString().compareTo(c2.toString()); } + /** + * Compares this object with the specified object for order. The fields of this class will + * be compared in the following order. + *
    + *
  1. {@link #mImeName}
  2. + *
  3. {@link #mIsSystemLocale}
  4. + *
  5. {@link #mIsSystemLanguage}
  6. + *
  7. {@link #mSubtypeName}
  8. + *
+ * 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 + * to, or greater than the specified other object. + */ @Override public int compareTo(ImeSubtypeListItem other) { int result = compareNullableCharSequences(mImeName, other.mImeName); if (result != 0) { return result; } - result = compareNullableCharSequences(mSubtypeName, other.mSubtypeName); - if (result != 0) { - return result; - } + // Subtype that has the same locale of the system's has higher priority. result = (mIsSystemLocale ? -1 : 0) - (other.mIsSystemLocale ? -1 : 0); if (result != 0) { return result; } - return (mIsSystemLanguage ? -1 : 0) - (other.mIsSystemLanguage ? -1 : 0); + // Subtype that has the same language of the system's has higher priority. + result = (mIsSystemLanguage ? -1 : 0) - (other.mIsSystemLanguage ? -1 : 0); + if (result != 0) { + return result; + } + return compareNullableCharSequences(mSubtypeName, other.mSubtypeName); } @Override @@ -141,13 +160,7 @@ public class InputMethodSubtypeSwitchingController { } if (o instanceof ImeSubtypeListItem) { final ImeSubtypeListItem that = (ImeSubtypeListItem)o; - if (!Objects.equals(this.mImi, that.mImi)) { - return false; - } - if (this.mSubtypeId != that.mSubtypeId) { - return false; - } - return true; + return Objects.equals(this.mImi, that.mImi) && this.mSubtypeId == that.mSubtypeId; } return false; } diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java index dc7541709dac1..686f75b6710bf 100644 --- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java +++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java @@ -364,39 +364,62 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe public void testImeSubtypeListComparator() throws Exception { { final List items = Arrays.asList( - createDummyItem("X", "A", "en_US", 0, "en_US"), - createDummyItem("X", "A", "en", 1, "en_US"), - createDummyItem("X", "A", "ja", 2, "en_US"), + // Subtypes of IME "X". + // Subtypes that has the same locale of the system's. + createDummyItem("X", "E", "en_US", 0, "en_US"), createDummyItem("X", "Z", "en_US", 3, "en_US"), - createDummyItem("X", "Z", "en", 4, "en_US"), - createDummyItem("X", "Z", "ja", 5, "en_US"), createDummyItem("X", "", "en_US", 6, "en_US"), + // Subtypes that has the same language of the system's. + createDummyItem("X", "E", "en", 1, "en_US"), + createDummyItem("X", "Z", "en", 4, "en_US"), createDummyItem("X", "", "en", 7, "en_US"), + // Subtypes that has different language than the system's. + createDummyItem("X", "A", "hi_IN", 27, "en_US"), + createDummyItem("X", "E", "ja", 2, "en_US"), + createDummyItem("X", "Z", "ja", 5, "en_US"), createDummyItem("X", "", "ja", 8, "en_US"), - createDummyItem("Y", "A", "en_US", 9, "en_US"), - createDummyItem("Y", "A", "en", 10, "en_US"), - createDummyItem("Y", "A", "ja", 11, "en_US"), + + // Subtypes of IME "Y". + // Subtypes that has the same locale of the system's. + createDummyItem("Y", "E", "en_US", 9, "en_US"), createDummyItem("Y", "Z", "en_US", 12, "en_US"), - createDummyItem("Y", "Z", "en", 13, "en_US"), - createDummyItem("Y", "Z", "ja", 14, "en_US"), createDummyItem("Y", "", "en_US", 15, "en_US"), + // Subtypes that has the same language of the system's. + createDummyItem("Y", "E", "en", 10, "en_US"), + createDummyItem("Y", "Z", "en", 13, "en_US"), createDummyItem("Y", "", "en", 16, "en_US"), + // Subtypes that has different language than the system's. + createDummyItem("Y", "A", "hi_IN", 28, "en_US"), + createDummyItem("Y", "E", "ja", 11, "en_US"), + createDummyItem("Y", "Z", "ja", 14, "en_US"), createDummyItem("Y", "", "ja", 17, "en_US"), - createDummyItem("", "A", "en_US", 18, "en_US"), - createDummyItem("", "A", "en", 19, "en_US"), - createDummyItem("", "A", "ja", 20, "en_US"), + + // Subtypes of IME "". + // Subtypes that has the same locale of the system's. + createDummyItem("", "E", "en_US", 18, "en_US"), createDummyItem("", "Z", "en_US", 21, "en_US"), - createDummyItem("", "Z", "en", 22, "en_US"), - createDummyItem("", "Z", "ja", 23, "en_US"), createDummyItem("", "", "en_US", 24, "en_US"), + // Subtypes that has the same language of the system's. + createDummyItem("", "E", "en", 19, "en_US"), + createDummyItem("", "Z", "en", 22, "en_US"), createDummyItem("", "", "en", 25, "en_US"), + // Subtypes that has different language than the system's. + createDummyItem("", "A", "hi_IN", 29, "en_US"), + createDummyItem("", "E", "ja", 20, "en_US"), + createDummyItem("", "Z", "ja", 23, "en_US"), createDummyItem("", "", "ja", 26, "en_US")); + // Ensure {@link java.lang.Comparable#compareTo} contracts are satisfied. for (int i = 0; i < items.size(); ++i) { - assertEquals(0, items.get(i).compareTo(items.get(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); + // Ensures (x.compareTo(y) > 0 && y.compareTo(z) > 0) implies x.compareTo(z) > 0. for (int j = i + 1; j < items.size(); ++j) { - assertTrue(items.get(i).compareTo(items.get(j)) < 0); - assertTrue(items.get(j).compareTo(items.get(i)) > 0); + final ImeSubtypeListItem item2 = items.get(j); + // Ensures sgn(x.compareTo(y)) == -sgn(y.compareTo(x)). + assertTrue(item1 + " is less than " + item2, item1.compareTo(item2) < 0); + assertTrue(item2 + " is greater than " + item1, item2.compareTo(item1) > 0); } } } @@ -404,11 +427,14 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe { // Following two items have the same priority. final ImeSubtypeListItem nonSystemLocale1 = - createDummyItem("X", "A", "ja_JP", 0, "en_us"); + createDummyItem("X", "A", "ja_JP", 0, "en_US"); final ImeSubtypeListItem nonSystemLocale2 = - createDummyItem("X", "A", "hi_IN", 1, "en_us"); - assertEquals(0, nonSystemLocale1.compareTo(nonSystemLocale2)); - assertEquals(0, nonSystemLocale2.compareTo(nonSystemLocale1)); + createDummyItem("X", "A", "hi_IN", 1, "en_US"); + assertTrue(nonSystemLocale1.compareTo(nonSystemLocale2) == 0); + assertTrue(nonSystemLocale2.compareTo(nonSystemLocale1) == 0); + // But those aren't equal to each other. + assertFalse(nonSystemLocale1.equals(nonSystemLocale2)); + assertFalse(nonSystemLocale2.equals(nonSystemLocale1)); } } }