diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
23 files changed, 441 insertions, 326 deletions
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java index 509fc1ba3..820733bdc 100644 --- a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java +++ b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java @@ -45,7 +45,7 @@ public final class AdditionalSubtype { final String keyboardLayoutSetName, final String extraValue) { final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName; final String layoutDisplayNameExtraValue; - if (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && SubtypeLocale.isExceptionalLocale(localeString)) { final String layoutDisplayName = SubtypeLocale.getKeyboardLayoutSetDisplayName( keyboardLayoutSetName); diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java index 08f08d24e..6ac5a9b94 100644 --- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java +++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java @@ -387,7 +387,7 @@ public final class AdditionalSubtypeSettings extends PreferenceFragment { super.onCreate(savedInstanceState); mPrefs = getPreferenceManager().getSharedPreferences(); - RichInputMethodManager.init(getActivity(), mPrefs); + RichInputMethodManager.init(getActivity()); mRichImm = RichInputMethodManager.getInstance(); addPreferencesFromResource(R.xml.additional_subtype_settings); setHasOptionsMenu(true); diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java index 024726391..0e7f891ff 100644 --- a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java +++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java @@ -30,6 +30,8 @@ import com.android.inputmethod.latin.VibratorUtils; * complexity of settings and the like. */ public final class AudioAndHapticFeedbackManager { + public static final int MAX_KEYPRESS_VIBRATION_DURATION = 250; // millisecond + private final AudioManager mAudioManager; private final VibratorUtils mVibratorUtils; diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java index ba932e590..3a7772452 100644 --- a/java/src/com/android/inputmethod/latin/Constants.java +++ b/java/src/com/android/inputmethod/latin/Constants.java @@ -111,7 +111,7 @@ public final class Constants { } } - public static class TextUtils { + public static final class TextUtils { /** * Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize * characters. This value may be used with @@ -126,7 +126,7 @@ public final class Constants { } } - public static class Dictionary { + public static final class Dictionary { public static final int MAX_WORD_LENGTH = 48; private Dictionary() { @@ -139,6 +139,7 @@ public final class Constants { public static final int NOT_A_COORDINATE = -1; public static final int SUGGESTION_STRIP_COORDINATE = -2; public static final int SPELL_CHECKER_COORDINATE = -3; + public static final int EXTERNAL_KEYBOARD_COORDINATE = -4; public static boolean isValidCoordinate(final int coordinate) { // Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE}, @@ -204,6 +205,7 @@ public final class Constants { case CODE_UNSPECIFIED: return "unspec"; case CODE_TAB: return "tab"; case CODE_ENTER: return "enter"; + case CODE_RESEARCH: return "research"; default: if (code < CODE_SPACE) return String.format("'\\u%02x'", code); if (code < 0x100) return String.format("'%c'", code); diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java index 7f78ac8a2..9a771cf1e 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -38,7 +38,7 @@ public final class DictionaryCollection extends Dictionary { mDictionaries = CollectionUtils.newCopyOnWriteArrayList(); } - public DictionaryCollection(final String dictType, Dictionary... dictionaries) { + public DictionaryCollection(final String dictType, final Dictionary... dictionaries) { super(dictType); if (null == dictionaries) { mDictionaries = CollectionUtils.newCopyOnWriteArrayList(); @@ -48,7 +48,7 @@ public final class DictionaryCollection extends Dictionary { } } - public DictionaryCollection(final String dictType, Collection<Dictionary> dictionaries) { + public DictionaryCollection(final String dictType, final Collection<Dictionary> dictionaries) { super(dictType); mDictionaries = CollectionUtils.newCopyOnWriteArrayList(dictionaries); mDictionaries.removeAll(Collections.singleton(null)); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 8196a97f8..f65bbe4a1 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -35,6 +35,7 @@ import android.graphics.Rect; import android.inputmethodservice.InputMethodService; import android.media.AudioManager; import android.net.ConnectivityManager; +import android.os.Build.VERSION_CODES; import android.os.Debug; import android.os.Handler; import android.os.HandlerThread; @@ -145,7 +146,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private final SubtypeState mSubtypeState = new SubtypeState(); // At start, create a default event interpreter that does nothing by passing it no decoder spec. // The event interpreter should never be null. - private EventInterpreter mEventInterpreter = new EventInterpreter(); + private EventInterpreter mEventInterpreter = new EventInterpreter(this); private boolean mIsMainDictionaryAvailable; private UserBinaryDictionary mUserDictionary; @@ -412,14 +413,14 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mPrefs = PreferenceManager.getDefaultSharedPreferences(this); mResources = getResources(); - LatinImeLogger.init(this, mPrefs); + LatinImeLogger.init(this); if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.getInstance().init(this, mPrefs); + ResearchLogger.getInstance().init(this); } - RichInputMethodManager.init(this, mPrefs); + RichInputMethodManager.init(this); mRichImm = RichInputMethodManager.getInstance(); SubtypeSwitcher.init(this); - KeyboardSwitcher.init(this, mPrefs); + KeyboardSwitcher.init(this); AccessibilityUtils.init(this); super.onCreate(); @@ -582,10 +583,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction @Override public void onConfigurationChanged(final Configuration conf) { - // System locale has been changed. Needs to reload keyboard. - if (mSubtypeSwitcher.onConfigurationChanged(conf)) { - loadKeyboard(); - } // If orientation changed while predicting, commit the change if (mDisplayOrientation != conf.orientation) { mDisplayOrientation = conf.orientation; @@ -651,7 +648,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction public void onCurrentInputMethodSubtypeChanged(final InputMethodSubtype subtype) { // Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged() // is not guaranteed. It may even be called at the same time on a different thread. - mSubtypeSwitcher.updateSubtype(subtype); + mSubtypeSwitcher.onSubtypeChanged(subtype); loadKeyboard(); } @@ -719,15 +716,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction final boolean inputTypeChanged = !mCurrentSettings.isSameInputType(editorInfo); final boolean isDifferentTextField = !restarting || inputTypeChanged; if (isDifferentTextField) { - final boolean currentSubtypeEnabled = mSubtypeSwitcher - .updateParametersOnStartInputViewAndReturnIfCurrentSubtypeEnabled(); - if (!currentSubtypeEnabled) { - // Current subtype is disabled. Needs to update subtype and keyboard. - final InputMethodSubtype newSubtype = mRichImm.getCurrentInputMethodSubtype( - mSubtypeSwitcher.getNoLanguageSubtype()); - mSubtypeSwitcher.updateSubtype(newSubtype); - loadKeyboard(); - } + mSubtypeSwitcher.updateParametersOnStartInputView(); } // The EditorInfo might have a flag that affects fullscreen mode. @@ -1009,9 +998,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction final boolean isAutoCorrection = false; setSuggestionStrip(suggestedWords, isAutoCorrection); setAutoCorrectionIndicator(isAutoCorrection); - // TODO: is this the right thing to do? What should we auto-correct to in - // this case? This says to keep whatever the user typed. - mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); setSuggestionStripShown(true); if (ProductionFlag.IS_EXPERIMENTAL) { ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions); @@ -1152,6 +1138,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction if (typedWord.length() > 0) { commitChosenWord(typedWord, LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, separatorString); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().onWordComplete(typedWord, Long.MAX_VALUE); + } } } @@ -1187,8 +1176,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction if (lastTwo != null && lastTwo.length() == 2 && lastTwo.charAt(0) == Constants.CODE_SPACE) { mConnection.deleteSurroundingText(2, 0); - mConnection.commitText(lastTwo.charAt(1) + " ", 1); + final String text = lastTwo.charAt(1) + " "; + mConnection.commitText(text, 1); if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().onWordComplete(text, Long.MAX_VALUE); ResearchLogger.latinIME_swapSwapperAndSpace(); } mKeyboardSwitcher.updateShiftState(); @@ -1206,7 +1197,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction && lastThree.charAt(2) == Constants.CODE_SPACE) { mHandler.cancelDoubleSpacePeriodTimer(); mConnection.deleteSurroundingText(2, 0); - mConnection.commitText(". ", 1); + final String textToInsert = ". "; + mConnection.commitText(textToInsert, 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().onWordComplete(textToInsert, Long.MAX_VALUE); + } mKeyboardSwitcher.updateShiftState(); return true; } @@ -1324,10 +1319,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction return; } - // 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because - // we want to be able to compile against the Ice Cream Sandwich SDK. if (Constants.CODE_ENTER == code && mTargetApplicationInfo != null - && mTargetApplicationInfo.targetSdkVersion < 16) { + && mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) { // Backward compatibility mode. Before Jelly bean, the keyboard would simulate // a hardware keyboard event on pressing enter or delete. This is bad for many // reasons (there are race conditions with commits) but some applications are @@ -1445,7 +1438,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction public void onTextInput(final String rawText) { mConnection.beginBatchEdit(); if (mWordComposer.isComposingWord()) { - commitCurrentAutoCorrection(rawText.toString()); + commitCurrentAutoCorrection(rawText); } else { resetComposingState(true /* alsoResetLastComposedWord */); } @@ -1455,6 +1448,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction promotePhantomSpace(); } mConnection.commitText(text, 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().onWordComplete(text, Long.MAX_VALUE); + } mConnection.endBatchEdit(); // Space state must be updated before calling updateShiftState mSpaceState = SPACE_STATE_NONE; @@ -1679,6 +1675,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction if (length > 0) { if (mWordComposer.isBatchMode()) { mWordComposer.reset(); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_handleBackspace_batch(mWordComposer.getTypedWord()); + } } else { mWordComposer.deleteLast(); } @@ -1734,10 +1733,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // This should never happen. Log.e(TAG, "Backspace when we don't know the selection position"); } - // 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because - // we want to be able to compile against the Ice Cream Sandwich SDK. if (mTargetApplicationInfo != null - && mTargetApplicationInfo.targetSdkVersion < 16) { + && mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) { // Backward compatibility mode. Before Jelly bean, the keyboard would simulate // a hardware keyboard event on pressing enter or delete. This is bad for many // reasons (there are race conditions with commits) but some applications are @@ -1920,6 +1917,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } private void handleClose() { + // TODO: Verify that words are logged properly when IME is closed. commitTyped(LastComposedWord.NOT_A_SEPARATOR); requestHideSelf(0); final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); @@ -1983,7 +1981,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction if (mWordComposer.isComposingWord()) { Log.w(TAG, "Called updateSuggestionsOrPredictions but suggestions were not " + "requested!"); - mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); } return; } @@ -2086,10 +2083,14 @@ public final class LatinIME extends InputMethodService implements KeyboardAction + "is empty? Impossible! I must commit suicide."); } if (ProductionFlag.IS_INTERNAL) { - Stats.onAutoCorrection( - typedWord, autoCorrection.toString(), separatorString, mWordComposer); + Stats.onAutoCorrection(typedWord, autoCorrection, separatorString, mWordComposer); } mExpectingUpdateSelection = true; + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIme_commitCurrentAutoCorrection(typedWord, autoCorrection, + separatorString); + } + commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD, separatorString); if (!typedWord.equals(autoCorrection)) { @@ -2115,7 +2116,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction if (suggestion.length() == 1 && isShowingPunctuationList()) { // Word separators are suggested before the user inputs something. // So, LatinImeLogger logs "" as a user's input. - LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords); + LatinImeLogger.logOnManualSuggestion("", suggestion, index, suggestedWords); // Rely on onCodeInput to do the complicated swapping/stripping logic consistently. final int primaryCode = suggestion.charAt(0); onCodeInput(primaryCode, @@ -2154,9 +2155,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // We need to log before we commit, because the word composer will store away the user // typed word. - final String replacedWord = mWordComposer.getTypedWord().toString(); - LatinImeLogger.logOnManualSuggestion(replacedWord, - suggestion.toString(), index, suggestedWords); + final String replacedWord = mWordComposer.getTypedWord(); + LatinImeLogger.logOnManualSuggestion(replacedWord, suggestion, index, suggestedWords); mExpectingUpdateSelection = true; commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK, LastComposedWord.NOT_A_SEPARATOR); @@ -2205,8 +2205,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // what user typed. Note: currently this is done much later in // LastComposedWord#didCommitTypedWord by string equality of the remembered // strings. - mLastComposedWord = mWordComposer.commitWord(commitType, chosenWord.toString(), - separatorString, prevWord); + mLastComposedWord = mWordComposer.commitWord(commitType, chosenWord, separatorString, + prevWord); } private void setPunctuationSuggestions() { @@ -2230,7 +2230,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction final UserHistoryDictionary userHistoryDictionary = mUserHistoryDictionary; if (userHistoryDictionary != null) { - final CharSequence prevWord + final String prevWord = mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators, 2); final String secondWord; if (mWordComposer.wasAutoCapitalized() && !mWordComposer.isMostlyCaps()) { @@ -2243,9 +2243,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction final int maxFreq = AutoCorrection.getMaxFrequency( mSuggest.getUnigramDictionaries(), suggestion); if (maxFreq == 0) return null; - final String prevWordString = (null == prevWord) ? null : prevWord.toString(); - userHistoryDictionary.addToUserHistory(prevWordString, secondWord, maxFreq > 0); - return prevWordString; + userHistoryDictionary.addToUserHistory(prevWord, secondWord, maxFreq > 0); + return prevWord; } return null; } @@ -2293,8 +2292,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } mConnection.deleteSurroundingText(deleteLength, 0); if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) { - mUserHistoryDictionary.cancelAddingUserHistory( - previousWord.toString(), committedWord.toString()); + mUserHistoryDictionary.cancelAddingUserHistory(previousWord, committedWord); } mConnection.commitText(originallyTypedWord + mLastComposedWord.mSeparatorString, 1); if (ProductionFlag.IS_INTERNAL) { @@ -2302,7 +2300,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); } if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.latinIME_revertCommit(originallyTypedWord); + ResearchLogger.latinIME_revertCommit(committedWord, originallyTypedWord); + ResearchLogger.getInstance().onWordComplete(originallyTypedWord, Long.MAX_VALUE); } // Don't restart suggestion yet. We'll restart if the user deletes the // separator. @@ -2390,7 +2389,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction @Override public boolean onKeyUp(final int keyCode, final KeyEvent event) { - if (mEventInterpreter.onHardwareKeyEvent(event)) return true; return super.onKeyUp(keyCode, event); } diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index 394a9c7aa..e4e8b94b2 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -31,7 +31,7 @@ public final class LatinImeLogger implements SharedPreferences.OnSharedPreferenc public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { } - public static void init(LatinIME context, SharedPreferences prefs) { + public static void init(LatinIME context) { } public static void commit() { diff --git a/java/src/com/android/inputmethod/latin/PositionalInfoForUserDictPendingAddition.java b/java/src/com/android/inputmethod/latin/PositionalInfoForUserDictPendingAddition.java index 8a2d22256..1fd25636c 100644 --- a/java/src/com/android/inputmethod/latin/PositionalInfoForUserDictPendingAddition.java +++ b/java/src/com/android/inputmethod/latin/PositionalInfoForUserDictPendingAddition.java @@ -29,7 +29,7 @@ import android.view.inputmethod.EditorInfo; * the IME needs to take a note of what it has to replace and where it is. * This class encapsulates this data. */ -public class PositionalInfoForUserDictPendingAddition { +public final class PositionalInfoForUserDictPendingAddition { final private String mOriginalWord; final private int mCursorPos; // Position of the cursor after the word final private EditorInfo mEditorInfo; // On what binding this has been added diff --git a/java/src/com/android/inputmethod/latin/ResourceUtils.java b/java/src/com/android/inputmethod/latin/ResourceUtils.java index 5021ad384..b74b979b5 100644 --- a/java/src/com/android/inputmethod/latin/ResourceUtils.java +++ b/java/src/com/android/inputmethod/latin/ResourceUtils.java @@ -19,11 +19,15 @@ package com.android.inputmethod.latin; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Build; +import android.util.Log; import android.util.TypedValue; import java.util.HashMap; public final class ResourceUtils { + private static final String TAG = ResourceUtils.class.getSimpleName(); + private static final boolean DEBUG = false; + public static final float UNDEFINED_RATIO = -1.0f; public static final int UNDEFINED_DIMENSION = -1; @@ -31,24 +35,44 @@ public final class ResourceUtils { // This utility class is not publicly instantiable. } + private static final String DEFAULT_PREFIX = "DEFAULT,"; private static final String HARDWARE_PREFIX = Build.HARDWARE + ","; private static final HashMap<String, String> sDeviceOverrideValueMap = CollectionUtils.newHashMap(); - public static String getDeviceOverrideValue(Resources res, int overrideResId, String defValue) { + public static String getDeviceOverrideValue(final Resources res, final int overrideResId) { final int orientation = res.getConfiguration().orientation; final String key = overrideResId + "-" + orientation; - if (!sDeviceOverrideValueMap.containsKey(key)) { - String overrideValue = defValue; - for (final String element : res.getStringArray(overrideResId)) { - if (element.startsWith(HARDWARE_PREFIX)) { - overrideValue = element.substring(HARDWARE_PREFIX.length()); - break; - } + if (sDeviceOverrideValueMap.containsKey(key)) { + return sDeviceOverrideValueMap.get(key); + } + + final String[] overrideArray = res.getStringArray(overrideResId); + final String overrideValue = StringUtils.findPrefixedString(HARDWARE_PREFIX, overrideArray); + // The overrideValue might be an empty string. + if (overrideValue != null) { + if (DEBUG) { + Log.d(TAG, "Find override value:" + + " resource="+ res.getResourceEntryName(overrideResId) + + " Build.HARDWARE=" + Build.HARDWARE + " override=" + overrideValue); } sDeviceOverrideValueMap.put(key, overrideValue); + return overrideValue; + } + + final String defaultValue = StringUtils.findPrefixedString(DEFAULT_PREFIX, overrideArray); + // The defaultValue might be an empty string. + if (defaultValue == null) { + Log.w(TAG, "Couldn't find override value nor default value:" + + " resource="+ res.getResourceEntryName(overrideResId) + + " Build.HARDWARE=" + Build.HARDWARE); + } else if (DEBUG) { + Log.d(TAG, "Found default value:" + + " resource="+ res.getResourceEntryName(overrideResId) + + " Build.HARDWARE=" + Build.HARDWARE + " default=" + defaultValue); } - return sDeviceOverrideValueMap.get(key); + sDeviceOverrideValueMap.put(key, defaultValue); + return defaultValue; } public static boolean isValidFraction(final float fraction) { @@ -85,8 +109,8 @@ public final class ResourceUtils { return a.getDimensionPixelSize(index, ResourceUtils.UNDEFINED_DIMENSION); } - public static float getDimensionOrFraction(TypedArray a, int index, int base, - float defValue) { + public static float getDimensionOrFraction(final TypedArray a, final int index, final int base, + final float defValue) { final TypedValue value = a.peekValue(index); if (value == null) { return defValue; @@ -99,7 +123,7 @@ public final class ResourceUtils { return defValue; } - public static int getEnumValue(TypedArray a, int index, int defValue) { + public static int getEnumValue(final TypedArray a, final int index, final int defValue) { final TypedValue value = a.peekValue(index); if (value == null) { return defValue; @@ -110,19 +134,19 @@ public final class ResourceUtils { return defValue; } - public static boolean isFractionValue(TypedValue v) { + public static boolean isFractionValue(final TypedValue v) { return v.type == TypedValue.TYPE_FRACTION; } - public static boolean isDimensionValue(TypedValue v) { + public static boolean isDimensionValue(final TypedValue v) { return v.type == TypedValue.TYPE_DIMENSION; } - public static boolean isIntegerValue(TypedValue v) { + public static boolean isIntegerValue(final TypedValue v) { return v.type >= TypedValue.TYPE_FIRST_INT && v.type <= TypedValue.TYPE_LAST_INT; } - public static boolean isStringValue(TypedValue v) { + public static boolean isStringValue(final TypedValue v) { return v.type == TypedValue.TYPE_STRING; } } diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index e9c81dab0..9cb24b54e 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -178,9 +178,6 @@ public final class RichInputConnection { mComposingText.setLength(0); if (null != mIC) { mIC.commitText(text, i); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.richInputConnection_commitText(text, i); - } } } @@ -287,40 +284,40 @@ public final class RichInputConnection { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) { if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); - // This method is only called for enter or backspace when speaking to old - // applications (target SDK <= 15), or for digits. + // This method is only called for enter or backspace when speaking to old applications + // (target SDK <= 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)), or for digits. // When talking to new applications we never use this method because it's inherently // racy and has unpredictable results, but for backward compatibility we continue // sending the key events for only Enter and Backspace because some applications // mistakenly catch them to do some stuff. switch (keyEvent.getKeyCode()) { - case KeyEvent.KEYCODE_ENTER: - mCommittedTextBeforeComposingText.append("\n"); - mCurrentCursorPosition += 1; - break; - case KeyEvent.KEYCODE_DEL: - if (0 == mComposingText.length()) { - if (mCommittedTextBeforeComposingText.length() > 0) { - mCommittedTextBeforeComposingText.delete( - mCommittedTextBeforeComposingText.length() - 1, - mCommittedTextBeforeComposingText.length()); - } - } else { - mComposingText.delete(mComposingText.length() - 1, mComposingText.length()); - } - if (mCurrentCursorPosition > 0) mCurrentCursorPosition -= 1; - break; - case KeyEvent.KEYCODE_UNKNOWN: - if (null != keyEvent.getCharacters()) { - mCommittedTextBeforeComposingText.append(keyEvent.getCharacters()); - mCurrentCursorPosition += keyEvent.getCharacters().length(); + case KeyEvent.KEYCODE_ENTER: + mCommittedTextBeforeComposingText.append("\n"); + mCurrentCursorPosition += 1; + break; + case KeyEvent.KEYCODE_DEL: + if (0 == mComposingText.length()) { + if (mCommittedTextBeforeComposingText.length() > 0) { + mCommittedTextBeforeComposingText.delete( + mCommittedTextBeforeComposingText.length() - 1, + mCommittedTextBeforeComposingText.length()); } - break; - default: - final String text = new String(new int[] { keyEvent.getUnicodeChar() }, 0, 1); - mCommittedTextBeforeComposingText.append(text); - mCurrentCursorPosition += text.length(); - break; + } else { + mComposingText.delete(mComposingText.length() - 1, mComposingText.length()); + } + if (mCurrentCursorPosition > 0) mCurrentCursorPosition -= 1; + break; + case KeyEvent.KEYCODE_UNKNOWN: + if (null != keyEvent.getCharacters()) { + mCommittedTextBeforeComposingText.append(keyEvent.getCharacters()); + mCurrentCursorPosition += keyEvent.getCharacters().length(); + } + break; + default: + final String text = new String(new int[] { keyEvent.getUnicodeChar() }, 0, 1); + mCommittedTextBeforeComposingText.append(text); + mCurrentCursorPosition += text.length(); + break; } } if (null != mIC) { @@ -537,17 +534,17 @@ public final class RichInputConnection { // Going backward, alternate skipping non-separators and separators until enough words // have been read. int count = additionalPrecedingWordsCount; - int start = before.length(); + int startIndexInBefore = before.length(); boolean isStoppingAtWhitespace = true; // toggles to indicate what to stop at while (true) { // see comments below for why this is guaranteed to halt - while (start > 0) { - final int codePoint = Character.codePointBefore(before, start); + while (startIndexInBefore > 0) { + final int codePoint = Character.codePointBefore(before, startIndexInBefore); if (isStoppingAtWhitespace == isSeparator(codePoint, sep)) { break; // inner loop } - --start; + --startIndexInBefore; if (Character.isSupplementaryCodePoint(codePoint)) { - --start; + --startIndexInBefore; } } // isStoppingAtWhitespace is true every other time through the loop, @@ -560,25 +557,20 @@ public final class RichInputConnection { } // Find last word separator after the cursor - int end = -1; - while (++end < after.length()) { - final int codePoint = Character.codePointAt(after, end); + int endIndexInAfter = -1; + while (++endIndexInAfter < after.length()) { + final int codePoint = Character.codePointAt(after, endIndexInAfter); if (isSeparator(codePoint, sep)) { break; } if (Character.isSupplementaryCodePoint(codePoint)) { - ++end; + ++endIndexInAfter; } } - final int cursor = getCursorPosition(); - if (start >= 0 && cursor + end <= after.length() + before.length()) { - String word = before.toString().substring(start, before.length()) - + after.toString().substring(0, end); - return new Range(before.length() - start, end, word); - } - - return null; + final String word = before.toString().substring(startIndexInBefore, before.length()) + + after.toString().substring(0, endIndexInAfter); + return new Range(before.length() - startIndexInBefore, endIndexInAfter, word); } public boolean isCursorTouchingWord(final SettingsValues settingsValues) { @@ -665,7 +657,11 @@ public final class RichInputConnection { return false; } deleteSurroundingText(2, 0); - commitText(" ", 1); + final String doubleSpace = " "; + commitText(doubleSpace, 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().onWordComplete(doubleSpace, Long.MAX_VALUE); + } return true; } @@ -686,7 +682,11 @@ public final class RichInputConnection { return false; } deleteSurroundingText(2, 0); - commitText(" " + textBeforeCursor.subSequence(0, 1), 1); + final String text = " " + textBeforeCursor.subSequence(0, 1); + commitText(text, 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().onWordComplete(text, Long.MAX_VALUE); + } return true; } diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java index af0d61cc7..637916f76 100644 --- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java +++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java @@ -21,6 +21,7 @@ import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE; import android.content.Context; import android.content.SharedPreferences; import android.os.IBinder; +import android.preference.PreferenceManager; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; @@ -50,7 +51,8 @@ public final class RichInputMethodManager { return sInstance; } - public static void init(final Context context, final SharedPreferences prefs) { + public static void init(final Context context) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); sInstance.initInternal(context, prefs); } diff --git a/java/src/com/android/inputmethod/latin/SeekBarDialog.java b/java/src/com/android/inputmethod/latin/SeekBarDialog.java new file mode 100644 index 000000000..e576c0984 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/SeekBarDialog.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.latin; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; + +public final class SeekBarDialog implements DialogInterface.OnClickListener, + OnSeekBarChangeListener { + public interface Listener { + public void onPositiveButtonClick(final SeekBarDialog dialog); + public void onNegativeButtonClick(final SeekBarDialog dialog); + public void onProgressChanged(final SeekBarDialog dialog); + public void onStartTrackingTouch(final SeekBarDialog dialog); + public void onStopTrackingTouch(final SeekBarDialog dialog); + } + + public static class Adapter implements Listener { + @Override + public void onPositiveButtonClick(final SeekBarDialog dialog) {} + @Override + public void onNegativeButtonClick(final SeekBarDialog dialog) { dialog.dismiss(); } + @Override + public void onProgressChanged(final SeekBarDialog dialog) {} + @Override + public void onStartTrackingTouch(final SeekBarDialog dialog) {} + @Override + public void onStopTrackingTouch(final SeekBarDialog dialog) {} + } + + private static final Listener EMPTY_ADAPTER = new Adapter(); + + private final AlertDialog mDialog; + private final Listener mListener; + private final TextView mValueView; + private final SeekBar mSeekBar; + private final String mValueFormat; + + private int mValue; + + private SeekBarDialog(final Builder builder) { + final AlertDialog.Builder dialogBuilder = builder.mDialogBuilder; + dialogBuilder.setView(builder.mView); + dialogBuilder.setPositiveButton(android.R.string.ok, this); + dialogBuilder.setNegativeButton(android.R.string.cancel, this); + mDialog = dialogBuilder.create(); + mListener = (builder.mListener == null) ? EMPTY_ADAPTER : builder.mListener; + mValueView = (TextView)builder.mView.findViewById(R.id.seek_bar_dialog_value); + mSeekBar = (SeekBar)builder.mView.findViewById(R.id.seek_bar_dialog_bar); + mSeekBar.setMax(builder.mMaxValue); + mSeekBar.setOnSeekBarChangeListener(this); + if (builder.mValueFormatResId == 0) { + mValueFormat = "%s"; + } else { + mValueFormat = mDialog.getContext().getString(builder.mValueFormatResId); + } + } + + public void setValue(final int value, final boolean fromUser) { + mValue = value; + mValueView.setText(String.format(mValueFormat, value)); + if (!fromUser) { + mSeekBar.setProgress(value); + } + } + + public int getValue() { + return mValue; + } + + public CharSequence getValueText() { + return mValueView.getText(); + } + + public void show() { + mDialog.show(); + } + + public void dismiss() { + mDialog.dismiss(); + } + + @Override + public void onClick(final DialogInterface dialog, int which) { + if (which == DialogInterface.BUTTON_POSITIVE) { + mListener.onPositiveButtonClick(this); + return; + } + if (which == DialogInterface.BUTTON_NEGATIVE) { + mListener.onNegativeButtonClick(this); + return; + } + } + + @Override + public void onProgressChanged(final SeekBar seekBar, final int progress, + final boolean fromUser) { + setValue(progress, fromUser); + if (fromUser) { + mListener.onProgressChanged(this); + } + } + + @Override + public void onStartTrackingTouch(final SeekBar seekBar) { + mListener.onStartTrackingTouch(this); + } + + @Override + public void onStopTrackingTouch(final SeekBar seekBar) { + mListener.onStopTrackingTouch(this); + } + + public static final class Builder { + final AlertDialog.Builder mDialogBuilder; + final View mView; + + int mMaxValue; + int mValueFormatResId; + int mValue; + Listener mListener; + + public Builder(final Context context) { + mDialogBuilder = new AlertDialog.Builder(context); + mView = LayoutInflater.from(context).inflate(R.layout.seek_bar_dialog, null); + } + + public Builder setTitle(final int resId) { + mDialogBuilder.setTitle(resId); + return this; + } + + public Builder setMaxValue(final int max) { + mMaxValue = max; + return this; + } + + public Builder setValueFromat(final int resId) { + mValueFormatResId = resId; + return this; + } + + public Builder setValue(final int value) { + mValue = value; + return this; + } + + public Builder setListener(final Listener listener) { + mListener = listener; + return this; + } + + public SeekBarDialog create() { + final SeekBarDialog dialog = new SeekBarDialog(this); + dialog.setValue(mValue, false /* fromUser */); + return dialog; + } + } +} diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 7a73cade3..222adcb2e 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -16,10 +16,8 @@ package com.android.inputmethod.latin; -import android.app.AlertDialog; import android.app.backup.BackupManager; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; @@ -31,12 +29,7 @@ import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; -import android.view.LayoutInflater; -import android.view.View; import android.view.inputmethod.InputMethodSubtype; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.TextView; import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethodcommon.InputMethodSettingsFragment; @@ -94,9 +87,6 @@ public final class Settings extends InputMethodSettingsFragment private CheckBoxPreference mBigramPrediction; private Preference mDebugSettingsPreference; - private TextView mKeypressVibrationDurationSettingsTextView; - private TextView mKeypressSoundVolumeSettingsTextView; - private static void setPreferenceEnabled(final Preference preference, final boolean enabled) { if (preference != null) { preference.setEnabled(enabled); @@ -127,7 +117,7 @@ public final class Settings extends InputMethodSettingsFragment mVoicePreference = (ListPreference) findPreference(PREF_VOICE_MODE); mShowCorrectionSuggestionsPreference = (ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING); - SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); + final SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); prefs.registerOnSharedPreferenceChangeListener(this); mAutoCorrectionThresholdPreference = @@ -227,7 +217,9 @@ public final class Settings extends InputMethodSettingsFragment return true; } }); - updateKeypressVibrationDurationSettingsSummary(prefs, res); + mKeypressVibrationDurationSettingsPref.setSummary( + res.getString(R.string.settings_keypress_vibration_duration, + SettingsValues.getCurrentVibrationDuration(prefs, res))); } mKeypressSoundVolumeSettingsPref = @@ -241,7 +233,8 @@ public final class Settings extends InputMethodSettingsFragment return true; } }); - updateKeypressSoundVolumeSummary(prefs, res); + mKeypressSoundVolumeSettingsPref.setSummary(String.valueOf( + getCurrentKeyPressSoundVolumePercent(prefs, res))); } refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, res); } @@ -349,122 +342,73 @@ public final class Settings extends InputMethodSettingsFragment } } - private void updateKeypressVibrationDurationSettingsSummary( - final SharedPreferences sp, final Resources res) { - if (mKeypressVibrationDurationSettingsPref != null) { - mKeypressVibrationDurationSettingsPref.setSummary( - SettingsValues.getCurrentVibrationDuration(sp, res) - + res.getString(R.string.settings_ms)); - } - } - private void showKeypressVibrationDurationSettingsDialog() { final SharedPreferences sp = getPreferenceManager().getSharedPreferences(); final Context context = getActivity(); - final Resources res = context.getResources(); - final AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.prefs_keypress_vibration_duration_settings); - builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + final PreferenceScreen settingsPref = mKeypressVibrationDurationSettingsPref; + final SeekBarDialog.Listener listener = new SeekBarDialog.Adapter() { @Override - public void onClick(DialogInterface dialog, int whichButton) { - final int ms = Integer.valueOf( - mKeypressVibrationDurationSettingsTextView.getText().toString()); + public void onPositiveButtonClick(final SeekBarDialog dialog) { + final int ms = dialog.getValue(); sp.edit().putInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, ms).apply(); - updateKeypressVibrationDurationSettingsSummary(sp, res); - } - }); - builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int whichButton) { - dialog.dismiss(); - } - }); - final View v = LayoutInflater.from(context).inflate( - R.layout.vibration_settings_dialog, null); - final int currentMs = SettingsValues.getCurrentVibrationDuration( - getPreferenceManager().getSharedPreferences(), getResources()); - mKeypressVibrationDurationSettingsTextView = (TextView)v.findViewById(R.id.vibration_value); - final SeekBar sb = (SeekBar)v.findViewById(R.id.vibration_settings); - sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { - final int tempMs = arg1; - mKeypressVibrationDurationSettingsTextView.setText(String.valueOf(tempMs)); - } - - @Override - public void onStartTrackingTouch(SeekBar arg0) { + if (settingsPref != null) { + settingsPref.setSummary(dialog.getValueText()); + } } @Override - public void onStopTrackingTouch(SeekBar arg0) { - final int tempMs = arg0.getProgress(); - VibratorUtils.getInstance(context).vibrate(tempMs); + public void onStopTrackingTouch(final SeekBarDialog dialog) { + final int ms = dialog.getValue(); + VibratorUtils.getInstance(context).vibrate(ms); } - }); - sb.setProgress(currentMs); - mKeypressVibrationDurationSettingsTextView.setText(String.valueOf(currentMs)); - builder.setView(v); - builder.create().show(); + }; + final int currentMs = SettingsValues.getCurrentVibrationDuration(sp, getResources()); + final SeekBarDialog.Builder builder = new SeekBarDialog.Builder(context); + builder.setTitle(R.string.prefs_keypress_vibration_duration_settings) + .setListener(listener) + .setMaxValue(AudioAndHapticFeedbackManager.MAX_KEYPRESS_VIBRATION_DURATION) + .setValueFromat(R.string.settings_keypress_vibration_duration) + .setValue(currentMs) + .create() + .show(); } - private void updateKeypressSoundVolumeSummary(final SharedPreferences sp, final Resources res) { - if (mKeypressSoundVolumeSettingsPref != null) { - mKeypressSoundVolumeSettingsPref.setSummary(String.valueOf( - (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100))); - } + private static final int PERCENT_INT = 100; + private static final float PERCENT_FLOAT = 100.0f; + + private static int getCurrentKeyPressSoundVolumePercent(final SharedPreferences sp, + final Resources res) { + return (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * PERCENT_FLOAT); } private void showKeypressSoundVolumeSettingDialog() { + final SharedPreferences sp = getPreferenceManager().getSharedPreferences(); final Context context = getActivity(); final AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - final SharedPreferences sp = getPreferenceManager().getSharedPreferences(); - final Resources res = context.getResources(); - final AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.prefs_keypress_sound_volume_settings); - builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + final PreferenceScreen settingsPref = mKeypressSoundVolumeSettingsPref; + final SeekBarDialog.Listener listener = new SeekBarDialog.Adapter() { @Override - public void onClick(DialogInterface dialog, int whichButton) { - final float volume = - ((float)Integer.valueOf( - mKeypressSoundVolumeSettingsTextView.getText().toString())) / 100; + public void onPositiveButtonClick(final SeekBarDialog dialog) { + final float volume = dialog.getValue() / PERCENT_FLOAT; sp.edit().putFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, volume).apply(); - updateKeypressSoundVolumeSummary(sp, res); - } - }); - builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int whichButton) { - dialog.dismiss(); - } - }); - final View v = LayoutInflater.from(context).inflate( - R.layout.sound_effect_volume_dialog, null); - final int currentVolumeInt = - (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100); - mKeypressSoundVolumeSettingsTextView = - (TextView)v.findViewById(R.id.sound_effect_volume_value); - final SeekBar sb = (SeekBar)v.findViewById(R.id.sound_effect_volume_bar); - sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { - final int tempVolume = arg1; - mKeypressSoundVolumeSettingsTextView.setText(String.valueOf(tempVolume)); - } - - @Override - public void onStartTrackingTouch(SeekBar arg0) { + if (settingsPref != null) { + settingsPref.setSummary(dialog.getValueText()); + } } @Override - public void onStopTrackingTouch(SeekBar arg0) { - final float tempVolume = ((float)arg0.getProgress()) / 100; - am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, tempVolume); + public void onStopTrackingTouch(final SeekBarDialog dialog) { + final float volume = dialog.getValue() / PERCENT_FLOAT; + am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, volume); } - }); - sb.setProgress(currentVolumeInt); - mKeypressSoundVolumeSettingsTextView.setText(String.valueOf(currentVolumeInt)); - builder.setView(v); - builder.create().show(); + }; + final SeekBarDialog.Builder builder = new SeekBarDialog.Builder(context); + final int currentVolumeInt = getCurrentKeyPressSoundVolumePercent(sp, getResources()); + builder.setTitle(R.string.prefs_keypress_sound_volume_settings) + .setListener(listener) + .setMaxValue(PERCENT_INT) + .setValue(currentVolumeInt) + .create() + .show(); } } diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index a23876722..157684437 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -78,10 +78,6 @@ public final class SettingsValues { public final boolean mUseDoubleSpacePeriod; // Use bigrams to predict the next word when there is no input for it yet public final boolean mBigramPredictionEnabled; - @SuppressWarnings("unused") // TODO: Use this - private final int mVibrationDurationSettingsRawValue; - @SuppressWarnings("unused") // TODO: Use this - private final float mKeypressSoundVolumeRawValue; public final boolean mGestureInputEnabled; public final boolean mGesturePreviewTrailEnabled; public final boolean mGestureFloatingPreviewTextEnabled; @@ -158,9 +154,6 @@ public final class SettingsValues { mUseDoubleSpacePeriod = prefs.getBoolean(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true); mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue); mBigramPredictionEnabled = isBigramPredictionEnabled(prefs, res); - mVibrationDurationSettingsRawValue = - prefs.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1); - mKeypressSoundVolumeRawValue = prefs.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f); // Compute other readable settings mKeypressVibrationDuration = getCurrentVibrationDuration(prefs, res); @@ -383,27 +376,23 @@ public final class SettingsValues { // Accessed from the settings interface, hence public public static float getCurrentKeypressSoundVolume(final SharedPreferences prefs, final Resources res) { - // TODO: use mVibrationDurationSettingsRawValue instead of reading it again here final float volume = prefs.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f); if (volume >= 0) { return volume; } - - return Float.parseFloat(ResourceUtils.getDeviceOverrideValue( - res, R.array.keypress_volumes, "-1.0f")); + return Float.parseFloat( + ResourceUtils.getDeviceOverrideValue(res, R.array.keypress_volumes)); } // Likewise public static int getCurrentVibrationDuration(final SharedPreferences prefs, final Resources res) { - // TODO: use mKeypressVibrationDuration instead of reading it again here final int ms = prefs.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1); if (ms >= 0) { return ms; } - - return Integer.parseInt(ResourceUtils.getDeviceOverrideValue( - res, R.array.keypress_vibration_durations, "-1")); + return Integer.parseInt( + ResourceUtils.getDeviceOverrideValue(res, R.array.keypress_vibration_durations)); } // Likewise diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java index 043043cef..ddaa5ff5b 100644 --- a/java/src/com/android/inputmethod/latin/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/StringUtils.java @@ -62,6 +62,23 @@ public final class StringUtils { } /** + * Find a string that start with specified prefix from an array. + * + * @param prefix a prefix string to find. + * @param array an string array to be searched. + * @return the rest part of the string that starts with the prefix. + * Returns null if it couldn't be found. + */ + public static String findPrefixedString(final String prefix, final String[] array) { + for (final String element : array) { + if (element.startsWith(prefix)) { + return element.substring(prefix.length()); + } + } + return null; + } + + /** * Remove duplicates from an array of strings. * * This method will always keep the first occurrence of all strings at their position diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java index 5d8c0b17d..370a6594b 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java +++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java @@ -130,7 +130,8 @@ public final class SubtypeLocale { } public static int getSubtypeNameId(String localeString, String keyboardLayoutName) { - if (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15 && isExceptionalLocale(localeString)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN + && isExceptionalLocale(localeString)) { return sExceptionalLocaleToWithLayoutNameIdsMap.get(localeString); } final String key = localeString.equals(NO_LANGUAGE) @@ -166,8 +167,9 @@ public final class SubtypeLocale { // zz azerty T No language (AZERTY) in system locale public static String getSubtypeDisplayName(final InputMethodSubtype subtype, Resources res) { - final String replacementString = (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15 - && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) + final String replacementString = + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN + && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) ? subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME) : getSubtypeLocaleDisplayName(subtype.getLocale()); final int nameResId = subtype.getNameResId(); diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 8f2e27549..fe2908428 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -20,7 +20,6 @@ import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.REQ_NET import android.content.Context; import android.content.Intent; -import android.content.res.Configuration; import android.content.res.Resources; import android.inputmethodservice.InputMethodService; import android.net.ConnectivityManager; @@ -53,9 +52,6 @@ public final class SubtypeSwitcher { private InputMethodInfo mShortcutInputMethodInfo; private InputMethodSubtype mShortcutSubtype; private InputMethodSubtype mNoLanguageSubtype; - // Note: This variable is always non-null after {@link #initialize(LatinIME)}. - private InputMethodSubtype mCurrentSubtype; - private Locale mCurrentSystemLocale; /*-----------------------------------------------------------*/ private boolean mIsNetworkConnected; @@ -84,7 +80,6 @@ public final class SubtypeSwitcher { public static void init(final Context context) { SubtypeLocale.init(context); sInstance.initialize(context); - sInstance.updateAllParameters(); } private SubtypeSwitcher() { @@ -96,60 +91,28 @@ public final class SubtypeSwitcher { mRichImm = RichInputMethodManager.getInstance(); mConnectivityManager = (ConnectivityManager) service.getSystemService( Context.CONNECTIVITY_SERVICE); - mCurrentSystemLocale = mResources.getConfiguration().locale; mNoLanguageSubtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( SubtypeLocale.NO_LANGUAGE, SubtypeLocale.QWERTY); - mCurrentSubtype = mRichImm.getCurrentInputMethodSubtype(mNoLanguageSubtype); if (mNoLanguageSubtype == null) { throw new RuntimeException("Can't find no lanugage with QWERTY subtype"); } final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); mIsNetworkConnected = (info != null && info.isConnected()); - } - - // Update all parameters stored in SubtypeSwitcher. - // Only configuration changed event is allowed to call this because this is heavy. - private void updateAllParameters() { - mCurrentSystemLocale = mResources.getConfiguration().locale; - updateSubtype(mRichImm.getCurrentInputMethodSubtype(mNoLanguageSubtype)); - updateParametersOnStartInputViewAndReturnIfCurrentSubtypeEnabled(); - } - /** - * Update parameters which are changed outside LatinIME. This parameters affect UI so they - * should be updated every time onStartInputView. - * - * @return true if the current subtype is enabled. - */ - public boolean updateParametersOnStartInputViewAndReturnIfCurrentSubtypeEnabled() { - final boolean currentSubtypeEnabled = - updateEnabledSubtypesAndReturnIfEnabled(mCurrentSubtype); - updateShortcutIME(); - return currentSubtypeEnabled; + onSubtypeChanged(getCurrentSubtype()); + updateParametersOnStartInputView(); } /** - * Update enabled subtypes from the framework. - * - * @param subtype the subtype to be checked - * @return true if the {@code subtype} is enabled. + * Update parameters which are changed outside LatinIME. This parameters affect UI so that they + * should be updated every time onStartInputView is called. */ - private boolean updateEnabledSubtypesAndReturnIfEnabled(final InputMethodSubtype subtype) { + public void updateParametersOnStartInputView() { final List<InputMethodSubtype> enabledSubtypesOfThisIme = mRichImm.getInputMethodManager().getEnabledInputMethodSubtypeList(null, true); mNeedsToDisplayLanguage.updateEnabledSubtypeCount(enabledSubtypesOfThisIme.size()); - - for (final InputMethodSubtype ims : enabledSubtypesOfThisIme) { - if (ims.equals(subtype)) { - return true; - } - } - if (DBG) { - Log.w(TAG, "Subtype: " + subtype.getLocale() + "/" + subtype.getExtraValue() - + " was disabled"); - } - return false; + updateShortcutIME(); } private void updateShortcutIME() { @@ -185,25 +148,21 @@ public final class SubtypeSwitcher { } // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function. - public void updateSubtype(InputMethodSubtype newSubtype) { + public void onSubtypeChanged(final InputMethodSubtype newSubtype) { if (DBG) { - Log.w(TAG, "onCurrentInputMethodSubtypeChanged: to: " - + newSubtype.getLocale() + "/" + newSubtype.getExtraValue() + ", from: " - + mCurrentSubtype.getLocale() + "/" + mCurrentSubtype.getExtraValue()); + Log.w(TAG, "onSubtypeChanged: " + SubtypeLocale.getSubtypeDisplayName( + newSubtype, mResources)); } final Locale newLocale = SubtypeLocale.getSubtypeLocale(newSubtype); - final boolean sameLocale = mCurrentSystemLocale.equals(newLocale); - final boolean sameLanguage = mCurrentSystemLocale.getLanguage().equals( - newLocale.getLanguage()); + final Locale systemLocale = mResources.getConfiguration().locale; + final boolean sameLocale = systemLocale.equals(newLocale); + final boolean sameLanguage = systemLocale.getLanguage().equals(newLocale.getLanguage()); final boolean implicitlyEnabled = mRichImm.checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(newSubtype); mNeedsToDisplayLanguage.updateIsSystemLanguageSameAsInputLanguage( sameLocale || (sameLanguage && implicitlyEnabled)); - if (newSubtype.equals(mCurrentSubtype)) return; - - mCurrentSubtype = newSubtype; updateShortcutIME(); } @@ -281,21 +240,11 @@ public final class SubtypeSwitcher { } public Locale getCurrentSubtypeLocale() { - return SubtypeLocale.getSubtypeLocale(mCurrentSubtype); - } - - public boolean onConfigurationChanged(final Configuration conf) { - final Locale systemLocale = conf.locale; - final boolean systemLocaleChanged = !systemLocale.equals(mCurrentSystemLocale); - // If system configuration was changed, update all parameters. - if (systemLocaleChanged) { - updateAllParameters(); - } - return systemLocaleChanged; + return SubtypeLocale.getSubtypeLocale(getCurrentSubtype()); } public InputMethodSubtype getCurrentSubtype() { - return mCurrentSubtype; + return mRichImm.getCurrentInputMethodSubtype(mNoLanguageSubtype); } public InputMethodSubtype getNoLanguageSubtype() { diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java index ddae5ac48..6cb39426d 100644 --- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java @@ -24,6 +24,7 @@ import android.content.Intent; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.provider.UserDictionary.Words; import android.text.TextUtils; @@ -43,8 +44,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { final static String SHORTCUT = "shortcut"; private static final String[] PROJECTION_QUERY; static { - // 16 is JellyBean, but we want this to compile against ICS. - if (android.os.Build.VERSION.SDK_INT >= 16) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { PROJECTION_QUERY = new String[] { Words.WORD, SHORTCUT, @@ -90,13 +90,14 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { mObserver = new ContentObserver(null) { @Override public void onChange(final boolean self) { - // This hook is deprecated as of API level 16, but should still be supported for - // cases where the IME is running on an older version of the platform. + // This hook is deprecated as of API level 16 (Build.VERSION_CODES.JELLY_BEAN), + // but should still be supported for cases where the IME is running on an older + // version of the platform. onChange(self, null); } - // The following hook is only available as of API level 16, and as such it will only - // work on JellyBean+ devices. On older versions of the platform, the hook - // above will be called instead. + // The following hook is only available as of API level 16 + // (Build.VERSION_CODES.JELLY_BEAN), and as such it will only work on JellyBean+ + // devices. On older versions of the platform, the hook above will be called instead. @Override public void onChange(final boolean self, final Uri uri) { setRequiresReload(true); @@ -233,8 +234,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { } private void addWords(final Cursor cursor) { - // 16 is JellyBean, but we want this to compile against ICS. - final boolean hasShortcutColumn = android.os.Build.VERSION.SDK_INT >= 16; + final boolean hasShortcutColumn = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; clearFusionDictionary(); if (cursor == null) return; if (cursor.moveToFirst()) { diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java index 100e377f6..4fa3d7df8 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java @@ -48,6 +48,7 @@ public final class UserHistoryDictIOUtils { public void setBigram(final String word1, final String word2, final int frequency); } + @UsedForTesting public interface BigramDictionaryInterface { public int getFrequency(final String word1, final String word2); } @@ -214,4 +215,4 @@ public final class UserHistoryDictIOUtils { } } -}
\ No newline at end of file +} diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java index df44948f9..316f09603 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java @@ -18,6 +18,8 @@ package com.android.inputmethod.latin; import android.util.Log; +import com.android.inputmethod.annotations.UsedForTesting; + import java.util.HashMap; import java.util.Set; @@ -26,6 +28,7 @@ import java.util.Set; * All bigrams including stale ones in SQL DB should be stored in this class to avoid adding stale * bigrams when we write to the SQL DB. */ +@UsedForTesting public final class UserHistoryDictionaryBigramList { public static final byte FORGETTING_CURVE_INITIAL_VALUE = 0; private static final String TAG = UserHistoryDictionaryBigramList.class.getSimpleName(); diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index 3eac6a237..acfcd5354 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -61,7 +61,7 @@ public final class Utils { } } - /* package */ static class RingCharBuffer { + /* package */ static final class RingCharBuffer { private static RingCharBuffer sRingCharBuffer = new RingCharBuffer(); private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC'; private static final int INVALID_COORDINATE = -2; @@ -203,7 +203,7 @@ public final class Utils { } // Initialization-on-demand holder - private static class OnDemandInitializationHolder { + private static final class OnDemandInitializationHolder { public static final UsabilityStudyLogUtils sInstance = new UsabilityStudyLogUtils(); } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index f1a7e97e8..937d7ab34 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -56,6 +56,7 @@ public final class BinaryDictInputOutput { private static final int MAX_PASSES = 24; private static final int MAX_JUMPS = 12; + @UsedForTesting public interface FusionDictionaryBufferInterface { public int readUnsignedByte(); public int readUnsignedShort(); diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index f7cc69359..bfc275df5 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin.makedict; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.Constants; import java.util.ArrayList; @@ -29,6 +30,7 @@ import java.util.LinkedList; /** * A dictionary that can fusion heads and tails of words for more compression. */ +@UsedForTesting public final class FusionDictionary implements Iterable<Word> { private static final boolean DBG = MakedictLog.DBG; |