summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2017-09-16 11:46:45 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2017-09-16 11:46:45 +0000
commitd2c78d68241513275a14fbb9ea4e2af8d98be645 (patch)
tree93635ed36463cd0ddbc891d6c01bb8fad97bbf1f
parentce31943cefed9ba07c13b6368b8ad8964846ed18 (diff)
parent9f240ad69726d2454fb8f9e34a6133c0d6d20b9f (diff)
Merge "Fix InputMethodPreference.compareTo method"
-rw-r--r--[-rwxr-xr-x]packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java43
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/ComparableUtils.java115
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java150
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java89
4 files changed, 320 insertions, 77 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
index 1bbc878b56c9..5e25f519a130 100755..100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
@@ -34,6 +34,7 @@ import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.Toast;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.InputMethodUtils;
import com.android.settingslib.R;
import com.android.settingslib.RestrictedLockUtils;
@@ -91,20 +92,28 @@ public class InputMethodPreference extends RestrictedSwitchPreference implements
public InputMethodPreference(final Context context, final InputMethodInfo imi,
final boolean isImeEnabler, final boolean isAllowedByOrganization,
final OnSavePreferenceListener onSaveListener) {
+ this(context, imi, imi.loadLabel(context.getPackageManager()), isAllowedByOrganization,
+ onSaveListener);
+ if (!isImeEnabler) {
+ // Remove switch widget.
+ setWidgetLayoutResource(NO_WIDGET);
+ }
+ }
+
+ @VisibleForTesting
+ InputMethodPreference(final Context context, final InputMethodInfo imi,
+ final CharSequence title, final boolean isAllowedByOrganization,
+ final OnSavePreferenceListener onSaveListener) {
super(context);
setPersistent(false);
mImi = imi;
mIsAllowedByOrganization = isAllowedByOrganization;
mOnSaveListener = onSaveListener;
- if (!isImeEnabler) {
- // Remove switch widget.
- setWidgetLayoutResource(NO_WIDGET);
- }
// Disable on/off switch texts.
setSwitchTextOn(EMPTY_TEXT);
setSwitchTextOff(EMPTY_TEXT);
setKey(imi.getId());
- setTitle(imi.loadLabel(context.getPackageManager()));
+ setTitle(title);
final String settingsActivity = imi.getSettingsActivity();
if (TextUtils.isEmpty(settingsActivity)) {
setIntent(null);
@@ -283,18 +292,18 @@ public class InputMethodPreference extends RestrictedSwitchPreference implements
if (this == rhs) {
return 0;
}
- if (mHasPriorityInSorting == rhs.mHasPriorityInSorting) {
- final CharSequence t0 = getTitle();
- final CharSequence t1 = rhs.getTitle();
- if (TextUtils.isEmpty(t0)) {
- return 1;
- }
- if (TextUtils.isEmpty(t1)) {
- return -1;
- }
- return collator.compare(t0.toString(), t1.toString());
+ if (mHasPriorityInSorting != rhs.mHasPriorityInSorting) {
+ // Prefer always checked system IMEs
+ return mHasPriorityInSorting ? -1 : 1;
+ }
+ final CharSequence title = getTitle();
+ final CharSequence rhsTitle = rhs.getTitle();
+ final boolean emptyTitle = TextUtils.isEmpty(title);
+ final boolean rhsEmptyTitle = TextUtils.isEmpty(rhsTitle);
+ if (!emptyTitle && !rhsEmptyTitle) {
+ return collator.compare(title.toString(), rhsTitle.toString());
}
- // Prefer always checked system IMEs
- return mHasPriorityInSorting ? -1 : 1;
+ // For historical reasons, an empty text needs to be put at the first.
+ return (emptyTitle ? -1 : 0) - (rhsEmptyTitle ? -1 : 0);
}
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/ComparableUtils.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/ComparableUtils.java
new file mode 100644
index 000000000000..8ec4ff2aad7e
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/ComparableUtils.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.inputmethod;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.ToIntBiFunction;
+
+/**
+ * Utility class to assert {@link Comparable} objects.
+ */
+final class ComparableUtils {
+
+ private ComparableUtils() {
+ }
+
+ /**
+ * Checks whether specified items have ascending ordering.
+ *
+ * @param items objects to be checked Comparable contracts.
+ * @param compareTo function to compare two objects as {@link Comparable#compareTo(Object)}.
+ * @param name function to extract name of an object.
+ * @param <T> type that implements {@link Comparable}.
+ */
+ static <T> void assertAscendingOrdering(final List<T> items,
+ final ToIntBiFunction<T, T> compareTo, final Function<T, String> name) {
+ for (int i = 1; i < items.size(); i++) {
+ final T x = items.get(i - 1);
+ final T y = items.get(i);
+ assertTrue(name.apply(x) + " is less than " + name.apply(y),
+ compareTo.applyAsInt(x, y) < 0);
+ }
+ }
+
+ /**
+ * Checks whether specified items have the same ordering.
+ *
+ * @param items objects to be checked equality.
+ * @param compareTo function to compare two objects as {@link Comparable#compareTo(Object)}.
+ * @param name function to extract name of an object.
+ * @param <T> type that implements {@link Comparable}.
+ */
+ static <T> void assertSameOrdering(final Collection<T> items,
+ final ToIntBiFunction<T, T> compareTo, final Function<T, String> name) {
+ for (final T x : items) {
+ for (final T y : items) {
+ assertTrue(name.apply(x) + " is equal to " + name.apply(y),
+ compareTo.applyAsInt(x, y) == 0);
+ }
+ }
+ }
+
+ /**
+ * Checks whether a {@link Comparable} type complies with Comparable contracts.
+ * <ul>
+ * <li>Ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.</li>
+ * <li>Ensure that the relation is transitive:
+ * (x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.</li>
+ * <li>Ensure that x.compareTo(y)==0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)),
+ * for all z.</li>
+ * </ul>
+ *
+ * @param items objects to be checked Comparable contracts.
+ * @param compareTo function to compare two objects as {@link Comparable#compareTo(Object)}.
+ * @param name function to extract name of an object.
+ * @param <T> type that implements {@link Comparable}.
+ */
+ static <T> void assertComparableContracts(final Collection<T> items,
+ final ToIntBiFunction<T, T> compareTo, final Function<T, String> name) {
+ for (final T x : items) {
+ final String nameX = name.apply(x);
+ assertTrue("Reflective: " + nameX + " is equal to itself",
+ compareTo.applyAsInt(x, x) == 0);
+ for (final T y : items) {
+ final String nameY = name.apply(y);
+ assertEquals("Asymmetric: " + nameX + " and " + nameY,
+ Integer.signum(compareTo.applyAsInt(x, y)),
+ -Integer.signum(compareTo.applyAsInt(y, x)));
+ for (final T z : items) {
+ final String nameZ = name.apply(z);
+ if (compareTo.applyAsInt(x, y) > 0 && compareTo.applyAsInt(y, z) > 0) {
+ assertTrue("Transitive: " + nameX + " is greater than " + nameY
+ + " and " + nameY + " is greater than " + nameZ
+ + " then " + nameX + " is greater than " + nameZ,
+ compareTo.applyAsInt(x, z) > 0);
+ }
+ if (compareTo.applyAsInt(x, y) == 0) {
+ assertEquals("Transitive: " + nameX + " and " + nameY + " is same "
+ + " then both return the same result for " + nameZ,
+ Integer.signum(compareTo.applyAsInt(x, z)),
+ Integer.signum(compareTo.applyAsInt(y, z)));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
new file mode 100644
index 000000000000..ab2b97f7b548
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.inputmethod;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.text.Collator;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class InputMethodPreferenceTest {
+
+ private static final Collator COLLATOR = Collator.getInstance(Locale.US);
+
+ @Test
+ public void testComparableOrdering() throws Exception {
+ final List<InputMethodPreference> itemsInAscendingOrder = Arrays.asList(
+ createPreference("", true, "no_title-system"),
+ createPreference("E", true, "E-system"),
+ createPreference("Z", true, "Z-system"),
+ createPreference("", false, "no_title-non_system"),
+ createPreference("E", false, "E-non_system"),
+ createPreference("Z", false, "Z-non_system")
+ );
+ ComparableUtils.assertAscendingOrdering(
+ itemsInAscendingOrder,
+ (x, y) -> x.compareTo(y, COLLATOR),
+ x -> x.getInputMethodInfo().getServiceName());
+ }
+
+ @Test
+ public void testComparableEquality() {
+ final List<InputMethodPreference> itemsInSameOrder1 = Arrays.asList(
+ createPreference("", true, "no_title-system-1"),
+ createPreference("", true, "no_title-system-2")
+ );
+ ComparableUtils.assertSameOrdering(
+ itemsInSameOrder1,
+ (x, y) -> x.compareTo(y, COLLATOR),
+ x -> x.getInputMethodInfo().getServiceName());
+
+ final List<InputMethodPreference> itemsInSameOrder2 = Arrays.asList(
+ createPreference("A", false, "A-non_system-1"),
+ createPreference("A", false, "A-non_system-2")
+ );
+ ComparableUtils.assertSameOrdering(
+ itemsInSameOrder2,
+ (x, y) -> x.compareTo(y, COLLATOR),
+ x -> x.getInputMethodInfo().getServiceName());
+ }
+
+ @Test
+ public void testComparableContracts() {
+ final List<InputMethodPreference> items = Arrays.asList(
+ // itemsInAscendingOrder.
+ createPreference("", true, "no_title-system"),
+ createPreference("E", true, "E-system"),
+ createPreference("Z", true, "Z-system"),
+ createPreference("", false, "no_title-non_system"),
+ createPreference("E", false, "E-non_system"),
+ createPreference("Z", false, "Z-non_system"),
+ // itemsInSameOrder1.
+ createPreference("", true, "no_title-system-1"),
+ createPreference("", true, "no_title-system-2"),
+ // itemsInSameOrder2.
+ createPreference("A", false, "A-non_system-1"),
+ createPreference("A", false, "A-non_system-2")
+ );
+
+ ComparableUtils.assertComparableContracts(
+ items,
+ (x, y) -> x.compareTo(y, COLLATOR),
+ x -> x.getInputMethodInfo().getServiceName());
+ }
+
+ private static InputMethodPreference createPreference(
+ final CharSequence title,
+ final boolean systemIme,
+ final String name) {
+ return new InputMethodPreference(
+ InstrumentationRegistry.getTargetContext(),
+ createInputMethodInfo(systemIme, name),
+ title,
+ true /* isAllowedByOrganization */,
+ p -> {} /* onSavePreferenceListener */);
+ }
+
+ private static InputMethodInfo createInputMethodInfo(
+ final boolean systemIme, final String name) {
+ final Context targetContext = InstrumentationRegistry.getTargetContext();
+ final Locale systemLocale = targetContext
+ .getResources()
+ .getConfiguration()
+ .getLocales()
+ .get(0);
+ final InputMethodSubtype systemLocaleSubtype =
+ new InputMethodSubtype.InputMethodSubtypeBuilder()
+ .setIsAsciiCapable(true)
+ .setSubtypeLocale(systemLocale.getLanguage())
+ .build();
+
+ final ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.serviceInfo = new ServiceInfo();
+ resolveInfo.serviceInfo.packageName = "com.android.ime";
+ resolveInfo.serviceInfo.name = name;
+ resolveInfo.serviceInfo.applicationInfo = new ApplicationInfo();
+ resolveInfo.serviceInfo.applicationInfo.enabled = true;
+ if (systemIme) {
+ resolveInfo.serviceInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ } else {
+ resolveInfo.serviceInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
+ }
+ return new InputMethodInfo(
+ resolveInfo,
+ false /* isAuxIme */,
+ "SettingsActivity",
+ Collections.singletonList(systemLocaleSubtype),
+ 0 /* isDefaultResId */,
+ true /* forceDefault */);
+ }
+}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java
index 8af027c024d0..131d74274a88 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java
@@ -1,7 +1,20 @@
-package com.android.settingslib.inputmethod;
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
+package com.android.settingslib.inputmethod;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
@@ -16,8 +29,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -39,7 +50,7 @@ public class InputMethodSubtypePreferenceTest {
createPreference("E", "ja", Locale.US),
createPreference("Z", "ja", Locale.US)
);
- private static final List<InputMethodSubtypePreference> SAME_ITEMS = Arrays.asList(
+ private static final List<InputMethodSubtypePreference> SAME_ORDER_ITEMS = Arrays.asList(
// Subtypes that has different language than the system's.
createPreference("A", "ja_JP", Locale.US),
createPreference("A", "hi_IN", Locale.US),
@@ -50,27 +61,25 @@ public class InputMethodSubtypePreferenceTest {
@Test
public void testComparableOrdering() throws Exception {
- onAllAdjacentItems(ITEMS_IN_ASCENDING,
- (x, y) -> assertTrue(
- x.getKey() + " is less than " + y.getKey(),
- x.compareTo(y, COLLATOR) < 0)
- );
+ ComparableUtils.assertAscendingOrdering(
+ ITEMS_IN_ASCENDING,
+ (x, y) -> x.compareTo(y, COLLATOR),
+ InputMethodSubtypePreference::getKey);
}
@Test
public void testComparableEquality() {
- onAllAdjacentItems(SAME_ITEMS,
- (x, y) -> assertTrue(
- x.getKey() + " is equal to " + y.getKey(),
- x.compareTo(y, COLLATOR) == 0)
- );
+ ComparableUtils.assertSameOrdering(
+ SAME_ORDER_ITEMS,
+ (x, y) -> x.compareTo(y, COLLATOR),
+ InputMethodSubtypePreference::getKey);
}
@Test
public void testComparableContracts() {
final Collection<InputMethodSubtypePreference> items = new ArrayList<>();
items.addAll(ITEMS_IN_ASCENDING);
- items.addAll(SAME_ITEMS);
+ items.addAll(SAME_ORDER_ITEMS);
items.add(createPreference("", "", Locale.US));
items.add(createPreference("A", "en", Locale.US));
items.add(createPreference("A", "en_US", Locale.US));
@@ -78,7 +87,7 @@ public class InputMethodSubtypePreferenceTest {
items.add(createPreference("E", "en", Locale.US));
items.add(createPreference("Z", "en_US", Locale.US));
- assertComparableContracts(
+ ComparableUtils.assertComparableContracts(
items,
(x, y) -> x.compareTo(y, COLLATOR),
InputMethodSubtypePreference::getKey);
@@ -88,52 +97,12 @@ public class InputMethodSubtypePreferenceTest {
final String subtypeName,
final String subtypeLocaleString,
final Locale systemLocale) {
+ final String key = subtypeName + "-" + subtypeLocaleString + "-" + systemLocale;
return new InputMethodSubtypePreference(
InstrumentationRegistry.getTargetContext(),
- subtypeName + "-" + subtypeLocaleString + "-" + systemLocale,
+ key,
subtypeName,
subtypeLocaleString,
systemLocale);
}
-
- private static <T> void onAllAdjacentItems(final List<T> items, final BiConsumer<T, T> check) {
- for (int i = 0; i < items.size() - 1; i++) {
- check.accept(items.get(i), items.get(i + 1));
- }
- }
-
- @FunctionalInterface
- interface CompareTo<T> {
- int apply(T t, T u);
- }
-
- private static <T> void assertComparableContracts(final Collection<T> items,
- final CompareTo<T> compareTo, final Function<T, String> name) {
- for (final T x : items) {
- final String nameX = name.apply(x);
- assertTrue("Reflective: " + nameX + " is equal to itself",
- compareTo.apply(x, x) == 0);
- for (final T y : items) {
- final String nameY = name.apply(y);
- assertEquals("Asymmetric: " + nameX + " and " + nameY,
- Integer.signum(compareTo.apply(x, y)),
- -Integer.signum(compareTo.apply(y, x)));
- for (final T z : items) {
- final String nameZ = name.apply(z);
- if (compareTo.apply(x, y) > 0 && compareTo.apply(y, z) > 0) {
- assertTrue("Transitive: " + nameX + " is greater than " + nameY
- + " and " + nameY + " is greater than " + nameZ
- + " then " + nameX + " is greater than " + nameZ,
- compareTo.apply(x, z) > 0);
- }
- if (compareTo.apply(x, y) == 0) {
- assertEquals("Transitive: " + nameX + " and " + nameY + " is same "
- + " then both return the same result for " + nameZ,
- Integer.signum(compareTo.apply(x, z)),
- Integer.signum(compareTo.apply(y, z)));
- }
- }
- }
- }
- }
}