Settings.java revision d7491e6e817e8954d15aa91300d209fb7e8bf384
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 com.android.inputmethod.latin.settings;
18
19import android.content.Context;
20import android.content.SharedPreferences;
21import android.content.pm.ApplicationInfo;
22import android.content.res.Resources;
23import android.preference.PreferenceManager;
24import android.util.Log;
25
26import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
27import com.android.inputmethod.latin.InputAttributes;
28import com.android.inputmethod.latin.R;
29import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
30import com.android.inputmethod.latin.utils.LocaleUtils;
31import com.android.inputmethod.latin.utils.ResourceUtils;
32import com.android.inputmethod.latin.utils.RunInLocale;
33
34import java.util.HashMap;
35import java.util.Locale;
36
37public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener {
38    private static final String TAG = Settings.class.getSimpleName();
39    // In the same order as xml/prefs.xml
40    public static final String PREF_GENERAL_SETTINGS = "general_settings";
41    public static final String PREF_AUTO_CAP = "auto_cap";
42    public static final String PREF_VIBRATE_ON = "vibrate_on";
43    public static final String PREF_SOUND_ON = "sound_on";
44    public static final String PREF_POPUP_ON = "popup_on";
45    public static final String PREF_VOICE_MODE = "voice_mode";
46    public static final String PREF_CORRECTION_SETTINGS = "correction_settings";
47    public static final String PREF_EDIT_PERSONAL_DICTIONARY = "edit_personal_dictionary";
48    public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key";
49    public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold";
50    public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
51    public static final String PREF_MISC_SETTINGS = "misc_settings";
52    public static final String PREF_LAST_USER_DICTIONARY_WRITE_TIME =
53            "last_user_dictionary_write_time";
54    public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings";
55    public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict";
56    public static final String PREF_KEY_USE_DOUBLE_SPACE_PERIOD =
57            "pref_key_use_double_space_period";
58    public static final String PREF_BLOCK_POTENTIALLY_OFFENSIVE =
59            "pref_key_block_potentially_offensive";
60    public static final String PREF_SHOW_LANGUAGE_SWITCH_KEY =
61            "pref_show_language_switch_key";
62    public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST =
63            "pref_include_other_imes_in_language_switch_list";
64    public static final String PREF_CUSTOM_INPUT_STYLES = "custom_input_styles";
65    public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
66            "pref_key_preview_popup_dismiss_delay";
67    public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction";
68    public static final String PREF_GESTURE_SETTINGS = "gesture_typing_settings";
69    public static final String PREF_GESTURE_INPUT = "gesture_input";
70    public static final String PREF_SLIDING_KEY_INPUT_PREVIEW = "pref_sliding_key_input_preview";
71    public static final String PREF_KEY_LONGPRESS_TIMEOUT = "pref_key_longpress_timeout";
72    public static final String PREF_VIBRATION_DURATION_SETTINGS =
73            "pref_vibration_duration_settings";
74    public static final String PREF_KEYPRESS_SOUND_VOLUME =
75            "pref_keypress_sound_volume";
76    public static final String PREF_GESTURE_PREVIEW_TRAIL = "pref_gesture_preview_trail";
77    public static final String PREF_GESTURE_FLOATING_PREVIEW_TEXT =
78            "pref_gesture_floating_preview_text";
79    public static final String PREF_SHOW_SETUP_WIZARD_ICON = "pref_show_setup_wizard_icon";
80
81    public static final String PREF_INPUT_LANGUAGE = "input_language";
82    public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
83    public static final String PREF_DEBUG_SETTINGS = "debug_settings";
84    public static final String PREF_KEY_IS_INTERNAL = "pref_key_is_internal";
85
86    // This preference key is deprecated. Use {@link #PREF_SHOW_LANGUAGE_SWITCH_KEY} instead.
87    // This is being used only for the backward compatibility.
88    private static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY =
89            "pref_suppress_language_switch_key";
90
91    public static final String PREF_SEND_FEEDBACK = "send_feedback";
92    public static final String PREF_ABOUT_KEYBOARD = "about_keyboard";
93
94    private Resources mRes;
95    private SharedPreferences mPrefs;
96    private SettingsValues mSettingsValues;
97
98    private static final Settings sInstance = new Settings();
99
100    public static Settings getInstance() {
101        return sInstance;
102    }
103
104    public static void init(final Context context) {
105        sInstance.onCreate(context);
106    }
107
108    private Settings() {
109        // Intentional empty constructor for singleton.
110    }
111
112    private void onCreate(final Context context) {
113        mRes = context.getResources();
114        mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
115        mPrefs.registerOnSharedPreferenceChangeListener(this);
116    }
117
118    public void onDestroy() {
119        mPrefs.unregisterOnSharedPreferenceChangeListener(this);
120    }
121
122    @Override
123    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
124        if (mSettingsValues == null) {
125            // TODO: Introduce a static function to register this class and ensure that
126            // loadSettings must be called before "onSharedPreferenceChanged" is called.
127            Log.w(TAG, "onSharedPreferenceChanged called before loadSettings.");
128            return;
129        }
130        loadSettings(mSettingsValues.mLocale, mSettingsValues.mInputAttributes);
131    }
132
133    public void loadSettings(final Locale locale, final InputAttributes inputAttributes) {
134        final SharedPreferences prefs = mPrefs;
135        final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() {
136            @Override
137            protected SettingsValues job(final Resources res) {
138                return new SettingsValues(prefs, locale, res, inputAttributes);
139            }
140        };
141        mSettingsValues = job.runInLocale(mRes, locale);
142    }
143
144    // TODO: Remove this method and add proxy method to SettingsValues.
145    public SettingsValues getCurrent() {
146        return mSettingsValues;
147    }
148
149    public boolean isInternal() {
150        return mSettingsValues.mIsInternal;
151    }
152
153    public String getWordSeparators() {
154        return mSettingsValues.mWordSeparators;
155    }
156
157    public boolean isWordSeparator(final int code) {
158        return mSettingsValues.isWordSeparator(code);
159    }
160
161    public boolean getBlockPotentiallyOffensive() {
162        return mSettingsValues.mBlockPotentiallyOffensive;
163    }
164
165    // Accessed from the settings interface, hence public
166    public static boolean readKeypressSoundEnabled(final SharedPreferences prefs,
167            final Resources res) {
168        return prefs.getBoolean(Settings.PREF_SOUND_ON,
169                res.getBoolean(R.bool.config_default_sound_enabled));
170    }
171
172    public static boolean readVibrationEnabled(final SharedPreferences prefs,
173            final Resources res) {
174        final boolean hasVibrator = AudioAndHapticFeedbackManager.getInstance().hasVibrator();
175        return hasVibrator && prefs.getBoolean(PREF_VIBRATE_ON,
176                res.getBoolean(R.bool.config_default_vibration_enabled));
177    }
178
179    public static boolean readAutoCorrectEnabled(final String currentAutoCorrectionSetting,
180            final Resources res) {
181        final String autoCorrectionOff = res.getString(
182                R.string.auto_correction_threshold_mode_index_off);
183        return !currentAutoCorrectionSetting.equals(autoCorrectionOff);
184    }
185
186    public static boolean readBlockPotentiallyOffensive(final SharedPreferences prefs,
187            final Resources res) {
188        return prefs.getBoolean(Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE,
189                res.getBoolean(R.bool.config_block_potentially_offensive));
190    }
191
192    public static boolean readFromBuildConfigIfGestureInputEnabled(final Resources res) {
193        return res.getBoolean(R.bool.config_gesture_input_enabled_by_build_config);
194    }
195
196    public static boolean readGestureInputEnabled(final SharedPreferences prefs,
197            final Resources res) {
198        return readFromBuildConfigIfGestureInputEnabled(res)
199                && prefs.getBoolean(Settings.PREF_GESTURE_INPUT, true);
200    }
201
202    public static boolean readFromBuildConfigIfToShowKeyPreviewPopupSettingsOption(
203            final Resources res) {
204        return res.getBoolean(R.bool.config_enable_show_option_of_key_preview_popup);
205    }
206
207    public static boolean readKeyPreviewPopupEnabled(final SharedPreferences prefs,
208            final Resources res) {
209        final boolean defaultKeyPreviewPopup = res.getBoolean(
210                R.bool.config_default_key_preview_popup);
211        if (!readFromBuildConfigIfToShowKeyPreviewPopupSettingsOption(res)) {
212            return defaultKeyPreviewPopup;
213        }
214        return prefs.getBoolean(PREF_POPUP_ON, defaultKeyPreviewPopup);
215    }
216
217    public static int readKeyPreviewPopupDismissDelay(final SharedPreferences prefs,
218            final Resources res) {
219        return Integer.parseInt(prefs.getString(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
220                Integer.toString(res.getInteger(
221                        R.integer.config_key_preview_linger_timeout))));
222    }
223
224    public static boolean readShowsLanguageSwitchKey(final SharedPreferences prefs) {
225        if (prefs.contains(PREF_SUPPRESS_LANGUAGE_SWITCH_KEY)) {
226            final boolean suppressLanguageSwitchKey = prefs.getBoolean(
227                    PREF_SUPPRESS_LANGUAGE_SWITCH_KEY, false);
228            final SharedPreferences.Editor editor = prefs.edit();
229            editor.remove(PREF_SUPPRESS_LANGUAGE_SWITCH_KEY);
230            editor.putBoolean(PREF_SHOW_LANGUAGE_SWITCH_KEY, !suppressLanguageSwitchKey);
231            editor.apply();
232        }
233        return prefs.getBoolean(PREF_SHOW_LANGUAGE_SWITCH_KEY, true);
234    }
235
236    public static String readPrefAdditionalSubtypes(final SharedPreferences prefs,
237            final Resources res) {
238        final String predefinedPrefSubtypes = AdditionalSubtypeUtils.createPrefSubtypes(
239                res.getStringArray(R.array.predefined_subtypes));
240        return prefs.getString(PREF_CUSTOM_INPUT_STYLES, predefinedPrefSubtypes);
241    }
242
243    public static void writePrefAdditionalSubtypes(final SharedPreferences prefs,
244            final String prefSubtypes) {
245        prefs.edit().putString(Settings.PREF_CUSTOM_INPUT_STYLES, prefSubtypes).apply();
246    }
247
248    public static float readKeypressSoundVolume(final SharedPreferences prefs,
249            final Resources res) {
250        final float volume = prefs.getFloat(PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
251        return (volume >= 0) ? volume : readDefaultKeypressSoundVolume(res);
252    }
253
254    public static float readDefaultKeypressSoundVolume(final Resources res) {
255        return Float.parseFloat(
256                ResourceUtils.getDeviceOverrideValue(res, R.array.keypress_volumes));
257    }
258
259    public static int readKeyLongpressTimeout(final SharedPreferences prefs,
260            final Resources res) {
261        final int ms = prefs.getInt(PREF_KEY_LONGPRESS_TIMEOUT, -1);
262        return (ms >= 0) ? ms : readDefaultKeyLongpressTimeout(res);
263    }
264
265    public static int readDefaultKeyLongpressTimeout(final Resources res) {
266        return res.getInteger(R.integer.config_default_longpress_key_timeout);
267    }
268
269    public static int readKeypressVibrationDuration(final SharedPreferences prefs,
270            final Resources res) {
271        final int ms = prefs.getInt(PREF_VIBRATION_DURATION_SETTINGS, -1);
272        return (ms >= 0) ? ms : readDefaultKeypressVibrationDuration(res);
273    }
274
275    public static int readDefaultKeypressVibrationDuration(final Resources res) {
276        return Integer.parseInt(
277                ResourceUtils.getDeviceOverrideValue(res, R.array.keypress_vibration_durations));
278    }
279
280    public static boolean readUsabilityStudyMode(final SharedPreferences prefs) {
281        return prefs.getBoolean(DebugSettings.PREF_USABILITY_STUDY_MODE, true);
282    }
283
284    public static long readLastUserHistoryWriteTime(final SharedPreferences prefs,
285            final String locale) {
286        final String str = prefs.getString(PREF_LAST_USER_DICTIONARY_WRITE_TIME, "");
287        final HashMap<String, Long> map = LocaleUtils.localeAndTimeStrToHashMap(str);
288        if (map.containsKey(locale)) {
289            return map.get(locale);
290        }
291        return 0;
292    }
293
294    public static void writeLastUserHistoryWriteTime(final SharedPreferences prefs,
295            final String locale) {
296        final String oldStr = prefs.getString(PREF_LAST_USER_DICTIONARY_WRITE_TIME, "");
297        final HashMap<String, Long> map = LocaleUtils.localeAndTimeStrToHashMap(oldStr);
298        map.put(locale, System.currentTimeMillis());
299        final String newStr = LocaleUtils.localeAndTimeHashMapToStr(map);
300        prefs.edit().putString(PREF_LAST_USER_DICTIONARY_WRITE_TIME, newStr).apply();
301    }
302
303    public static boolean readUseFullscreenMode(final Resources res) {
304        return res.getBoolean(R.bool.config_use_fullscreen_mode);
305    }
306
307    public static boolean readShowSetupWizardIcon(final SharedPreferences prefs,
308            final Context context) {
309        final boolean enableSetupWizardByConfig = context.getResources().getBoolean(
310                R.bool.config_setup_wizard_available);
311        if (!enableSetupWizardByConfig) {
312            return false;
313        }
314        if (!prefs.contains(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) {
315            final ApplicationInfo appInfo = context.getApplicationInfo();
316            final boolean isApplicationInSystemImage =
317                    (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
318            // Default value
319            return !isApplicationInSystemImage;
320        }
321        return prefs.getBoolean(Settings.PREF_SHOW_SETUP_WIZARD_ICON, false);
322    }
323
324    public static boolean isInternal(final SharedPreferences prefs) {
325        return prefs.getBoolean(Settings.PREF_KEY_IS_INTERNAL, false);
326    }
327
328    public static boolean readUseOnlyPersonalizationDictionaryForDebug(
329            final SharedPreferences prefs) {
330        return prefs.getBoolean(
331                DebugSettings.PREF_USE_ONLY_PERSONALIZATION_DICTIONARY_FOR_DEBUG, false);
332    }
333}
334