InputMethodTest.java revision 589800485d770cab7b159ffcf4b18c10ae2aee6d
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
19import com.android.internal.inputmethod.InputMethodUtils;
20
21import android.content.Context;
22import android.content.pm.ApplicationInfo;
23import android.content.pm.ResolveInfo;
24import android.content.pm.ServiceInfo;
25import android.test.InstrumentationTestCase;
26import android.test.suitebuilder.annotation.SmallTest;
27import android.view.inputmethod.InputMethodInfo;
28import android.view.inputmethod.InputMethodSubtype;
29
30import java.util.ArrayList;
31import java.util.List;
32
33public class InputMethodTest extends InstrumentationTestCase {
34    private static final boolean IS_AUX = true;
35    private static final boolean IS_DEFAULT = true;
36    private static final boolean IS_AUTO = true;
37    private static final ArrayList<InputMethodSubtype> NO_SUBTYPE = null;
38
39    @SmallTest
40    public void testDefaultEnabledImesWithDefaultVoiceIme() throws Exception {
41        final Context context = getInstrumentation().getTargetContext();
42        final ArrayList<InputMethodInfo> imis = new ArrayList<InputMethodInfo>();
43        imis.add(createDefaultAutoDummyVoiceIme());
44        imis.add(createNonDefaultAutoDummyVoiceIme0());
45        imis.add(createNonDefaultAutoDummyVoiceIme1());
46        imis.add(createNonDefaultDummyVoiceIme2());
47        imis.add(createDefaultDummyEnUSKeyboardIme());
48        imis.add(createNonDefaultDummyJaJPKeyboardIme());
49        imis.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes());
50        final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes(
51                context, true, imis);
52        assertEquals(2, enabledImis.size());
53        for (int i = 0; i < enabledImis.size(); ++i) {
54            final InputMethodInfo imi = enabledImis.get(0);
55            // "DummyDefaultAutoVoiceIme" and "DummyDefaultEnKeyboardIme"
56            if (imi.getPackageName().equals("DummyDefaultAutoVoiceIme")
57                    || imi.getPackageName().equals("DummyDefaultEnKeyboardIme")) {
58                continue;
59            } else {
60                fail("Invalid enabled subtype.");
61            }
62        }
63    }
64
65    @SmallTest
66    public void testDefaultEnabledImesWithOutDefaultVoiceIme() throws Exception {
67        final Context context = getInstrumentation().getTargetContext();
68        final ArrayList<InputMethodInfo> imis = new ArrayList<InputMethodInfo>();
69        imis.add(createNonDefaultAutoDummyVoiceIme0());
70        imis.add(createNonDefaultAutoDummyVoiceIme1());
71        imis.add(createNonDefaultDummyVoiceIme2());
72        imis.add(createDefaultDummyEnUSKeyboardIme());
73        imis.add(createNonDefaultDummyJaJPKeyboardIme());
74        imis.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes());
75        final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes(
76                context, true, imis);
77        assertEquals(3, enabledImis.size());
78        for (int i = 0; i < enabledImis.size(); ++i) {
79            final InputMethodInfo imi = enabledImis.get(0);
80            // "DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1" and
81            // "DummyDefaultEnKeyboardIme"
82            if (imi.getPackageName().equals("DummyNonDefaultAutoVoiceIme0")
83                    || imi.getPackageName().equals("DummyNonDefaultAutoVoiceIme1")
84                    || imi.getPackageName().equals("DummyDefaultEnKeyboardIme")) {
85                continue;
86            } else {
87                fail("Invalid enabled subtype.");
88            }
89        }
90    }
91
92    @SmallTest
93    public void testParcelable() throws Exception {
94        final ArrayList<InputMethodInfo> originalList = new ArrayList<InputMethodInfo>();
95        originalList.add(createNonDefaultAutoDummyVoiceIme0());
96        originalList.add(createNonDefaultAutoDummyVoiceIme1());
97        originalList.add(createNonDefaultDummyVoiceIme2());
98        originalList.add(createDefaultDummyEnUSKeyboardIme());
99        originalList.add(createNonDefaultDummyJaJPKeyboardIme());
100        originalList.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes());
101
102        final List<InputMethodInfo> clonedList = cloneViaParcel(originalList);
103        assertNotNull(clonedList);
104        assertEquals(originalList.size(), clonedList.size());
105        assertEquals(originalList, clonedList);
106
107        for (int imeIndex = 0; imeIndex < originalList.size(); ++imeIndex) {
108            final InputMethodInfo original = originalList.get(imeIndex);
109            final InputMethodInfo cloned = clonedList.get(imeIndex);
110            assertEquals(original, cloned);
111            assertEquals(original.getSubtypeCount(), cloned.getSubtypeCount());
112            for (int subtypeIndex = 0; subtypeIndex < original.getSubtypeCount(); ++subtypeIndex) {
113                final InputMethodSubtype originalSubtype = original.getSubtypeAt(subtypeIndex);
114                final InputMethodSubtype clonedSubtype = cloned.getSubtypeAt(subtypeIndex);
115                assertEquals(originalSubtype, clonedSubtype);
116                assertEquals(originalSubtype.hashCode(), clonedSubtype.hashCode());
117            }
118        }
119    }
120
121    private static List<InputMethodInfo> cloneViaParcel(final List<InputMethodInfo> list) {
122        Parcel p = null;
123        try {
124            p = Parcel.obtain();
125            p.writeTypedList(list);
126            p.setDataPosition(0);
127            return p.createTypedArrayList(InputMethodInfo.CREATOR);
128        } finally {
129            if (p != null) {
130                p.recycle();
131            }
132        }
133    }
134
135    private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name,
136            CharSequence label, boolean isAuxIme, boolean isDefault,
137            List<InputMethodSubtype> subtypes) {
138        final ResolveInfo ri = new ResolveInfo();
139        final ServiceInfo si = new ServiceInfo();
140        final ApplicationInfo ai = new ApplicationInfo();
141        ai.packageName = packageName;
142        ai.enabled = true;
143        ai.flags |= ApplicationInfo.FLAG_SYSTEM;
144        si.applicationInfo = ai;
145        si.enabled = true;
146        si.packageName = packageName;
147        si.name = name;
148        si.exported = true;
149        si.nonLocalizedLabel = label;
150        ri.serviceInfo = si;
151        return new InputMethodInfo(ri, isAuxIme, "", subtypes, 1, isDefault);
152    }
153
154    private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
155            boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
156        return new InputMethodSubtype(0, 0, locale, mode, "", isAuxiliary,
157                overridesImplicitlyEnabledSubtype);
158    }
159
160    private static InputMethodInfo createDefaultAutoDummyVoiceIme() {
161        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
162        subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO));
163        subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
164        return createDummyInputMethodInfo("DummyDefaultAutoVoiceIme", "dummy.voice0",
165                "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes);
166    }
167
168    private static InputMethodInfo createNonDefaultAutoDummyVoiceIme0() {
169        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
170        subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO));
171        subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
172        return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0", "dummy.voice1",
173                "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes);
174    }
175
176    private static InputMethodInfo createNonDefaultAutoDummyVoiceIme1() {
177        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
178        subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO));
179        subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
180        return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1", "dummy.voice2",
181                "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes);
182    }
183
184    private static InputMethodInfo createNonDefaultDummyVoiceIme2() {
185        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
186        subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO));
187        return createDummyInputMethodInfo("DummyNonDefaultVoiceIme2", "dummy.voice3",
188                "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes);
189    }
190
191    private static InputMethodInfo createDefaultDummyEnUSKeyboardIme() {
192        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
193        subtypes.add(createDummyInputMethodSubtype("en_US", "keyboard", !IS_AUX, !IS_AUTO));
194        return createDummyInputMethodInfo("DummyDefaultEnKeyboardIme", "dummy.keyboard0",
195                "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes);
196    }
197
198    private static InputMethodInfo createNonDefaultDummyJaJPKeyboardIme() {
199        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
200        subtypes.add(createDummyInputMethodSubtype("ja_JP", "keyboard", !IS_AUX, !IS_AUTO));
201        return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardIme", "dummy.keyboard1",
202                "DummyKeyboard1", !IS_AUX, !IS_DEFAULT, subtypes);
203    }
204
205    // Although IMEs that have no subtype are considered to be deprecated, the Android framework
206    // must still be able to handle such IMEs as well as IMEs that have at least one subtype.
207    private static InputMethodInfo createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes() {
208        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
209        return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardImeWithoutSubtypes",
210                "dummy.keyboard2", "DummyKeyboard2", !IS_AUX, !IS_DEFAULT, NO_SUBTYPE);
211    }
212}
213