blob: c0c20e2ff9f14fde4ff0bd2cf6d31a3df4836498 [file] [log] [blame]
/*
* Copyright (C) 2014 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 android.os;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ControllerImpl;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
import com.android.internal.inputmethod.InputMethodUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTestCase {
private static final String DUMMY_PACKAGE_NAME = "dymmy package name";
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 int DUMMY_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)
.setSubtypeIconResId(0)
.setSubtypeLocale(locale)
.setIsAsciiCapable(true)
.build();
}
private static void addDummyImeSubtypeListItems(List<ImeSubtypeListItem> items,
String imeName, String imeLabel, 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.enabled = true;
si.applicationInfo = ai;
si.enabled = true;
si.packageName = DUMMY_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>();
for (String subtypeLocale : subtypeLocales) {
subtypes.add(createDummySubtype(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);
if (subtypes == null) {
items.add(new ImeSubtypeListItem(imeName, null /* variableName */, imi,
NOT_A_SUBTYPE_ID, null, SYSTEM_LOCALE));
} else {
for (int i = 0; i < subtypes.size(); ++i) {
final String subtypeLocale = subtypeLocales.get(i);
items.add(new ImeSubtypeListItem(imeName, subtypeLocale, imi, i, subtypeLocale,
SYSTEM_LOCALE));
}
}
}
private static List<ImeSubtypeListItem> createEnabledImeSubtypes() {
final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
addDummyImeSubtypeListItems(items, "LatinIme", "LatinIme", Arrays.asList("en_US", "fr"),
true /* supportsSwitchingToNextInputMethod*/);
addDummyImeSubtypeListItems(items, "switchUnawareLatinIme", "switchUnawareLatinIme",
Arrays.asList("en_UK", "hi"),
false /* supportsSwitchingToNextInputMethod*/);
addDummyImeSubtypeListItems(items, "subtypeUnawareIme", "subtypeUnawareIme", null,
false /* supportsSwitchingToNextInputMethod*/);
addDummyImeSubtypeListItems(items, "JapaneseIme", "JapaneseIme", Arrays.asList("ja_JP"),
true /* supportsSwitchingToNextInputMethod*/);
addDummyImeSubtypeListItems(items, "switchUnawareJapaneseIme", "switchUnawareJapaneseIme",
Arrays.asList("ja_JP"), false /* supportsSwitchingToNextInputMethod*/);
return items;
}
private static List<ImeSubtypeListItem> createDisabledImeSubtypes() {
final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
addDummyImeSubtypeListItems(items,
"UnknownIme", "UnknownIme",
Arrays.asList("en_US", "hi"),
true /* supportsSwitchingToNextInputMethod*/);
addDummyImeSubtypeListItems(items,
"UnknownSwitchingUnawareIme", "UnknownSwitchingUnawareIme",
Arrays.asList("en_US"),
false /* supportsSwitchingToNextInputMethod*/);
addDummyImeSubtypeListItems(items, "UnknownSubtypeUnawareIme",
"UnknownSubtypeUnawareIme", null,
false /* supportsSwitchingToNextInputMethod*/);
return items;
}
private void assertNextInputMethod(final ControllerImpl controller,
final boolean onlyCurrentIme,
final ImeSubtypeListItem currentItem, final ImeSubtypeListItem nextItem) {
InputMethodSubtype subtype = null;
if (currentItem.mSubtypeName != null) {
subtype = createDummySubtype(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) {
final int N = expectedRotationOrderOfImeSubtypeList.length;
for (int i = 0; i < N; i++) {
final int currentIndex = i;
final int nextIndex = (currentIndex + 1) % N;
final ImeSubtypeListItem currentItem =
expectedRotationOrderOfImeSubtypeList[currentIndex];
final ImeSubtypeListItem nextItem = expectedRotationOrderOfImeSubtypeList[nextIndex];
assertNextInputMethod(controller, onlyCurrentIme, currentItem, nextItem);
}
}
private void onUserAction(final ControllerImpl controller,
final ImeSubtypeListItem subtypeListItem) {
InputMethodSubtype subtype = null;
if (subtypeListItem.mSubtypeName != null) {
subtype = createDummySubtype(subtypeListItem.mSubtypeName.toString());
}
controller.onUserActionLocked(subtypeListItem.mImi, subtype);
}
@SmallTest
public void testControllerImpl() throws Exception {
final List<ImeSubtypeListItem> disabledItems = createDisabledImeSubtypes();
final ImeSubtypeListItem disabledIme_en_US = disabledItems.get(0);
final ImeSubtypeListItem disabledIme_hi = disabledItems.get(1);
final ImeSubtypeListItem disabledSwitchingUnawareIme = disabledItems.get(2);
final ImeSubtypeListItem disabledSubtypeUnawareIme = disabledItems.get(3);
final List<ImeSubtypeListItem> enabledItems = createEnabledImeSubtypes();
final ImeSubtypeListItem latinIme_en_US = enabledItems.get(0);
final ImeSubtypeListItem latinIme_fr = enabledItems.get(1);
final ImeSubtypeListItem switchingUnawarelatinIme_en_UK = enabledItems.get(2);
final ImeSubtypeListItem switchingUnawarelatinIme_hi = enabledItems.get(3);
final ImeSubtypeListItem subtypeUnawareIme = enabledItems.get(4);
final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5);
final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6);
final ControllerImpl controller = new ControllerImpl(enabledItems);
// switching-aware loop
assertRotationOrder(controller, false /* onlyCurrentIme */,
latinIme_en_US, latinIme_fr, japaneseIme_ja_JP);
// switching-unaware loop
assertRotationOrder(controller, false /* onlyCurrentIme */,
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme,
switchUnawareJapaneseIme_ja_JP);
// test onlyCurrentIme == true
assertRotationOrder(controller, true /* onlyCurrentIme */,
latinIme_en_US, latinIme_fr);
assertRotationOrder(controller, true /* onlyCurrentIme */,
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
subtypeUnawareIme, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
japaneseIme_ja_JP, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
switchUnawareJapaneseIme_ja_JP, null);
// Make sure that disabled IMEs are not accepted.
assertNextInputMethod(controller, false /* onlyCurrentIme */,
disabledIme_en_US, null);
assertNextInputMethod(controller, false /* onlyCurrentIme */,
disabledIme_hi, null);
assertNextInputMethod(controller, false /* onlyCurrentIme */,
disabledSwitchingUnawareIme, null);
assertNextInputMethod(controller, false /* onlyCurrentIme */,
disabledSubtypeUnawareIme, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
disabledIme_en_US, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
disabledIme_hi, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
disabledSwitchingUnawareIme, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
disabledSubtypeUnawareIme, null);
}
// This test is disabled until DynamicRotationList is enabled.
@SmallTest
public void DISABLED_testControllerImplWithUserAction() throws Exception {
final List<ImeSubtypeListItem> enabledItems = createEnabledImeSubtypes();
final ImeSubtypeListItem latinIme_en_US = enabledItems.get(0);
final ImeSubtypeListItem latinIme_fr = enabledItems.get(1);
final ImeSubtypeListItem switchingUnawarelatinIme_en_UK = enabledItems.get(2);
final ImeSubtypeListItem switchingUnawarelatinIme_hi = enabledItems.get(3);
final ImeSubtypeListItem subtypeUnawareIme = enabledItems.get(4);
final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5);
final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6);
final ControllerImpl controller = new ControllerImpl(enabledItems);
// === switching-aware loop ===
assertRotationOrder(controller, false /* onlyCurrentIme */,
latinIme_en_US, latinIme_fr, japaneseIme_ja_JP);
// Then notify that a user did something for latinIme_fr.
onUserAction(controller, latinIme_fr);
assertRotationOrder(controller, false /* onlyCurrentIme */,
latinIme_fr, latinIme_en_US, japaneseIme_ja_JP);
// Then notify that a user did something for latinIme_fr again.
onUserAction(controller, latinIme_fr);
assertRotationOrder(controller, false /* onlyCurrentIme */,
latinIme_fr, latinIme_en_US, japaneseIme_ja_JP);
// Then notify that a user did something for japaneseIme_ja_JP.
onUserAction(controller, latinIme_fr);
assertRotationOrder(controller, false /* onlyCurrentIme */,
japaneseIme_ja_JP, latinIme_fr, latinIme_en_US);
// Check onlyCurrentIme == true.
assertNextInputMethod(controller, true /* onlyCurrentIme */,
japaneseIme_ja_JP, null);
assertRotationOrder(controller, true /* onlyCurrentIme */,
latinIme_fr, latinIme_en_US);
assertRotationOrder(controller, true /* onlyCurrentIme */,
latinIme_en_US, latinIme_fr);
// === switching-unaware loop ===
assertRotationOrder(controller, false /* onlyCurrentIme */,
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme,
switchUnawareJapaneseIme_ja_JP);
// User action should be ignored for switching unaware IMEs.
onUserAction(controller, switchingUnawarelatinIme_hi);
assertRotationOrder(controller, false /* onlyCurrentIme */,
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme,
switchUnawareJapaneseIme_ja_JP);
// User action should be ignored for switching unaware IMEs.
onUserAction(controller, switchUnawareJapaneseIme_ja_JP);
assertRotationOrder(controller, false /* onlyCurrentIme */,
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme,
switchUnawareJapaneseIme_ja_JP);
// Check onlyCurrentIme == true.
assertRotationOrder(controller, true /* onlyCurrentIme */,
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
subtypeUnawareIme, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
switchUnawareJapaneseIme_ja_JP, null);
}
}