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 android.content.SharedPreferences; 20 import android.os.Build.VERSION_CODES; 21 import android.util.Log; 22 23 import com.android.inputmethod.annotations.UsedForTesting; 24 import com.android.inputmethod.compat.BuildCompatUtils; 25 import com.android.inputmethod.latin.R; 26 27 import java.util.Arrays; 28 29 public final class KeyboardTheme implements Comparable<KeyboardTheme> { 30 private static final String TAG = KeyboardTheme.class.getSimpleName(); 31 32 static final String KLP_KEYBOARD_THEME_KEY = "pref_keyboard_layout_20110916"; 33 static final String LXX_KEYBOARD_THEME_KEY = "pref_keyboard_theme_20140509"; 34 35 // These should be aligned with Keyboard.themeId and Keyboard.Case.keyboardTheme 36 // attributes' values in attrs.xml. 37 public static final int THEME_ID_ICS = 0; 38 public static final int THEME_ID_KLP = 2; 39 public static final int THEME_ID_LXX_LIGHT = 3; 40 public static final int THEME_ID_LXX_DARK = 4; 41 public static final int DEFAULT_THEME_ID = THEME_ID_KLP; 42 43 private static final KeyboardTheme[] KEYBOARD_THEMES = { 44 new KeyboardTheme(THEME_ID_ICS, "ICS", R.style.KeyboardTheme_ICS, 45 // This has never been selected because we support ICS or later. 46 VERSION_CODES.BASE), 47 new KeyboardTheme(THEME_ID_KLP, "KLP", R.style.KeyboardTheme_KLP, 48 // Default theme for ICS, JB, and KLP. 49 VERSION_CODES.ICE_CREAM_SANDWICH), 50 new KeyboardTheme(THEME_ID_LXX_LIGHT, "LXXLight", R.style.KeyboardTheme_LXX_Light, 51 // Default theme for LXX. 52 BuildCompatUtils.VERSION_CODES_LXX), 53 new KeyboardTheme(THEME_ID_LXX_DARK, "LXXDark", R.style.KeyboardTheme_LXX_Dark, 54 VERSION_CODES.BASE), 55 }; 56 57 static { 58 // Sort {@link #KEYBOARD_THEME} by descending order of {@link #mMinApiVersion}. 59 Arrays.sort(KEYBOARD_THEMES); 60 } 61 62 public final int mThemeId; 63 public final int mStyleId; 64 public final String mThemeName; 65 private final int mMinApiVersion; 66 67 // Note: The themeId should be aligned with "themeId" attribute of Keyboard style 68 // in values/themes-<style>.xml. KeyboardTheme(final int themeId, final String themeName, final int styleId, final int minApiVersion)69 private KeyboardTheme(final int themeId, final String themeName, final int styleId, 70 final int minApiVersion) { 71 mThemeId = themeId; 72 mThemeName = themeName; 73 mStyleId = styleId; 74 mMinApiVersion = minApiVersion; 75 } 76 77 @Override compareTo(final KeyboardTheme rhs)78 public int compareTo(final KeyboardTheme rhs) { 79 if (mMinApiVersion > rhs.mMinApiVersion) return -1; 80 if (mMinApiVersion < rhs.mMinApiVersion) return 1; 81 return 0; 82 } 83 84 @Override equals(final Object o)85 public boolean equals(final Object o) { 86 if (o == this) return true; 87 return (o instanceof KeyboardTheme) && ((KeyboardTheme)o).mThemeId == mThemeId; 88 } 89 90 @Override hashCode()91 public int hashCode() { 92 return mThemeId; 93 } 94 95 @UsedForTesting searchKeyboardThemeById(final int themeId)96 static KeyboardTheme searchKeyboardThemeById(final int themeId) { 97 // TODO: This search algorithm isn't optimal if there are many themes. 98 for (final KeyboardTheme theme : KEYBOARD_THEMES) { 99 if (theme.mThemeId == themeId) { 100 return theme; 101 } 102 } 103 return null; 104 } 105 106 @UsedForTesting getDefaultKeyboardTheme(final SharedPreferences prefs, final int sdkVersion)107 static KeyboardTheme getDefaultKeyboardTheme(final SharedPreferences prefs, 108 final int sdkVersion) { 109 final String klpThemeIdString = prefs.getString(KLP_KEYBOARD_THEME_KEY, null); 110 if (klpThemeIdString != null) { 111 if (sdkVersion <= VERSION_CODES.KITKAT) { 112 try { 113 final int themeId = Integer.parseInt(klpThemeIdString); 114 final KeyboardTheme theme = searchKeyboardThemeById(themeId); 115 if (theme != null) { 116 return theme; 117 } 118 Log.w(TAG, "Unknown keyboard theme in KLP preference: " + klpThemeIdString); 119 } catch (final NumberFormatException e) { 120 Log.w(TAG, "Illegal keyboard theme in KLP preference: " + klpThemeIdString, e); 121 } 122 } 123 // Remove old preference. 124 Log.i(TAG, "Remove KLP keyboard theme preference: " + klpThemeIdString); 125 prefs.edit().remove(KLP_KEYBOARD_THEME_KEY).apply(); 126 } 127 // TODO: This search algorithm isn't optimal if there are many themes. 128 for (final KeyboardTheme theme : KEYBOARD_THEMES) { 129 if (sdkVersion >= theme.mMinApiVersion) { 130 return theme; 131 } 132 } 133 return searchKeyboardThemeById(DEFAULT_THEME_ID); 134 } 135 getKeyboardThemeName(final int themeId)136 public static String getKeyboardThemeName(final int themeId) { 137 final KeyboardTheme theme = searchKeyboardThemeById(themeId); 138 return theme.mThemeName; 139 } 140 saveKeyboardThemeId(final String themeIdString, final SharedPreferences prefs)141 public static void saveKeyboardThemeId(final String themeIdString, 142 final SharedPreferences prefs) { 143 saveKeyboardThemeId(themeIdString, prefs, BuildCompatUtils.EFFECTIVE_SDK_INT); 144 } 145 146 @UsedForTesting getPreferenceKey(final int sdkVersion)147 static String getPreferenceKey(final int sdkVersion) { 148 if (sdkVersion <= VERSION_CODES.KITKAT) { 149 return KLP_KEYBOARD_THEME_KEY; 150 } 151 return LXX_KEYBOARD_THEME_KEY; 152 } 153 154 @UsedForTesting saveKeyboardThemeId(final String themeIdString, final SharedPreferences prefs, final int sdkVersion)155 static void saveKeyboardThemeId(final String themeIdString, 156 final SharedPreferences prefs, final int sdkVersion) { 157 final String prefKey = getPreferenceKey(sdkVersion); 158 prefs.edit().putString(prefKey, themeIdString).apply(); 159 } 160 getKeyboardTheme(final SharedPreferences prefs)161 public static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs) { 162 return getKeyboardTheme(prefs, BuildCompatUtils.EFFECTIVE_SDK_INT); 163 } 164 165 @UsedForTesting getKeyboardTheme(final SharedPreferences prefs, final int sdkVersion)166 static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs, final int sdkVersion) { 167 final String lxxThemeIdString = prefs.getString(LXX_KEYBOARD_THEME_KEY, null); 168 if (lxxThemeIdString == null) { 169 return getDefaultKeyboardTheme(prefs, sdkVersion); 170 } 171 try { 172 final int themeId = Integer.parseInt(lxxThemeIdString); 173 final KeyboardTheme theme = searchKeyboardThemeById(themeId); 174 if (theme != null) { 175 return theme; 176 } 177 Log.w(TAG, "Unknown keyboard theme in LXX preference: " + lxxThemeIdString); 178 } catch (final NumberFormatException e) { 179 Log.w(TAG, "Illegal keyboard theme in LXX preference: " + lxxThemeIdString, e); 180 } 181 // Remove preference that contains unknown or illegal theme id. 182 prefs.edit().remove(LXX_KEYBOARD_THEME_KEY).apply(); 183 return getDefaultKeyboardTheme(prefs, sdkVersion); 184 } 185 } 186