summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodMenuControllerNew.java25
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodMenuControllerTest.java66
2 files changed, 80 insertions, 11 deletions
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuControllerNew.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuControllerNew.java
index 5e2a6ac31a0a..1d0e3c639c3f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuControllerNew.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuControllerNew.java
@@ -199,8 +199,10 @@ final class InputMethodMenuControllerNew {
* handles adding headers and dividers between groups of items from different input methods
* as follows:
*
+ * <li>If there is only one group, no divider or header will be added.</li>
* <li>A divider is added before each group, except the first one.</li>
- * <li>A header is added before each group (after the divider, if it exists).</li>
+ * <li>A header is added before each group (after the divider, if it exists) if the group has
+ * at least two items, or a single item with a subtype name.</li>
*
* @param items the list of input method and subtype items.
*/
@@ -212,23 +214,32 @@ final class InputMethodMenuControllerNew {
return menuItems;
}
- String prevImeId = null;
- for (int i = 0; i < items.size(); i++) {
- final var item = items.get(i);
+ final var itemsArray = (ArrayList<ImeSubtypeListItem>) items;
+ final int numItems = itemsArray.size();
+ // Initialize to the last IME id to avoid headers if there is only a single IME.
+ String prevImeId = itemsArray.getLast().mImi.getId();
+ boolean firstGroup = true;
+ for (int i = 0; i < numItems; i++) {
+ final var item = itemsArray.get(i);
final var imeId = item.mImi.getId();
final boolean groupChange = !imeId.equals(prevImeId);
if (groupChange) {
- final boolean firstGroup = prevImeId == null;
if (!firstGroup) {
menuItems.add(DividerItem.getInstance());
}
- menuItems.add(new HeaderItem(item.mImeName));
+ // Add a header if we have at least two items, or a single item with a subtype name.
+ final var nextItemId = i + 1 < numItems ? itemsArray.get(i + 1).mImi.getId() : null;
+ final boolean addHeader = item.mSubtypeName != null || imeId.equals(nextItemId);
+ if (addHeader) {
+ menuItems.add(new HeaderItem(item.mImeName));
+ }
+ firstGroup = false;
+ prevImeId = imeId;
}
menuItems.add(new SubtypeItem(item.mImeName, item.mSubtypeName, item.mImi,
item.mSubtypeIndex));
- prevImeId = imeId;
}
return menuItems;
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodMenuControllerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodMenuControllerTest.java
index 02071695505c..02dc86bffe2d 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodMenuControllerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodMenuControllerTest.java
@@ -81,6 +81,63 @@ public class InputMethodMenuControllerTest {
.isEqualTo(items.size());
}
+ /**
+ * Verifies that getMenuItems does not add a header or divider if all the items belong to
+ * a single input method.
+ */
+ @Test
+ public void testGetMenuItemsNoHeaderOrDividerForSingleInputMethod() {
+ final var items = new ArrayList<ImeSubtypeListItem>();
+ addTestImeSubtypeListItems(items, "LatinIme", "LatinIme",
+ List.of("en", "fr"), true /* supportsSwitchingToNextInputMethod */);
+
+ final var menuItems = getMenuItems(items);
+
+ assertThat(menuItems.stream()
+ .filter(item -> item instanceof HeaderItem || item instanceof DividerItem).toList())
+ .isEmpty();
+ }
+
+ /**
+ * Verifies that getMenuItems only adds headers for item groups with at least two items,
+ * or with a single item with a subtype name.
+ */
+ @Test
+ public void testGetMenuItemsHeaders() {
+ final var items = new ArrayList<ImeSubtypeListItem>();
+ addTestImeSubtypeListItems(items, "DefaultIme", "DefaultIme",
+ null, true /* supportsSwitchingToNextInputMethod */);
+ addTestImeSubtypeListItems(items, "LatinIme", "LatinIme",
+ List.of("en", "fr"), true /* supportsSwitchingToNextInputMethod */);
+ addTestImeSubtypeListItems(items, "ItalianIme", "ItalianIme",
+ List.of("it"), true /* supportsSwitchingToNextInputMethod */);
+ addTestImeSubtypeListItems(items, "SimpleIme", "SimpleIme",
+ null, true /* supportsSwitchingToNextInputMethod */);
+
+ final var menuItems = getMenuItems(items);
+
+ assertWithMessage("Must have menu items").that(menuItems).isNotEmpty();
+
+ final var headersAndDividers = menuItems.stream()
+ .filter(item -> item instanceof HeaderItem || item instanceof DividerItem)
+ .toList();
+
+ assertWithMessage("Must have header and divider items").that(headersAndDividers).hasSize(5);
+
+ assertWithMessage("First group has no header")
+ .that(menuItems.getFirst()).isInstanceOf(SubtypeItem.class);
+ assertWithMessage("Group with multiple items has divider")
+ .that(headersAndDividers.get(0)).isInstanceOf(DividerItem.class);
+ assertWithMessage("Group with multiple items has header")
+ .that(headersAndDividers.get(1)).isInstanceOf(HeaderItem.class);
+ assertWithMessage("Group with single item with subtype name has divider")
+ .that(headersAndDividers.get(2)).isInstanceOf(DividerItem.class);
+ assertWithMessage("Group with single item with subtype name has header")
+ .that(headersAndDividers.get(3)).isInstanceOf(HeaderItem.class);
+ assertWithMessage("Group with single item without subtype name has divider only")
+ .that(headersAndDividers.get(4)).isInstanceOf(DividerItem.class);
+ }
+
/** Verifies that getMenuItems adds a divider before every header except the first one. */
@Test
public void testGetMenuItemsDivider() {
@@ -107,8 +164,9 @@ public class InputMethodMenuControllerTest {
.that(prevItem).isInstanceOf(DividerItem.class);
} else if (item instanceof DividerItem && i < menuItems.size() - 1) {
final var nextItem = menuItems.get(i + 1);
- assertWithMessage("The item after a divider should be a header")
- .that(nextItem).isInstanceOf(HeaderItem.class);
+ assertWithMessage("The item after a divider should be a header or subtype")
+ .that(nextItem instanceof HeaderItem || nextItem instanceof SubtypeItem)
+ .isTrue();
}
}
}
@@ -170,7 +228,7 @@ public class InputMethodMenuControllerTest {
final int selectedIndex = getSelectedIndex(menuItems, simpleImeId, 1);
- // Two headers + one divider + two items
- assertThat(selectedIndex).isEqualTo(5);
+ // One header + one divider + two items
+ assertThat(selectedIndex).isEqualTo(4);
}
}