KeyboardTheme.java revision f9f409530ccdc975ef965b1d1fee44bbd341d718
1d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka/* 2d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * Copyright (C) 2014 The Android Open Source Project 3d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * 4d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 5d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * you may not use this file except in compliance with the License. 6d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * You may obtain a copy of the License at 7d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * 8d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 9d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * 10d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 11d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 12d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * See the License for the specific language governing permissions and 14d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka * limitations under the License. 15d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka */ 16d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka 17d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaokapackage com.android.inputmethod.keyboard; 18d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka 1921eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaokaimport android.content.SharedPreferences; 2059c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaokaimport android.os.Build; 2159c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaokaimport android.os.Build.VERSION_CODES; 2221eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaokaimport android.util.Log; 2321eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka 24c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaokaimport com.android.inputmethod.annotations.UsedForTesting; 25d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaokaimport com.android.inputmethod.latin.R; 2659c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka 2759c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaokaimport java.util.Arrays; 28d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka 29c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaokapublic final class KeyboardTheme implements Comparable<KeyboardTheme> { 3021eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka private static final String TAG = KeyboardTheme.class.getSimpleName(); 3121eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka 323b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka static final String KLP_KEYBOARD_THEME_KEY = "pref_keyboard_layout_20110916"; 333b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka static final String LXX_KEYBOARD_THEME_KEY = "pref_keyboard_theme_20140509"; 3459c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka 35c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka public static final int THEME_ID_ICS = 0; 36c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka public static final int THEME_ID_KLP = 2; 37f9f409530ccdc975ef965b1d1fee44bbd341d718Tadashi G. Takaoka public static final int THEME_ID_LXX_LIGHT = 3; 38f9f409530ccdc975ef965b1d1fee44bbd341d718Tadashi G. Takaoka public static final int THEME_ID_LXX_DARK = 4; 39c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka public static final int DEFAULT_THEME_ID = THEME_ID_KLP; 4021eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka 4121eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka private static final KeyboardTheme[] KEYBOARD_THEMES = { 4259c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka new KeyboardTheme(THEME_ID_ICS, R.style.KeyboardTheme_ICS, 43c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka // This has never been selected because we support ICS or later. 443b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka VERSION_CODES.BASE), 4559c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka new KeyboardTheme(THEME_ID_KLP, R.style.KeyboardTheme_KLP, 46c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka // Default theme for ICS, JB, and KLP. 473b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka VERSION_CODES.ICE_CREAM_SANDWICH), 48f9f409530ccdc975ef965b1d1fee44bbd341d718Tadashi G. Takaoka new KeyboardTheme(THEME_ID_LXX_LIGHT, R.style.KeyboardTheme_LXX_Light, 49c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka // Default theme for LXX. 5059c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka // TODO: Update this constant once the *next* version becomes available. 5159c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka VERSION_CODES.CUR_DEVELOPMENT), 52f9f409530ccdc975ef965b1d1fee44bbd341d718Tadashi G. Takaoka new KeyboardTheme(THEME_ID_LXX_DARK, R.style.KeyboardTheme_LXX_Dark, 53f9f409530ccdc975ef965b1d1fee44bbd341d718Tadashi G. Takaoka VERSION_CODES.BASE), 54d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka }; 55c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka 5659c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka static { 5759c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka // Sort {@link #KEYBOARD_THEME} by descending order of {@link #mMinApiVersion}. 58c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka Arrays.sort(KEYBOARD_THEMES); 5959c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 60d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka 61d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka public final int mThemeId; 62d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka public final int mStyleId; 63c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka private final int mMinApiVersion; 64d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka 65d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka // Note: The themeId should be aligned with "themeId" attribute of Keyboard style 6659c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka // in values/themes-<style>.xml. 6759c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka private KeyboardTheme(final int themeId, final int styleId, final int minApiVersion) { 68d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka mThemeId = themeId; 69d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka mStyleId = styleId; 7059c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka mMinApiVersion = minApiVersion; 7159c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 7259c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka 7359c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka @Override 74c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka public int compareTo(final KeyboardTheme rhs) { 75c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka if (mMinApiVersion > rhs.mMinApiVersion) return -1; 76c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka if (mMinApiVersion < rhs.mMinApiVersion) return 1; 77c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka return 0; 78c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka } 79c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka 80c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka @Override 8159c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka public boolean equals(final Object o) { 8259c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka if (o == this) return true; 8359c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka return (o instanceof KeyboardTheme) && ((KeyboardTheme)o).mThemeId == mThemeId; 84d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka } 8521eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka 8659c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka @Override 8759c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka public int hashCode() { 8859c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka return mThemeId; 8959c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 9059c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka 91c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka @UsedForTesting 92c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka static KeyboardTheme searchKeyboardThemeById(final int themeId) { 9321eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka // TODO: This search algorithm isn't optimal if there are many themes. 9421eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka for (final KeyboardTheme theme : KEYBOARD_THEMES) { 9521eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka if (theme.mThemeId == themeId) { 9621eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka return theme; 9721eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka } 9821eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka } 9921eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka return null; 10021eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka } 10121eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka 10259c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka private static int getSdkVersion() { 10359c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka final int sdkVersion = Build.VERSION.SDK_INT; 10459c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka // TODO: Consider to remove this check once the *next* version becomes available. 1054f28b22766e06b8c62636527393945114ea78002Tadashi G. Takaoka if (sdkVersion > VERSION_CODES.KITKAT) { 10659c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka return VERSION_CODES.CUR_DEVELOPMENT; 10759c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 10859c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka return sdkVersion; 10959c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 11059c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka 111c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka @UsedForTesting 11259c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka static KeyboardTheme getDefaultKeyboardTheme(final SharedPreferences prefs, 11359c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka final int sdkVersion) { 1143b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka final String klpThemeIdString = prefs.getString(KLP_KEYBOARD_THEME_KEY, null); 1153b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka if (klpThemeIdString != null) { 11659c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka if (sdkVersion <= VERSION_CODES.KITKAT) { 11759c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka try { 1183b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka final int themeId = Integer.parseInt(klpThemeIdString); 11959c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka final KeyboardTheme theme = searchKeyboardThemeById(themeId); 12059c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka if (theme != null) { 12159c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka return theme; 12259c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 1233b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka Log.w(TAG, "Unknown keyboard theme in KLP preference: " + klpThemeIdString); 12459c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } catch (final NumberFormatException e) { 1253b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka Log.w(TAG, "Illegal keyboard theme in KLP preference: " + klpThemeIdString, e); 12659c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 12759c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 1283b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka // Remove old preference. 1293b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka Log.i(TAG, "Remove KLP keyboard theme preference: " + klpThemeIdString); 1303b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka prefs.edit().remove(KLP_KEYBOARD_THEME_KEY).apply(); 13159c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 13259c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka // TODO: This search algorithm isn't optimal if there are many themes. 13359c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka for (final KeyboardTheme theme : KEYBOARD_THEMES) { 13459c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka if (sdkVersion >= theme.mMinApiVersion) { 13559c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka return theme; 13659c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 13759c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 13859c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka return searchKeyboardThemeById(DEFAULT_THEME_ID); 13959c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka } 14059c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka 14159c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka public static void saveKeyboardThemeId(final String themeIdString, 14259c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka final SharedPreferences prefs) { 1433b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka saveKeyboardThemeId(themeIdString, prefs, getSdkVersion()); 1443b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka } 1453b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka 146c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka @UsedForTesting 1473b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka static String getPreferenceKey(final int sdkVersion) { 1483b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka if (sdkVersion <= VERSION_CODES.KITKAT) { 1493b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka return KLP_KEYBOARD_THEME_KEY; 1503b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka } 1513b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka return LXX_KEYBOARD_THEME_KEY; 1523b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka } 1533b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka 154c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka @UsedForTesting 155c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka static void saveKeyboardThemeId(final String themeIdString, 156c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka final SharedPreferences prefs, final int sdkVersion) { 1573b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka final String prefKey = getPreferenceKey(sdkVersion); 1583b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka prefs.edit().putString(prefKey, themeIdString).apply(); 15921eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka } 16021eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka 16121eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka public static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs) { 1623b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka return getKeyboardTheme(prefs, getSdkVersion()); 1633b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka } 1643b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka 165c5dc74067385f9ab6ec3086825d0b369c26a1ea3Tadashi G. Takaoka @UsedForTesting 1663b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs, final int sdkVersion) { 1673b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka final String lxxThemeIdString = prefs.getString(LXX_KEYBOARD_THEME_KEY, null); 1683b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka if (lxxThemeIdString == null) { 16959c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka return getDefaultKeyboardTheme(prefs, sdkVersion); 17021eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka } 17121eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka try { 1723b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka final int themeId = Integer.parseInt(lxxThemeIdString); 17359c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka final KeyboardTheme theme = searchKeyboardThemeById(themeId); 17421eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka if (theme != null) { 17521eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka return theme; 17621eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka } 1773b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka Log.w(TAG, "Unknown keyboard theme in LXX preference: " + lxxThemeIdString); 17821eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka } catch (final NumberFormatException e) { 1793b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka Log.w(TAG, "Illegal keyboard theme in LXX preference: " + lxxThemeIdString, e); 18021eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka } 1813b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka // Remove preference that contains unknown or illegal theme id. 1823b12718537f40b262e5eeb5c8168d69b2afa6955Tadashi G. Takaoka prefs.edit().remove(LXX_KEYBOARD_THEME_KEY).apply(); 18359c3ef1ff8df23e3c3e3f549c0289c479553c666Tadashi G. Takaoka return getDefaultKeyboardTheme(prefs, sdkVersion); 18421eafd7910182a31372fb92895f057cff28a8480Tadashi G. Takaoka } 185d6aa94e6b5fd7abc25a8d21857211ffd0852b33aTadashi G. Takaoka} 186