Settings.java revision 0b593ce858d4b406e949f0e809cb77f41da691f9
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.ResourceUtils; 31import com.android.inputmethod.latin.utils.RunInLocale; 32import com.android.inputmethod.latin.utils.StringUtils; 33 34import java.util.Locale; 35import java.util.concurrent.locks.ReentrantLock; 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 // PREF_VOICE_MODE_OBSOLETE is obsolete. Use PREF_VOICE_INPUT_KEY instead. 46 public static final String PREF_VOICE_MODE_OBSOLETE = "voice_mode"; 47 public static final String PREF_VOICE_INPUT_KEY = "pref_voice_input_key"; 48 public static final String PREF_CORRECTION_SETTINGS = "correction_settings"; 49 public static final String PREF_EDIT_PERSONAL_DICTIONARY = "edit_personal_dictionary"; 50 public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key"; 51 public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold"; 52 public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting"; 53 public static final String PREF_MISC_SETTINGS = "misc_settings"; 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_PERSONALIZED_DICTS = "pref_key_use_personalized_dicts"; 57 public static final String PREF_KEY_USE_DOUBLE_SPACE_PERIOD = 58 "pref_key_use_double_space_period"; 59 public static final String PREF_BLOCK_POTENTIALLY_OFFENSIVE = 60 "pref_key_block_potentially_offensive"; 61 public static final String PREF_SHOW_LANGUAGE_SWITCH_KEY = 62 "pref_show_language_switch_key"; 63 public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST = 64 "pref_include_other_imes_in_language_switch_list"; 65 public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916"; 66 public static final String PREF_CUSTOM_INPUT_STYLES = "custom_input_styles"; 67 public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY = 68 "pref_key_preview_popup_dismiss_delay"; 69 public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction"; 70 public static final String PREF_GESTURE_SETTINGS = "gesture_typing_settings"; 71 public static final String PREF_GESTURE_INPUT = "gesture_input"; 72 public static final String PREF_SLIDING_KEY_INPUT_PREVIEW = "pref_sliding_key_input_preview"; 73 public static final String PREF_KEY_LONGPRESS_TIMEOUT = "pref_key_longpress_timeout"; 74 public static final String PREF_VIBRATION_DURATION_SETTINGS = 75 "pref_vibration_duration_settings"; 76 public static final String PREF_KEYPRESS_SOUND_VOLUME = 77 "pref_keypress_sound_volume"; 78 public static final String PREF_GESTURE_PREVIEW_TRAIL = "pref_gesture_preview_trail"; 79 public static final String PREF_GESTURE_FLOATING_PREVIEW_TEXT = 80 "pref_gesture_floating_preview_text"; 81 public static final String PREF_SHOW_SETUP_WIZARD_ICON = "pref_show_setup_wizard_icon"; 82 public static final String PREF_PHRASE_GESTURE_ENABLED = "pref_gesture_space_aware"; 83 84 public static final String PREF_INPUT_LANGUAGE = "input_language"; 85 public static final String PREF_SELECTED_LANGUAGES = "selected_languages"; 86 public static final String PREF_DEBUG_SETTINGS = "debug_settings"; 87 public static final String PREF_KEY_IS_INTERNAL = "pref_key_is_internal"; 88 89 // This preference key is deprecated. Use {@link #PREF_SHOW_LANGUAGE_SWITCH_KEY} instead. 90 // This is being used only for the backward compatibility. 91 private static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY = 92 "pref_suppress_language_switch_key"; 93 94 private static final String PREF_LAST_USED_PERSONALIZATION_TOKEN = 95 "pref_last_used_personalization_token"; 96 public static final String PREF_SEND_FEEDBACK = "send_feedback"; 97 public static final String PREF_ABOUT_KEYBOARD = "about_keyboard"; 98 99 // Emoji 100 public static final String PREF_EMOJI_RECENT_KEYS = "emoji_recent_keys"; 101 public static final String PREF_EMOJI_CATEGORY_LAST_TYPED_ID = "emoji_category_last_typed_id"; 102 public static final String PREF_LAST_SHOWN_EMOJI_CATEGORY_ID = "last_shown_emoji_category_id"; 103 104 private Context mContext; 105 private Resources mRes; 106 private SharedPreferences mPrefs; 107 private SettingsValues mSettingsValues; 108 private final ReentrantLock mSettingsValuesLock = new ReentrantLock(); 109 110 private static final Settings sInstance = new Settings(); 111 112 public static Settings getInstance() { 113 return sInstance; 114 } 115 116 public static void init(final Context context) { 117 sInstance.onCreate(context); 118 } 119 120 private Settings() { 121 // Intentional empty constructor for singleton. 122 } 123 124 private void onCreate(final Context context) { 125 mContext = context; 126 mRes = context.getResources(); 127 mPrefs = PreferenceManager.getDefaultSharedPreferences(context); 128 mPrefs.registerOnSharedPreferenceChangeListener(this); 129 } 130 131 public void onDestroy() { 132 mPrefs.unregisterOnSharedPreferenceChangeListener(this); 133 } 134 135 @Override 136 public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { 137 mSettingsValuesLock.lock(); 138 try { 139 if (mSettingsValues == null) { 140 // TODO: Introduce a static function to register this class and ensure that 141 // loadSettings must be called before "onSharedPreferenceChanged" is called. 142 Log.w(TAG, "onSharedPreferenceChanged called before loadSettings."); 143 return; 144 } 145 loadSettings(mContext, mSettingsValues.mLocale, mSettingsValues.mInputAttributes); 146 } finally { 147 mSettingsValuesLock.unlock(); 148 } 149 } 150 151 public void loadSettings(final Context context, final Locale locale, 152 final InputAttributes inputAttributes) { 153 mSettingsValuesLock.lock(); 154 mContext = context; 155 try { 156 final SharedPreferences prefs = mPrefs; 157 final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() { 158 @Override 159 protected SettingsValues job(final Resources res) { 160 return new SettingsValues(context, prefs, locale, res, inputAttributes); 161 } 162 }; 163 mSettingsValues = job.runInLocale(mRes, locale); 164 } finally { 165 mSettingsValuesLock.unlock(); 166 } 167 } 168 169 // TODO: Remove this method and add proxy method to SettingsValues. 170 public SettingsValues getCurrent() { 171 return mSettingsValues; 172 } 173 174 public boolean isInternal() { 175 return mSettingsValues.mIsInternal; 176 } 177 178 public String getWordSeparators() { 179 return mSettingsValues.mSpacingAndPunctuations.mWordSeparators; 180 } 181 182 public boolean isWordSeparator(final int code) { 183 return mSettingsValues.isWordSeparator(code); 184 } 185 186 public boolean getBlockPotentiallyOffensive() { 187 return mSettingsValues.mBlockPotentiallyOffensive; 188 } 189 190 // Accessed from the settings interface, hence public 191 public static boolean readKeypressSoundEnabled(final SharedPreferences prefs, 192 final Resources res) { 193 return prefs.getBoolean(Settings.PREF_SOUND_ON, 194 res.getBoolean(R.bool.config_default_sound_enabled)); 195 } 196 197 public static boolean readVibrationEnabled(final SharedPreferences prefs, 198 final Resources res) { 199 final boolean hasVibrator = AudioAndHapticFeedbackManager.getInstance().hasVibrator(); 200 return hasVibrator && prefs.getBoolean(PREF_VIBRATE_ON, 201 res.getBoolean(R.bool.config_default_vibration_enabled)); 202 } 203 204 public static boolean readAutoCorrectEnabled(final String currentAutoCorrectionSetting, 205 final Resources res) { 206 final String autoCorrectionOff = res.getString( 207 R.string.auto_correction_threshold_mode_index_off); 208 return !currentAutoCorrectionSetting.equals(autoCorrectionOff); 209 } 210 211 public static boolean readBlockPotentiallyOffensive(final SharedPreferences prefs, 212 final Resources res) { 213 return prefs.getBoolean(Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE, 214 res.getBoolean(R.bool.config_block_potentially_offensive)); 215 } 216 217 public static boolean readFromBuildConfigIfGestureInputEnabled(final Resources res) { 218 return res.getBoolean(R.bool.config_gesture_input_enabled_by_build_config); 219 } 220 221 public static boolean readGestureInputEnabled(final SharedPreferences prefs, 222 final Resources res) { 223 return readFromBuildConfigIfGestureInputEnabled(res) 224 && prefs.getBoolean(Settings.PREF_GESTURE_INPUT, true); 225 } 226 227 public static boolean readPhraseGestureEnabled(final SharedPreferences prefs, 228 final Resources res) { 229 return prefs.getBoolean(Settings.PREF_PHRASE_GESTURE_ENABLED, 230 res.getBoolean(R.bool.config_default_phrase_gesture_enabled)); 231 } 232 233 public static boolean readFromBuildConfigIfToShowKeyPreviewPopupOption(final Resources res) { 234 return res.getBoolean(R.bool.config_enable_show_key_preview_popup_option); 235 } 236 237 public static boolean readKeyPreviewPopupEnabled(final SharedPreferences prefs, 238 final Resources res) { 239 final boolean defaultKeyPreviewPopup = res.getBoolean( 240 R.bool.config_default_key_preview_popup); 241 if (!readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) { 242 return defaultKeyPreviewPopup; 243 } 244 return prefs.getBoolean(PREF_POPUP_ON, defaultKeyPreviewPopup); 245 } 246 247 public static int readKeyPreviewPopupDismissDelay(final SharedPreferences prefs, 248 final Resources res) { 249 return Integer.parseInt(prefs.getString(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, 250 Integer.toString(res.getInteger( 251 R.integer.config_key_preview_linger_timeout)))); 252 } 253 254 public static boolean readShowsLanguageSwitchKey(final SharedPreferences prefs) { 255 if (prefs.contains(PREF_SUPPRESS_LANGUAGE_SWITCH_KEY)) { 256 final boolean suppressLanguageSwitchKey = prefs.getBoolean( 257 PREF_SUPPRESS_LANGUAGE_SWITCH_KEY, false); 258 final SharedPreferences.Editor editor = prefs.edit(); 259 editor.remove(PREF_SUPPRESS_LANGUAGE_SWITCH_KEY); 260 editor.putBoolean(PREF_SHOW_LANGUAGE_SWITCH_KEY, !suppressLanguageSwitchKey); 261 editor.apply(); 262 } 263 return prefs.getBoolean(PREF_SHOW_LANGUAGE_SWITCH_KEY, true); 264 } 265 266 public static int readKeyboardThemeIndex(final SharedPreferences prefs, final Resources res) { 267 final String defaultThemeIndex = res.getString( 268 R.string.config_default_keyboard_theme_index); 269 final String themeIndex = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultThemeIndex); 270 try { 271 return Integer.valueOf(themeIndex); 272 } catch (final NumberFormatException e) { 273 // Format error, returns default keyboard theme index. 274 Log.e(TAG, "Illegal keyboard theme in preference: " + themeIndex + ", default to " 275 + defaultThemeIndex, e); 276 return Integer.valueOf(defaultThemeIndex); 277 } 278 } 279 280 public static int resetAndGetDefaultKeyboardThemeIndex(final SharedPreferences prefs, 281 final Resources res) { 282 final String defaultThemeIndex = res.getString( 283 R.string.config_default_keyboard_theme_index); 284 prefs.edit().putString(PREF_KEYBOARD_LAYOUT, defaultThemeIndex).apply(); 285 return Integer.valueOf(defaultThemeIndex); 286 } 287 288 public static String readPrefAdditionalSubtypes(final SharedPreferences prefs, 289 final Resources res) { 290 final String predefinedPrefSubtypes = AdditionalSubtypeUtils.createPrefSubtypes( 291 res.getStringArray(R.array.predefined_subtypes)); 292 return prefs.getString(PREF_CUSTOM_INPUT_STYLES, predefinedPrefSubtypes); 293 } 294 295 public static void writePrefAdditionalSubtypes(final SharedPreferences prefs, 296 final String prefSubtypes) { 297 prefs.edit().putString(Settings.PREF_CUSTOM_INPUT_STYLES, prefSubtypes).apply(); 298 } 299 300 public static float readKeypressSoundVolume(final SharedPreferences prefs, 301 final Resources res) { 302 final float volume = prefs.getFloat(PREF_KEYPRESS_SOUND_VOLUME, -1.0f); 303 return (volume >= 0) ? volume : readDefaultKeypressSoundVolume(res); 304 } 305 306 public static float readDefaultKeypressSoundVolume(final Resources res) { 307 return Float.parseFloat( 308 ResourceUtils.getDeviceOverrideValue(res, R.array.keypress_volumes)); 309 } 310 311 public static int readKeyLongpressTimeout(final SharedPreferences prefs, 312 final Resources res) { 313 final int ms = prefs.getInt(PREF_KEY_LONGPRESS_TIMEOUT, -1); 314 return (ms >= 0) ? ms : readDefaultKeyLongpressTimeout(res); 315 } 316 317 public static int readDefaultKeyLongpressTimeout(final Resources res) { 318 return res.getInteger(R.integer.config_default_longpress_key_timeout); 319 } 320 321 public static int readKeypressVibrationDuration(final SharedPreferences prefs, 322 final Resources res) { 323 final int ms = prefs.getInt(PREF_VIBRATION_DURATION_SETTINGS, -1); 324 return (ms >= 0) ? ms : readDefaultKeypressVibrationDuration(res); 325 } 326 327 public static int readDefaultKeypressVibrationDuration(final Resources res) { 328 return Integer.parseInt( 329 ResourceUtils.getDeviceOverrideValue(res, R.array.keypress_vibration_durations)); 330 } 331 332 public static boolean readUsabilityStudyMode(final SharedPreferences prefs) { 333 return prefs.getBoolean(DebugSettings.PREF_USABILITY_STUDY_MODE, true); 334 } 335 336 public static boolean readUseFullscreenMode(final Resources res) { 337 return res.getBoolean(R.bool.config_use_fullscreen_mode); 338 } 339 340 public static boolean readShowSetupWizardIcon(final SharedPreferences prefs, 341 final Context context) { 342 final boolean enableSetupWizardByConfig = context.getResources().getBoolean( 343 R.bool.config_setup_wizard_available); 344 if (!enableSetupWizardByConfig) { 345 return false; 346 } 347 if (!prefs.contains(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) { 348 final ApplicationInfo appInfo = context.getApplicationInfo(); 349 final boolean isApplicationInSystemImage = 350 (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 351 // Default value 352 return !isApplicationInSystemImage; 353 } 354 return prefs.getBoolean(Settings.PREF_SHOW_SETUP_WIZARD_ICON, false); 355 } 356 357 public static boolean isInternal(final SharedPreferences prefs) { 358 return prefs.getBoolean(Settings.PREF_KEY_IS_INTERNAL, false); 359 } 360 361 public void writeLastUsedPersonalizationToken(byte[] token) { 362 if (token == null) { 363 mPrefs.edit().remove(PREF_LAST_USED_PERSONALIZATION_TOKEN).apply(); 364 } else { 365 final String tokenStr = StringUtils.byteArrayToHexString(token); 366 mPrefs.edit().putString(PREF_LAST_USED_PERSONALIZATION_TOKEN, tokenStr).apply(); 367 } 368 } 369 370 public byte[] readLastUsedPersonalizationToken() { 371 final String tokenStr = mPrefs.getString(PREF_LAST_USED_PERSONALIZATION_TOKEN, null); 372 return StringUtils.hexStringToByteArray(tokenStr); 373 } 374 375 public static void writeEmojiRecentKeys(final SharedPreferences prefs, String str) { 376 prefs.edit().putString(PREF_EMOJI_RECENT_KEYS, str).apply(); 377 } 378 379 public static String readEmojiRecentKeys(final SharedPreferences prefs) { 380 return prefs.getString(PREF_EMOJI_RECENT_KEYS, ""); 381 } 382 383 public static void writeLastTypedEmojiCategoryPageId( 384 final SharedPreferences prefs, final int categoryId, final int categoryPageId) { 385 final String key = PREF_EMOJI_CATEGORY_LAST_TYPED_ID + categoryId; 386 prefs.edit().putInt(key, categoryPageId).apply(); 387 } 388 389 public static int readLastTypedEmojiCategoryPageId( 390 final SharedPreferences prefs, final int categoryId) { 391 final String key = PREF_EMOJI_CATEGORY_LAST_TYPED_ID + categoryId; 392 return prefs.getInt(key, 0); 393 } 394 395 public static void writeLastShownEmojiCategoryId( 396 final SharedPreferences prefs, final int categoryId) { 397 prefs.edit().putInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_ID, categoryId).apply(); 398 } 399 400 public static int readLastShownEmojiCategoryId( 401 final SharedPreferences prefs, final int defValue) { 402 return prefs.getInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_ID, defValue); 403 } 404} 405