KeyboardTheme.java revision 8f3e778a21ff2c8855fb0014116eda9eec7f2b5d
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
17package com.android.inputmethod.keyboard;
18
19import android.content.SharedPreferences;
20import android.os.Build;
21import android.os.Build.VERSION_CODES;
22import android.util.Log;
23
24import com.android.inputmethod.annotations.UsedForTesting;
25import com.android.inputmethod.latin.R;
26
27import java.util.Arrays;
28
29public 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    public static final int THEME_ID_ICS = 0;
36    public static final int THEME_ID_KLP = 2;
37    public static final int THEME_ID_LXX_LIGHT = 3;
38    public static final int THEME_ID_LXX_DARK = 4;
39    public static final int DEFAULT_THEME_ID = THEME_ID_KLP;
40
41    private static final KeyboardTheme[] KEYBOARD_THEMES = {
42        new KeyboardTheme(THEME_ID_ICS, R.style.KeyboardTheme_ICS,
43                // This has never been selected because we support ICS or later.
44                VERSION_CODES.BASE),
45        new KeyboardTheme(THEME_ID_KLP, R.style.KeyboardTheme_KLP,
46                // Default theme for ICS, JB, and KLP.
47                VERSION_CODES.ICE_CREAM_SANDWICH),
48        new KeyboardTheme(THEME_ID_LXX_LIGHT, R.style.KeyboardTheme_LXX_Light,
49                // Default theme for LXX.
50                // TODO: Update this constant once the *next* version becomes available.
51                VERSION_CODES.CUR_DEVELOPMENT),
52        new KeyboardTheme(THEME_ID_LXX_DARK, R.style.KeyboardTheme_LXX_Dark,
53                VERSION_CODES.BASE),
54    };
55
56    static {
57        // Sort {@link #KEYBOARD_THEME} by descending order of {@link #mMinApiVersion}.
58        Arrays.sort(KEYBOARD_THEMES);
59    }
60
61    public final int mThemeId;
62    public final int mStyleId;
63    private final int mMinApiVersion;
64
65    // Note: The themeId should be aligned with "themeId" attribute of Keyboard style
66    // in values/themes-<style>.xml.
67    private KeyboardTheme(final int themeId, final int styleId, final int minApiVersion) {
68        mThemeId = themeId;
69        mStyleId = styleId;
70        mMinApiVersion = minApiVersion;
71    }
72
73    @Override
74    public int compareTo(final KeyboardTheme rhs) {
75        if (mMinApiVersion > rhs.mMinApiVersion) return -1;
76        if (mMinApiVersion < rhs.mMinApiVersion) return 1;
77        return 0;
78    }
79
80    @Override
81    public boolean equals(final Object o) {
82        if (o == this) return true;
83        return (o instanceof KeyboardTheme) && ((KeyboardTheme)o).mThemeId == mThemeId;
84    }
85
86    @Override
87    public int hashCode() {
88        return mThemeId;
89    }
90
91    @UsedForTesting
92    static KeyboardTheme searchKeyboardThemeById(final int themeId) {
93        // TODO: This search algorithm isn't optimal if there are many themes.
94        for (final KeyboardTheme theme : KEYBOARD_THEMES) {
95            if (theme.mThemeId == themeId) {
96                return theme;
97            }
98        }
99        return null;
100    }
101
102    private static int getSdkVersion() {
103        final int sdkVersion = Build.VERSION.SDK_INT;
104        // TODO: Consider to remove this check once the *next* version becomes available.
105        if (sdkVersion > VERSION_CODES.KITKAT) {
106            return VERSION_CODES.CUR_DEVELOPMENT;
107        }
108        return sdkVersion;
109    }
110
111    @UsedForTesting
112    static KeyboardTheme getDefaultKeyboardTheme(final SharedPreferences prefs,
113            final int sdkVersion) {
114        final String klpThemeIdString = prefs.getString(KLP_KEYBOARD_THEME_KEY, null);
115        if (klpThemeIdString != null) {
116            if (sdkVersion <= VERSION_CODES.KITKAT) {
117                try {
118                    final int themeId = Integer.parseInt(klpThemeIdString);
119                    final KeyboardTheme theme = searchKeyboardThemeById(themeId);
120                    if (theme != null) {
121                        return theme;
122                    }
123                    Log.w(TAG, "Unknown keyboard theme in KLP preference: " + klpThemeIdString);
124                } catch (final NumberFormatException e) {
125                    Log.w(TAG, "Illegal keyboard theme in KLP preference: " + klpThemeIdString, e);
126                }
127            }
128            // Remove old preference.
129            Log.i(TAG, "Remove KLP keyboard theme preference: " + klpThemeIdString);
130            prefs.edit().remove(KLP_KEYBOARD_THEME_KEY).apply();
131        }
132        // TODO: This search algorithm isn't optimal if there are many themes.
133        for (final KeyboardTheme theme : KEYBOARD_THEMES) {
134            if (sdkVersion >= theme.mMinApiVersion) {
135                return theme;
136            }
137        }
138        return searchKeyboardThemeById(DEFAULT_THEME_ID);
139    }
140
141    public static void saveKeyboardThemeId(final String themeIdString,
142            final SharedPreferences prefs) {
143        saveKeyboardThemeId(themeIdString, prefs, getSdkVersion());
144    }
145
146    @UsedForTesting
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
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
161    public static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs) {
162        return getKeyboardTheme(prefs, getSdkVersion());
163    }
164
165    @UsedForTesting
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