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