SettingsValues.java revision c225d2e29cfd85fb416952daa4bcebd4df48b57c
1/* 2 * Copyright (C) 2011 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.PackageInfo; 22import android.content.res.Configuration; 23import android.content.res.Resources; 24import android.util.Log; 25import android.view.inputmethod.EditorInfo; 26 27import com.android.inputmethod.compat.AppWorkaroundsUtils; 28import com.android.inputmethod.latin.InputAttributes; 29import com.android.inputmethod.latin.R; 30import com.android.inputmethod.latin.RichInputMethodManager; 31import com.android.inputmethod.latin.SubtypeSwitcher; 32import com.android.inputmethod.latin.utils.AsyncResultHolder; 33import com.android.inputmethod.latin.utils.ResourceUtils; 34import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask; 35 36import java.util.Arrays; 37import java.util.Locale; 38 39/** 40 * When you call the constructor of this class, you may want to change the current system locale by 41 * using {@link com.android.inputmethod.latin.utils.RunInLocale}. 42 */ 43public final class SettingsValues { 44 private static final String TAG = SettingsValues.class.getSimpleName(); 45 // "floatMaxValue" and "floatNegativeInfinity" are special marker strings for 46 // Float.NEGATIVE_INFINITE and Float.MAX_VALUE. Currently used for auto-correction settings. 47 private static final String FLOAT_MAX_VALUE_MARKER_STRING = "floatMaxValue"; 48 private static final String FLOAT_NEGATIVE_INFINITY_MARKER_STRING = "floatNegativeInfinity"; 49 private static final int TIMEOUT_TO_GET_TARGET_PACKAGE = 5; // seconds 50 51 // From resources: 52 public final SpacingAndPunctuations mSpacingAndPunctuations; 53 public final int mDelayUpdateOldSuggestions; 54 public final long mDoubleSpacePeriodTimeout; 55 56 // From preferences, in the same order as xml/prefs.xml: 57 public final boolean mAutoCap; 58 public final boolean mVibrateOn; 59 public final boolean mSoundOn; 60 public final boolean mKeyPreviewPopupOn; 61 public final boolean mShowsVoiceInputKey; 62 public final boolean mIncludesOtherImesInLanguageSwitchList; 63 public final boolean mShowsLanguageSwitchKey; 64 public final boolean mUseContactsDict; 65 public final boolean mUsePersonalizedDicts; 66 public final boolean mUseDoubleSpacePeriod; 67 public final boolean mBlockPotentiallyOffensive; 68 // Use bigrams to predict the next word when there is no input for it yet 69 public final boolean mBigramPredictionEnabled; 70 public final boolean mGestureInputEnabled; 71 public final boolean mGestureTrailEnabled; 72 public final boolean mGestureFloatingPreviewTextEnabled; 73 public final boolean mSlidingKeyInputPreviewEnabled; 74 public final boolean mPhraseGestureEnabled; 75 public final int mKeyLongpressTimeout; 76 public final Locale mLocale; 77 public final boolean mEnableMetricsLogging; 78 public final boolean mShouldShowUiToAcceptTypedWord; 79 80 // From the input box 81 public final InputAttributes mInputAttributes; 82 83 // Deduced settings 84 public final int mKeypressVibrationDuration; 85 public final float mKeypressSoundVolume; 86 public final int mKeyPreviewPopupDismissDelay; 87 private final boolean mAutoCorrectEnabled; 88 public final float mAutoCorrectionThreshold; 89 public final boolean mAutoCorrectionEnabledPerUserSettings; 90 private final boolean mSuggestionsEnabledPerUserSettings; 91 public final int mDisplayOrientation; 92 private final AsyncResultHolder<AppWorkaroundsUtils> mAppWorkarounds; 93 94 // Setting values for additional features 95 public final int[] mAdditionalFeaturesSettingValues = 96 new int[AdditionalFeaturesSettingUtils.ADDITIONAL_FEATURES_SETTINGS_SIZE]; 97 98 // Debug settings 99 public final boolean mIsInternal; 100 public final int mKeyPreviewShowUpDuration; 101 public final int mKeyPreviewDismissDuration; 102 public final float mKeyPreviewShowUpStartScale; 103 public final float mKeyPreviewDismissEndScale; 104 105 public SettingsValues(final Context context, final SharedPreferences prefs, final Resources res, 106 final InputAttributes inputAttributes) { 107 mLocale = res.getConfiguration().locale; 108 // Get the resources 109 mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions); 110 mSpacingAndPunctuations = new SpacingAndPunctuations(res); 111 112 // Store the input attributes 113 if (null == inputAttributes) { 114 mInputAttributes = new InputAttributes( 115 null, false /* isFullscreenMode */, context.getPackageName()); 116 } else { 117 mInputAttributes = inputAttributes; 118 } 119 120 // Get the settings preferences 121 mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true); 122 mVibrateOn = Settings.readVibrationEnabled(prefs, res); 123 mSoundOn = Settings.readKeypressSoundEnabled(prefs, res); 124 mKeyPreviewPopupOn = Settings.readKeyPreviewPopupEnabled(prefs, res); 125 mSlidingKeyInputPreviewEnabled = prefs.getBoolean( 126 DebugSettings.PREF_SLIDING_KEY_INPUT_PREVIEW, true); 127 mShowsVoiceInputKey = needsToShowVoiceInputKey(prefs, res) 128 && mInputAttributes.mShouldShowVoiceInputKey 129 && SubtypeSwitcher.getInstance().isShortcutImeEnabled(); 130 final String autoCorrectionThresholdRawValue = prefs.getString( 131 Settings.PREF_AUTO_CORRECTION_THRESHOLD, 132 res.getString(R.string.auto_correction_threshold_mode_index_modest)); 133 mIncludesOtherImesInLanguageSwitchList = Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS 134 ? prefs.getBoolean(Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, false) 135 : true /* forcibly */; 136 mShowsLanguageSwitchKey = Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS 137 ? Settings.readShowsLanguageSwitchKey(prefs) : true /* forcibly */; 138 mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true); 139 mUsePersonalizedDicts = prefs.getBoolean(Settings.PREF_KEY_USE_PERSONALIZED_DICTS, true); 140 mUseDoubleSpacePeriod = prefs.getBoolean(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true); 141 mBlockPotentiallyOffensive = Settings.readBlockPotentiallyOffensive(prefs, res); 142 mAutoCorrectEnabled = Settings.readAutoCorrectEnabled(autoCorrectionThresholdRawValue, res); 143 mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res); 144 mDoubleSpacePeriodTimeout = res.getInteger(R.integer.config_double_space_period_timeout); 145 mEnableMetricsLogging = prefs.getBoolean(Settings.PREF_ENABLE_METRICS_LOGGING, true); 146 mShouldShowUiToAcceptTypedWord = Settings.HAS_UI_TO_ACCEPT_TYPED_WORD 147 && prefs.getBoolean(DebugSettings.PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD, true); 148 // Compute other readable settings 149 mKeyLongpressTimeout = Settings.readKeyLongpressTimeout(prefs, res); 150 mKeypressVibrationDuration = Settings.readKeypressVibrationDuration(prefs, res); 151 mKeypressSoundVolume = Settings.readKeypressSoundVolume(prefs, res); 152 mKeyPreviewPopupDismissDelay = Settings.readKeyPreviewPopupDismissDelay(prefs, res); 153 mAutoCorrectionThreshold = readAutoCorrectionThreshold(res, 154 autoCorrectionThresholdRawValue); 155 mGestureInputEnabled = Settings.readGestureInputEnabled(prefs, res); 156 mGestureTrailEnabled = prefs.getBoolean(Settings.PREF_GESTURE_PREVIEW_TRAIL, true); 157 mGestureFloatingPreviewTextEnabled = prefs.getBoolean( 158 Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, true); 159 mPhraseGestureEnabled = Settings.readPhraseGestureEnabled(prefs, res); 160 mAutoCorrectionEnabledPerUserSettings = mAutoCorrectEnabled 161 && !mInputAttributes.mInputTypeNoAutoCorrect; 162 mSuggestionsEnabledPerUserSettings = readSuggestionsEnabled(prefs); 163 AdditionalFeaturesSettingUtils.readAdditionalFeaturesPreferencesIntoArray( 164 prefs, mAdditionalFeaturesSettingValues); 165 mIsInternal = Settings.isInternal(prefs); 166 mKeyPreviewShowUpDuration = Settings.readKeyPreviewAnimationDuration( 167 prefs, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION, 168 res.getInteger(R.integer.config_key_preview_show_up_duration)); 169 mKeyPreviewDismissDuration = Settings.readKeyPreviewAnimationDuration( 170 prefs, DebugSettings.PREF_KEY_PREVIEW_DISMISS_DURATION, 171 res.getInteger(R.integer.config_key_preview_dismiss_duration)); 172 mKeyPreviewShowUpStartScale = Settings.readKeyPreviewAnimationScale( 173 prefs, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_SCALE, 174 ResourceUtils.getFloatFromFraction( 175 res, R.fraction.config_key_preview_show_up_start_scale)); 176 mKeyPreviewDismissEndScale = Settings.readKeyPreviewAnimationScale( 177 prefs, DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_SCALE, 178 ResourceUtils.getFloatFromFraction( 179 res, R.fraction.config_key_preview_dismiss_end_scale)); 180 mDisplayOrientation = res.getConfiguration().orientation; 181 mAppWorkarounds = new AsyncResultHolder<>(); 182 final PackageInfo packageInfo = TargetPackageInfoGetterTask.getCachedPackageInfo( 183 mInputAttributes.mTargetApplicationPackageName); 184 if (null != packageInfo) { 185 mAppWorkarounds.set(new AppWorkaroundsUtils(packageInfo)); 186 } else { 187 new TargetPackageInfoGetterTask(context, mAppWorkarounds) 188 .execute(mInputAttributes.mTargetApplicationPackageName); 189 } 190 } 191 192 public boolean isApplicationSpecifiedCompletionsOn() { 193 return mInputAttributes.mApplicationSpecifiedCompletionOn; 194 } 195 196 public boolean needsToLookupSuggestions() { 197 return mInputAttributes.mShouldShowSuggestions 198 && (mAutoCorrectionEnabledPerUserSettings || isSuggestionsEnabledPerUserSettings()); 199 } 200 201 public boolean isSuggestionsEnabledPerUserSettings() { 202 return mSuggestionsEnabledPerUserSettings; 203 } 204 205 public boolean isWordSeparator(final int code) { 206 return mSpacingAndPunctuations.isWordSeparator(code); 207 } 208 209 public boolean isWordConnector(final int code) { 210 return mSpacingAndPunctuations.isWordConnector(code); 211 } 212 213 public boolean isWordCodePoint(final int code) { 214 return Character.isLetter(code) || isWordConnector(code) 215 || Character.COMBINING_SPACING_MARK == Character.getType(code); 216 } 217 218 public boolean isUsuallyPrecededBySpace(final int code) { 219 return mSpacingAndPunctuations.isUsuallyPrecededBySpace(code); 220 } 221 222 public boolean isUsuallyFollowedBySpace(final int code) { 223 return mSpacingAndPunctuations.isUsuallyFollowedBySpace(code); 224 } 225 226 public boolean shouldInsertSpacesAutomatically() { 227 return mInputAttributes.mShouldInsertSpacesAutomatically; 228 } 229 230 public boolean isLanguageSwitchKeyEnabled() { 231 if (!mShowsLanguageSwitchKey) { 232 return false; 233 } 234 final RichInputMethodManager imm = RichInputMethodManager.getInstance(); 235 if (mIncludesOtherImesInLanguageSwitchList) { 236 return imm.hasMultipleEnabledIMEsOrSubtypes(false /* include aux subtypes */); 237 } else { 238 return imm.hasMultipleEnabledSubtypesInThisIme(false /* include aux subtypes */); 239 } 240 } 241 242 public boolean isSameInputType(final EditorInfo editorInfo) { 243 return mInputAttributes.isSameInputType(editorInfo); 244 } 245 246 public boolean hasSameOrientation(final Configuration configuration) { 247 return mDisplayOrientation == configuration.orientation; 248 } 249 250 public boolean isBeforeJellyBean() { 251 final AppWorkaroundsUtils appWorkaroundUtils 252 = mAppWorkarounds.get(null, TIMEOUT_TO_GET_TARGET_PACKAGE); 253 return null == appWorkaroundUtils ? false : appWorkaroundUtils.isBeforeJellyBean(); 254 } 255 256 public boolean isBrokenByRecorrection() { 257 final AppWorkaroundsUtils appWorkaroundUtils 258 = mAppWorkarounds.get(null, TIMEOUT_TO_GET_TARGET_PACKAGE); 259 return null == appWorkaroundUtils ? false : appWorkaroundUtils.isBrokenByRecorrection(); 260 } 261 262 private static final String SUGGESTIONS_VISIBILITY_HIDE_VALUE_OBSOLETE = "2"; 263 264 private static boolean readSuggestionsEnabled(final SharedPreferences prefs) { 265 if (prefs.contains(Settings.PREF_SHOW_SUGGESTIONS_SETTING_OBSOLETE)) { 266 final boolean alwaysHide = SUGGESTIONS_VISIBILITY_HIDE_VALUE_OBSOLETE.equals( 267 prefs.getString(Settings.PREF_SHOW_SUGGESTIONS_SETTING_OBSOLETE, null)); 268 prefs.edit() 269 .remove(Settings.PREF_SHOW_SUGGESTIONS_SETTING_OBSOLETE) 270 .putBoolean(Settings.PREF_SHOW_SUGGESTIONS, !alwaysHide) 271 .apply(); 272 } 273 return prefs.getBoolean(Settings.PREF_SHOW_SUGGESTIONS, true); 274 } 275 276 private static boolean readBigramPredictionEnabled(final SharedPreferences prefs, 277 final Resources res) { 278 return prefs.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, res.getBoolean( 279 R.bool.config_default_next_word_prediction)); 280 } 281 282 private static float readAutoCorrectionThreshold(final Resources res, 283 final String currentAutoCorrectionSetting) { 284 final String[] autoCorrectionThresholdValues = res.getStringArray( 285 R.array.auto_correction_threshold_values); 286 // When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off. 287 final float autoCorrectionThreshold; 288 try { 289 final int arrayIndex = Integer.parseInt(currentAutoCorrectionSetting); 290 if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) { 291 final String val = autoCorrectionThresholdValues[arrayIndex]; 292 if (FLOAT_MAX_VALUE_MARKER_STRING.equals(val)) { 293 autoCorrectionThreshold = Float.MAX_VALUE; 294 } else if (FLOAT_NEGATIVE_INFINITY_MARKER_STRING.equals(val)) { 295 autoCorrectionThreshold = Float.NEGATIVE_INFINITY; 296 } else { 297 autoCorrectionThreshold = Float.parseFloat(val); 298 } 299 } else { 300 autoCorrectionThreshold = Float.MAX_VALUE; 301 } 302 } catch (final NumberFormatException e) { 303 // Whenever the threshold settings are correct, never come here. 304 Log.w(TAG, "Cannot load auto correction threshold setting." 305 + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting 306 + ", autoCorrectionThresholdValues: " 307 + Arrays.toString(autoCorrectionThresholdValues), e); 308 return Float.MAX_VALUE; 309 } 310 return autoCorrectionThreshold; 311 } 312 313 private static boolean needsToShowVoiceInputKey(final SharedPreferences prefs, 314 final Resources res) { 315 // Migrate preference from {@link Settings#PREF_VOICE_MODE_OBSOLETE} to 316 // {@link Settings#PREF_VOICE_INPUT_KEY}. 317 if (prefs.contains(Settings.PREF_VOICE_MODE_OBSOLETE)) { 318 final String voiceModeMain = res.getString(R.string.voice_mode_main); 319 final String voiceMode = prefs.getString( 320 Settings.PREF_VOICE_MODE_OBSOLETE, voiceModeMain); 321 final boolean shouldShowVoiceInputKey = voiceModeMain.equals(voiceMode); 322 prefs.edit() 323 .putBoolean(Settings.PREF_VOICE_INPUT_KEY, shouldShowVoiceInputKey) 324 // Remove the obsolete preference if exists. 325 .remove(Settings.PREF_VOICE_MODE_OBSOLETE) 326 .apply(); 327 } 328 return prefs.getBoolean(Settings.PREF_VOICE_INPUT_KEY, true); 329 } 330 331 public String dump() { 332 final StringBuilder sb = new StringBuilder("Current settings :"); 333 sb.append("\n mSpacingAndPunctuations = "); 334 sb.append("" + mSpacingAndPunctuations.dump()); 335 sb.append("\n mDelayUpdateOldSuggestions = "); 336 sb.append("" + mDelayUpdateOldSuggestions); 337 sb.append("\n mAutoCap = "); 338 sb.append("" + mAutoCap); 339 sb.append("\n mVibrateOn = "); 340 sb.append("" + mVibrateOn); 341 sb.append("\n mSoundOn = "); 342 sb.append("" + mSoundOn); 343 sb.append("\n mKeyPreviewPopupOn = "); 344 sb.append("" + mKeyPreviewPopupOn); 345 sb.append("\n mShowsVoiceInputKey = "); 346 sb.append("" + mShowsVoiceInputKey); 347 sb.append("\n mIncludesOtherImesInLanguageSwitchList = "); 348 sb.append("" + mIncludesOtherImesInLanguageSwitchList); 349 sb.append("\n mShowsLanguageSwitchKey = "); 350 sb.append("" + mShowsLanguageSwitchKey); 351 sb.append("\n mUseContactsDict = "); 352 sb.append("" + mUseContactsDict); 353 sb.append("\n mUsePersonalizedDicts = "); 354 sb.append("" + mUsePersonalizedDicts); 355 sb.append("\n mUseDoubleSpacePeriod = "); 356 sb.append("" + mUseDoubleSpacePeriod); 357 sb.append("\n mBlockPotentiallyOffensive = "); 358 sb.append("" + mBlockPotentiallyOffensive); 359 sb.append("\n mBigramPredictionEnabled = "); 360 sb.append("" + mBigramPredictionEnabled); 361 sb.append("\n mGestureInputEnabled = "); 362 sb.append("" + mGestureInputEnabled); 363 sb.append("\n mGestureTrailEnabled = "); 364 sb.append("" + mGestureTrailEnabled); 365 sb.append("\n mGestureFloatingPreviewTextEnabled = "); 366 sb.append("" + mGestureFloatingPreviewTextEnabled); 367 sb.append("\n mSlidingKeyInputPreviewEnabled = "); 368 sb.append("" + mSlidingKeyInputPreviewEnabled); 369 sb.append("\n mPhraseGestureEnabled = "); 370 sb.append("" + mPhraseGestureEnabled); 371 sb.append("\n mKeyLongpressTimeout = "); 372 sb.append("" + mKeyLongpressTimeout); 373 sb.append("\n mLocale = "); 374 sb.append("" + mLocale); 375 sb.append("\n mInputAttributes = "); 376 sb.append("" + mInputAttributes); 377 sb.append("\n mKeypressVibrationDuration = "); 378 sb.append("" + mKeypressVibrationDuration); 379 sb.append("\n mKeypressSoundVolume = "); 380 sb.append("" + mKeypressSoundVolume); 381 sb.append("\n mKeyPreviewPopupDismissDelay = "); 382 sb.append("" + mKeyPreviewPopupDismissDelay); 383 sb.append("\n mAutoCorrectEnabled = "); 384 sb.append("" + mAutoCorrectEnabled); 385 sb.append("\n mAutoCorrectionThreshold = "); 386 sb.append("" + mAutoCorrectionThreshold); 387 sb.append("\n mAutoCorrectionEnabledPerUserSettings = "); 388 sb.append("" + mAutoCorrectionEnabledPerUserSettings); 389 sb.append("\n mSuggestionsEnabledPerUserSettings = "); 390 sb.append("" + mSuggestionsEnabledPerUserSettings); 391 sb.append("\n mDisplayOrientation = "); 392 sb.append("" + mDisplayOrientation); 393 sb.append("\n mAppWorkarounds = "); 394 final AppWorkaroundsUtils awu = mAppWorkarounds.get(null, 0); 395 sb.append("" + (null == awu ? "null" : awu.toString())); 396 sb.append("\n mAdditionalFeaturesSettingValues = "); 397 sb.append("" + Arrays.toString(mAdditionalFeaturesSettingValues)); 398 sb.append("\n mIsInternal = "); 399 sb.append("" + mIsInternal); 400 sb.append("\n mKeyPreviewShowUpDuration = "); 401 sb.append("" + mKeyPreviewShowUpDuration); 402 sb.append("\n mKeyPreviewDismissDuration = "); 403 sb.append("" + mKeyPreviewDismissDuration); 404 sb.append("\n mKeyPreviewShowUpStartScale = "); 405 sb.append("" + mKeyPreviewShowUpStartScale); 406 sb.append("\n mKeyPreviewDismissEndScale = "); 407 sb.append("" + mKeyPreviewDismissEndScale); 408 return sb.toString(); 409 } 410} 411