1 /*
2  * Copyright (C) 2014 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 
17 package com.android.inputmethod.keyboard;
18 
19 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_ICS;
20 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_KLP;
21 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_LXX_DARK;
22 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_LXX_LIGHT;
23 
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertFalse;
26 import static org.junit.Assert.assertNotNull;
27 import static org.junit.Assert.assertTrue;
28 
29 import android.content.Context;
30 import android.content.SharedPreferences;
31 import android.os.Build;
32 import android.os.Build.VERSION_CODES;
33 import android.preference.PreferenceManager;
34 
35 import androidx.test.InstrumentationRegistry;
36 import androidx.test.filters.SmallTest;
37 import androidx.test.runner.AndroidJUnit4;
38 
39 import org.junit.Before;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 
43 import java.util.Arrays;
44 
45 @SmallTest
46 @RunWith(AndroidJUnit4.class)
47 public class KeyboardThemeTests {
48     private SharedPreferences mPrefs;
49 
50     private static final int THEME_ID_NULL = -1;
51     private static final int THEME_ID_UNKNOWN = -2;
52     private static final int THEME_ID_ILLEGAL = -3;
53     private static final String ILLEGAL_THEME_ID_STRING = "ThisCausesNumberFormatExecption";
54 
getContext()55     private Context getContext() {
56         return InstrumentationRegistry.getTargetContext();
57     }
58 
59     @Before
setUp()60     public void setUp() throws Exception {
61         mPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
62     }
63 
64     /*
65      * Helper functions.
66      */
67 
isValidKeyboardThemeId(final int themeId)68     private static boolean isValidKeyboardThemeId(final int themeId) {
69         switch (themeId) {
70         case THEME_ID_ICS:
71         case THEME_ID_KLP:
72         case THEME_ID_LXX_LIGHT:
73         case THEME_ID_LXX_DARK:
74             return true;
75         default:
76             return false;
77         }
78     }
79 
setKeyboardThemePreference(final String prefKey, final int themeId)80     private void setKeyboardThemePreference(final String prefKey, final int themeId) {
81         final String themeIdString = Integer.toString(themeId);
82         if (isValidKeyboardThemeId(themeId) || themeId == THEME_ID_UNKNOWN) {
83             // Set valid theme id to preference.
84             mPrefs.edit().putString(prefKey, themeIdString).apply();
85             return;
86         }
87         if (themeId == THEME_ID_NULL) {
88             // Simulate undefined preference.
89             mPrefs.edit().remove(prefKey).apply();
90             return;
91         }
92         // themeId == THEME_ID_ILLEGAL
93         // Simulate illegal format theme id in preference.
94         mPrefs.edit().putString(prefKey, ILLEGAL_THEME_ID_STRING).apply();
95     }
96 
assertKeyboardTheme(final int sdkVersion, final int expectedThemeId)97     private void assertKeyboardTheme(final int sdkVersion, final int expectedThemeId) {
98         final KeyboardTheme actualTheme = KeyboardTheme.getKeyboardTheme(
99                 mPrefs, sdkVersion, KeyboardTheme.KEYBOARD_THEMES);
100         assertEquals(expectedThemeId, actualTheme.mThemeId);
101     }
102 
103     /*
104      * Test keyboard theme preference on the same platform version and the same keyboard version.
105      */
106 
assertKeyboardThemePreference(final int sdkVersion, final int previousThemeId, final int expectedThemeId)107     private void assertKeyboardThemePreference(final int sdkVersion, final int previousThemeId,
108             final int expectedThemeId) {
109         // Clear preferences before testing.
110         setKeyboardThemePreference(KeyboardTheme.KLP_KEYBOARD_THEME_KEY, THEME_ID_NULL);
111         setKeyboardThemePreference(KeyboardTheme.LXX_KEYBOARD_THEME_KEY, THEME_ID_NULL);
112         // Set the preference of the sdkVersion to previousThemeId.
113         final String prefKey = KeyboardTheme.getPreferenceKey(sdkVersion);
114         setKeyboardThemePreference(prefKey, previousThemeId);
115         assertKeyboardTheme(sdkVersion, expectedThemeId);
116     }
117 
assertKeyboardThemePreferenceOnKlp(final int sdkVersion)118     private void assertKeyboardThemePreferenceOnKlp(final int sdkVersion) {
119         final int defaultThemeId = THEME_ID_KLP;
120         assertKeyboardThemePreference(sdkVersion, THEME_ID_NULL, defaultThemeId);
121         assertKeyboardThemePreference(sdkVersion, THEME_ID_ICS, THEME_ID_ICS);
122         assertKeyboardThemePreference(sdkVersion, THEME_ID_KLP, THEME_ID_KLP);
123         assertKeyboardThemePreference(sdkVersion, THEME_ID_LXX_LIGHT, THEME_ID_LXX_LIGHT);
124         assertKeyboardThemePreference(sdkVersion, THEME_ID_LXX_DARK, THEME_ID_LXX_DARK);
125         assertKeyboardThemePreference(sdkVersion, THEME_ID_UNKNOWN, defaultThemeId);
126         assertKeyboardThemePreference(sdkVersion, THEME_ID_ILLEGAL, defaultThemeId);
127     }
128 
129     @Test
testKeyboardThemePreferenceOnKlp()130     public void testKeyboardThemePreferenceOnKlp() {
131         assertKeyboardThemePreferenceOnKlp(VERSION_CODES.ICE_CREAM_SANDWICH);
132         assertKeyboardThemePreferenceOnKlp(VERSION_CODES.ICE_CREAM_SANDWICH_MR1);
133         assertKeyboardThemePreferenceOnKlp(VERSION_CODES.JELLY_BEAN);
134         assertKeyboardThemePreferenceOnKlp(VERSION_CODES.JELLY_BEAN_MR1);
135         assertKeyboardThemePreferenceOnKlp(VERSION_CODES.JELLY_BEAN_MR2);
136         assertKeyboardThemePreferenceOnKlp(VERSION_CODES.KITKAT);
137     }
138 
assertKeyboardThemePreferenceOnLxx(final int sdkVersion)139     private void assertKeyboardThemePreferenceOnLxx(final int sdkVersion) {
140         final int defaultThemeId = THEME_ID_LXX_LIGHT;
141         assertKeyboardThemePreference(sdkVersion, THEME_ID_NULL, defaultThemeId);
142         assertKeyboardThemePreference(sdkVersion, THEME_ID_ICS, THEME_ID_ICS);
143         assertKeyboardThemePreference(sdkVersion, THEME_ID_KLP, THEME_ID_KLP);
144         assertKeyboardThemePreference(sdkVersion, THEME_ID_LXX_LIGHT, THEME_ID_LXX_LIGHT);
145         assertKeyboardThemePreference(sdkVersion, THEME_ID_LXX_DARK, THEME_ID_LXX_DARK);
146         assertKeyboardThemePreference(sdkVersion, THEME_ID_UNKNOWN, defaultThemeId);
147         assertKeyboardThemePreference(sdkVersion, THEME_ID_ILLEGAL, defaultThemeId);
148     }
149 
150     @Test
testKeyboardThemePreferenceOnLxx()151     public void testKeyboardThemePreferenceOnLxx() {
152         assertKeyboardThemePreferenceOnLxx(Build.VERSION_CODES.LOLLIPOP);
153     }
154 
155     /*
156      * Test default keyboard theme based on the platform version.
157      */
158 
assertDefaultKeyboardTheme(final int sdkVersion, final int previousThemeId, final int expectedThemeId)159     private void assertDefaultKeyboardTheme(final int sdkVersion, final int previousThemeId,
160             final int expectedThemeId) {
161         final String oldPrefKey = KeyboardTheme.KLP_KEYBOARD_THEME_KEY;
162         setKeyboardThemePreference(oldPrefKey, previousThemeId);
163 
164         final KeyboardTheme defaultTheme = KeyboardTheme.getDefaultKeyboardTheme(
165                 mPrefs, sdkVersion, KeyboardTheme.KEYBOARD_THEMES);
166 
167         assertNotNull(defaultTheme);
168         assertEquals(expectedThemeId, defaultTheme.mThemeId);
169         if (sdkVersion <= VERSION_CODES.KITKAT) {
170             // Old preference must be retained if it is valid. Otherwise it must be pruned.
171             assertEquals(isValidKeyboardThemeId(previousThemeId), mPrefs.contains(oldPrefKey));
172             return;
173         }
174         // Old preference must be removed.
175         assertFalse(mPrefs.contains(oldPrefKey));
176     }
177 
assertDefaultKeyboardThemeOnKlp(final int sdkVersion)178     private void assertDefaultKeyboardThemeOnKlp(final int sdkVersion) {
179         assertDefaultKeyboardTheme(sdkVersion, THEME_ID_NULL, THEME_ID_KLP);
180         assertDefaultKeyboardTheme(sdkVersion, THEME_ID_ICS, THEME_ID_ICS);
181         assertDefaultKeyboardTheme(sdkVersion, THEME_ID_KLP, THEME_ID_KLP);
182         assertDefaultKeyboardTheme(sdkVersion, THEME_ID_UNKNOWN, THEME_ID_KLP);
183         assertDefaultKeyboardTheme(sdkVersion, THEME_ID_ILLEGAL, THEME_ID_KLP);
184     }
185 
186     @Test
testDefaultKeyboardThemeOnKlp()187     public void testDefaultKeyboardThemeOnKlp() {
188         assertDefaultKeyboardThemeOnKlp(VERSION_CODES.ICE_CREAM_SANDWICH);
189         assertDefaultKeyboardThemeOnKlp(VERSION_CODES.ICE_CREAM_SANDWICH_MR1);
190         assertDefaultKeyboardThemeOnKlp(VERSION_CODES.JELLY_BEAN);
191         assertDefaultKeyboardThemeOnKlp(VERSION_CODES.JELLY_BEAN_MR1);
192         assertDefaultKeyboardThemeOnKlp(VERSION_CODES.JELLY_BEAN_MR2);
193         assertDefaultKeyboardThemeOnKlp(VERSION_CODES.KITKAT);
194     }
195 
assertDefaultKeyboardThemeOnLxx(final int sdkVersion)196     private void assertDefaultKeyboardThemeOnLxx(final int sdkVersion) {
197         // Forced to switch to LXX theme.
198         assertDefaultKeyboardTheme(sdkVersion, THEME_ID_NULL, THEME_ID_LXX_LIGHT);
199         assertDefaultKeyboardTheme(sdkVersion, THEME_ID_ICS, THEME_ID_LXX_LIGHT);
200         assertDefaultKeyboardTheme(sdkVersion, THEME_ID_KLP, THEME_ID_LXX_LIGHT);
201         assertDefaultKeyboardTheme(sdkVersion, THEME_ID_UNKNOWN, THEME_ID_LXX_LIGHT);
202         assertDefaultKeyboardTheme(sdkVersion, THEME_ID_ILLEGAL, THEME_ID_LXX_LIGHT);
203     }
204 
205     @Test
testDefaultKeyboardThemeOnLxx()206     public void testDefaultKeyboardThemeOnLxx() {
207         assertDefaultKeyboardThemeOnLxx(Build.VERSION_CODES.LOLLIPOP);
208     }
209 
210     /*
211      * Test keyboard theme preference while upgrading the keyboard that doesn't support LXX theme
212      * to the keyboard that supports LXX theme.
213      */
214 
assertUpgradeKeyboardToLxxOn(final int sdkVersion, final int previousThemeId, final int expectedThemeId)215     private void assertUpgradeKeyboardToLxxOn(final int sdkVersion, final int previousThemeId,
216             final int expectedThemeId) {
217         setKeyboardThemePreference(KeyboardTheme.KLP_KEYBOARD_THEME_KEY, previousThemeId);
218         // Clean up new keyboard theme preference to simulate "upgrade to LXX keyboard".
219         setKeyboardThemePreference(KeyboardTheme.LXX_KEYBOARD_THEME_KEY, THEME_ID_NULL);
220 
221         final KeyboardTheme theme = KeyboardTheme.getKeyboardTheme(
222                 mPrefs, sdkVersion, KeyboardTheme.KEYBOARD_THEMES);
223 
224         assertNotNull(theme);
225         assertEquals(expectedThemeId, theme.mThemeId);
226         if (sdkVersion <= VERSION_CODES.KITKAT) {
227             // New preference must not exist.
228             assertFalse(mPrefs.contains(KeyboardTheme.LXX_KEYBOARD_THEME_KEY));
229             // Old preference must be retained if it is valid. Otherwise it must be pruned.
230             assertEquals(isValidKeyboardThemeId(previousThemeId),
231                     mPrefs.contains(KeyboardTheme.KLP_KEYBOARD_THEME_KEY));
232             if (isValidKeyboardThemeId(previousThemeId)) {
233                 // Old preference must have an expected value.
234                 assertEquals(mPrefs.getString(KeyboardTheme.KLP_KEYBOARD_THEME_KEY, null),
235                         Integer.toString(expectedThemeId));
236             }
237             return;
238         }
239         // Old preference must be removed.
240         assertFalse(mPrefs.contains(KeyboardTheme.KLP_KEYBOARD_THEME_KEY));
241         // New preference must not exist.
242         assertFalse(mPrefs.contains(KeyboardTheme.LXX_KEYBOARD_THEME_KEY));
243     }
244 
assertUpgradeKeyboardToLxxOnKlp(final int sdkVersion)245     private void assertUpgradeKeyboardToLxxOnKlp(final int sdkVersion) {
246         assertUpgradeKeyboardToLxxOn(sdkVersion, THEME_ID_NULL, THEME_ID_KLP);
247         assertUpgradeKeyboardToLxxOn(sdkVersion, THEME_ID_ICS, THEME_ID_ICS);
248         assertUpgradeKeyboardToLxxOn(sdkVersion, THEME_ID_KLP, THEME_ID_KLP);
249         assertUpgradeKeyboardToLxxOn(sdkVersion, THEME_ID_UNKNOWN, THEME_ID_KLP);
250         assertUpgradeKeyboardToLxxOn(sdkVersion, THEME_ID_ILLEGAL, THEME_ID_KLP);
251     }
252 
253     // Upgrading keyboard on I,J and K.
254     @Test
testUpgradeKeyboardToLxxOnKlp()255     public void testUpgradeKeyboardToLxxOnKlp() {
256         assertUpgradeKeyboardToLxxOnKlp(VERSION_CODES.ICE_CREAM_SANDWICH);
257         assertUpgradeKeyboardToLxxOnKlp(VERSION_CODES.ICE_CREAM_SANDWICH_MR1);
258         assertUpgradeKeyboardToLxxOnKlp(VERSION_CODES.JELLY_BEAN);
259         assertUpgradeKeyboardToLxxOnKlp(VERSION_CODES.JELLY_BEAN_MR1);
260         assertUpgradeKeyboardToLxxOnKlp(VERSION_CODES.JELLY_BEAN_MR2);
261         assertUpgradeKeyboardToLxxOnKlp(VERSION_CODES.KITKAT);
262     }
263 
assertUpgradeKeyboardToLxxOnLxx(final int sdkVersion)264     private void assertUpgradeKeyboardToLxxOnLxx(final int sdkVersion) {
265         // Forced to switch to LXX theme.
266         assertUpgradeKeyboardToLxxOn(sdkVersion, THEME_ID_NULL, THEME_ID_LXX_LIGHT);
267         assertUpgradeKeyboardToLxxOn(sdkVersion, THEME_ID_ICS, THEME_ID_LXX_LIGHT);
268         assertUpgradeKeyboardToLxxOn(sdkVersion, THEME_ID_KLP, THEME_ID_LXX_LIGHT);
269         assertUpgradeKeyboardToLxxOn(sdkVersion, THEME_ID_UNKNOWN, THEME_ID_LXX_LIGHT);
270         assertUpgradeKeyboardToLxxOn(sdkVersion, THEME_ID_ILLEGAL, THEME_ID_LXX_LIGHT);
271     }
272 
273     // Upgrading keyboard on L.
274     @Test
testUpgradeKeyboardToLxxOnLxx()275     public void testUpgradeKeyboardToLxxOnLxx() {
276         assertUpgradeKeyboardToLxxOnLxx(Build.VERSION_CODES.LOLLIPOP);
277     }
278 
279     /*
280      * Test keyboard theme preference while upgrading platform version.
281      */
282 
assertUpgradePlatformFromTo(final int oldSdkVersion, final int newSdkVersion, final int previousThemeId, final int expectedThemeId)283     private void assertUpgradePlatformFromTo(final int oldSdkVersion, final int newSdkVersion,
284             final int previousThemeId, final int expectedThemeId) {
285         if (newSdkVersion < oldSdkVersion) {
286             // No need to test.
287             return;
288         }
289         // Clean up preferences.
290         setKeyboardThemePreference(KeyboardTheme.KLP_KEYBOARD_THEME_KEY, THEME_ID_NULL);
291         setKeyboardThemePreference(KeyboardTheme.LXX_KEYBOARD_THEME_KEY, THEME_ID_NULL);
292 
293         final String oldPrefKey = KeyboardTheme.getPreferenceKey(oldSdkVersion);
294         setKeyboardThemePreference(oldPrefKey, previousThemeId);
295 
296         assertKeyboardTheme(newSdkVersion, expectedThemeId);
297     }
298 
assertUpgradePlatformFromKlpToKlp(final int oldSdkVersion, final int newSdkVersion)299     private void assertUpgradePlatformFromKlpToKlp(final int oldSdkVersion,
300             final int newSdkVersion) {
301         assertUpgradePlatformFromTo(oldSdkVersion, newSdkVersion, THEME_ID_NULL, THEME_ID_KLP);
302         assertUpgradePlatformFromTo(oldSdkVersion, newSdkVersion, THEME_ID_ICS, THEME_ID_ICS);
303         assertUpgradePlatformFromTo(oldSdkVersion, newSdkVersion, THEME_ID_KLP, THEME_ID_KLP);
304         assertUpgradePlatformFromTo(oldSdkVersion, newSdkVersion, THEME_ID_UNKNOWN, THEME_ID_KLP);
305         assertUpgradePlatformFromTo(oldSdkVersion, newSdkVersion, THEME_ID_ILLEGAL, THEME_ID_KLP);
306     }
307 
assertUpgradePlatformToKlpFrom(final int oldSdkVersion)308     private void assertUpgradePlatformToKlpFrom(final int oldSdkVersion) {
309         assertUpgradePlatformFromKlpToKlp(oldSdkVersion, VERSION_CODES.ICE_CREAM_SANDWICH);
310         assertUpgradePlatformFromKlpToKlp(oldSdkVersion, VERSION_CODES.ICE_CREAM_SANDWICH_MR1);
311         assertUpgradePlatformFromKlpToKlp(oldSdkVersion, VERSION_CODES.JELLY_BEAN);
312         assertUpgradePlatformFromKlpToKlp(oldSdkVersion, VERSION_CODES.JELLY_BEAN_MR1);
313         assertUpgradePlatformFromKlpToKlp(oldSdkVersion, VERSION_CODES.JELLY_BEAN_MR2);
314         assertUpgradePlatformFromKlpToKlp(oldSdkVersion, VERSION_CODES.KITKAT);
315     }
316 
317     // Update platform from I,J, and K to I,J, and K
318     @Test
testUpgradePlatformToKlpFromKlp()319     public void testUpgradePlatformToKlpFromKlp() {
320         assertUpgradePlatformToKlpFrom(VERSION_CODES.ICE_CREAM_SANDWICH);
321         assertUpgradePlatformToKlpFrom(VERSION_CODES.ICE_CREAM_SANDWICH_MR1);
322         assertUpgradePlatformToKlpFrom(VERSION_CODES.JELLY_BEAN);
323         assertUpgradePlatformToKlpFrom(VERSION_CODES.JELLY_BEAN_MR1);
324         assertUpgradePlatformToKlpFrom(VERSION_CODES.JELLY_BEAN_MR2);
325         assertUpgradePlatformToKlpFrom(VERSION_CODES.KITKAT);
326     }
327 
assertUpgradePlatformToLxxFrom(final int oldSdkVersion)328     private void assertUpgradePlatformToLxxFrom(final int oldSdkVersion) {
329         // Forced to switch to LXX theme.
330         final int newSdkVersion = Build.VERSION_CODES.LOLLIPOP;
331         assertUpgradePlatformFromTo(
332                 oldSdkVersion, newSdkVersion, THEME_ID_NULL, THEME_ID_LXX_LIGHT);
333         assertUpgradePlatformFromTo(
334                 oldSdkVersion, newSdkVersion, THEME_ID_ICS, THEME_ID_LXX_LIGHT);
335         assertUpgradePlatformFromTo(
336                 oldSdkVersion, newSdkVersion, THEME_ID_KLP, THEME_ID_LXX_LIGHT);
337         assertUpgradePlatformFromTo(
338                 oldSdkVersion, newSdkVersion, THEME_ID_UNKNOWN, THEME_ID_LXX_LIGHT);
339         assertUpgradePlatformFromTo(
340                 oldSdkVersion, newSdkVersion, THEME_ID_ILLEGAL, THEME_ID_LXX_LIGHT);
341     }
342 
343     // Update platform from I,J, and K to L
344     @Test
testUpgradePlatformToLxx()345     public void testUpgradePlatformToLxx() {
346         assertUpgradePlatformToLxxFrom(VERSION_CODES.ICE_CREAM_SANDWICH);
347         assertUpgradePlatformToLxxFrom(VERSION_CODES.ICE_CREAM_SANDWICH_MR1);
348         assertUpgradePlatformToLxxFrom(VERSION_CODES.JELLY_BEAN);
349         assertUpgradePlatformToLxxFrom(VERSION_CODES.JELLY_BEAN_MR1);
350         assertUpgradePlatformToLxxFrom(VERSION_CODES.JELLY_BEAN_MR2);
351         assertUpgradePlatformToLxxFrom(VERSION_CODES.KITKAT);
352     }
353 
354     // Update platform from L to L.
355     @Test
testUpgradePlatformToLxxFromLxx()356     public void testUpgradePlatformToLxxFromLxx() {
357         final int oldSdkVersion = Build.VERSION_CODES.LOLLIPOP;
358         final int newSdkVersion = Build.VERSION_CODES.LOLLIPOP;
359         assertUpgradePlatformFromTo(
360                 oldSdkVersion, newSdkVersion, THEME_ID_NULL, THEME_ID_LXX_LIGHT);
361         assertUpgradePlatformFromTo(
362                 oldSdkVersion, newSdkVersion, THEME_ID_ICS, THEME_ID_ICS);
363         assertUpgradePlatformFromTo(
364                 oldSdkVersion, newSdkVersion, THEME_ID_KLP, THEME_ID_KLP);
365         assertUpgradePlatformFromTo(
366                 oldSdkVersion, newSdkVersion, THEME_ID_LXX_LIGHT, THEME_ID_LXX_LIGHT);
367         assertUpgradePlatformFromTo(
368                 oldSdkVersion, newSdkVersion, THEME_ID_LXX_DARK, THEME_ID_LXX_DARK);
369         assertUpgradePlatformFromTo(
370                 oldSdkVersion, newSdkVersion, THEME_ID_UNKNOWN, THEME_ID_LXX_LIGHT);
371         assertUpgradePlatformFromTo(
372                 oldSdkVersion, newSdkVersion, THEME_ID_ILLEGAL, THEME_ID_LXX_LIGHT);
373     }
374 
375     /*
376      * Test that KeyboardTheme array should be sorted by descending order of
377      * {@link KeyboardTheme#mMinApiVersion}.
378      */
assertSortedKeyboardThemeArray(final KeyboardTheme[] array)379     private static void assertSortedKeyboardThemeArray(final KeyboardTheme[] array) {
380         assertNotNull(array);
381         final int length = array.length;
382         assertTrue("array length=" + length, length > 0);
383         for (int index = 0; index < length - 1; index++) {
384             final KeyboardTheme theme = array[index];
385             final KeyboardTheme nextTheme = array[index + 1];
386             assertTrue("sorted MinApiVersion: "
387                     + theme.mThemeName + ": minApiVersion=" + theme.mMinApiVersion,
388                     theme.mMinApiVersion >= nextTheme.mMinApiVersion);
389         }
390     }
391 
392     @Test
testSortedKeyboardTheme()393     public void testSortedKeyboardTheme() {
394         assertSortedKeyboardThemeArray(KeyboardTheme.KEYBOARD_THEMES);
395     }
396 
397     @Test
testSortedAvailableKeyboardTheme()398     public void testSortedAvailableKeyboardTheme() {
399         assertSortedKeyboardThemeArray(KeyboardTheme.getAvailableThemeArray(getContext()));
400     }
401 
402     /*
403      * Test for missing selected theme.
404      */
405     private static KeyboardTheme[] LIMITED_THEMES = {
406         KeyboardTheme.searchKeyboardThemeById(THEME_ID_ICS, KeyboardTheme.KEYBOARD_THEMES),
407         KeyboardTheme.searchKeyboardThemeById(THEME_ID_KLP, KeyboardTheme.KEYBOARD_THEMES)
408     };
409     static {
410         Arrays.sort(LIMITED_THEMES);
411         assertSortedKeyboardThemeArray(LIMITED_THEMES);
412     }
413 
414     @Test
testMissingSelectedThemeIcs()415     public void testMissingSelectedThemeIcs() {
416         // Clean up preferences.
417         setKeyboardThemePreference(KeyboardTheme.KLP_KEYBOARD_THEME_KEY, THEME_ID_NULL);
418         setKeyboardThemePreference(KeyboardTheme.LXX_KEYBOARD_THEME_KEY, THEME_ID_NULL);
419 
420         final int sdkVersion = VERSION_CODES.ICE_CREAM_SANDWICH;
421         final String oldPrefKey = KeyboardTheme.getPreferenceKey(sdkVersion);
422         setKeyboardThemePreference(oldPrefKey, THEME_ID_LXX_LIGHT);
423 
424         final KeyboardTheme actualTheme = KeyboardTheme.getKeyboardTheme(
425                 mPrefs, sdkVersion, LIMITED_THEMES);
426         // LXX_LIGHT is missing, fall-back to KLP.
427         assertEquals(THEME_ID_KLP, actualTheme.mThemeId);
428     }
429 
430     @Test
testMissingSelectedThemeKlp()431     public void testMissingSelectedThemeKlp() {
432         // Clean up preferences.
433         setKeyboardThemePreference(KeyboardTheme.KLP_KEYBOARD_THEME_KEY, THEME_ID_NULL);
434         setKeyboardThemePreference(KeyboardTheme.LXX_KEYBOARD_THEME_KEY, THEME_ID_NULL);
435 
436         final int sdkVersion = VERSION_CODES.KITKAT;
437         final String oldPrefKey = KeyboardTheme.getPreferenceKey(sdkVersion);
438         setKeyboardThemePreference(oldPrefKey, THEME_ID_LXX_LIGHT);
439 
440         final KeyboardTheme actualTheme = KeyboardTheme.getKeyboardTheme(
441                 mPrefs, sdkVersion, LIMITED_THEMES);
442         // LXX_LIGHT is missing, fall-back to KLP.
443         assertEquals(THEME_ID_KLP, actualTheme.mThemeId);
444     }
445 
446     @Test
testMissingSelectedThemeLxx()447     public void testMissingSelectedThemeLxx() {
448         // Clean up preferences.
449         setKeyboardThemePreference(KeyboardTheme.KLP_KEYBOARD_THEME_KEY, THEME_ID_NULL);
450         setKeyboardThemePreference(KeyboardTheme.LXX_KEYBOARD_THEME_KEY, THEME_ID_NULL);
451 
452         final int sdkVersion = Build.VERSION_CODES.LOLLIPOP;
453         final String oldPrefKey = KeyboardTheme.getPreferenceKey(sdkVersion);
454         setKeyboardThemePreference(oldPrefKey, THEME_ID_LXX_DARK);
455 
456         final KeyboardTheme actualTheme = KeyboardTheme.getKeyboardTheme(
457                 mPrefs, sdkVersion, LIMITED_THEMES);
458         // LXX_DARK is missing, fall-back to KLP.
459         assertEquals(THEME_ID_KLP, actualTheme.mThemeId);
460     }
461 }
462