diff options
Diffstat (limited to 'java/src')
18 files changed, 158 insertions, 147 deletions
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java index e82d91411..a9e48404a 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java @@ -48,21 +48,30 @@ public class SuggestionSpanUtils { Context.class, Locale.class, String[].class, int.class, Class.class }; private static final Constructor<?> CONSTRUCTOR_SuggestionSpan = CompatUtils .getConstructor(CLASS_SuggestionSpan, INPUT_TYPE_SuggestionSpan); - public static final Field FIELD_FLAG_AUTO_CORRECTION - = CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_AUTO_CORRECTION"); + public static final Field FIELD_FLAG_EASY_CORRECT = + CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_EASY_CORRECT"); + public static final Field FIELD_FLAG_MISSPELLED = + CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_MISSPELLED"); + public static final Field FIELD_FLAG_AUTO_CORRECTION = + CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_AUTO_CORRECTION"); public static final Field FIELD_SUGGESTIONS_MAX_SIZE = CompatUtils.getField(CLASS_SuggestionSpan, "SUGGESTIONS_MAX_SIZE"); + public static final Integer OBJ_FLAG_EASY_CORRECT = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_FLAG_EASY_CORRECT); + public static final Integer OBJ_FLAG_MISSPELLED = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_FLAG_MISSPELLED); public static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION);; + .getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION); public static final Integer OBJ_SUGGESTIONS_MAX_SIZE = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_SUGGESTIONS_MAX_SIZE);; + .getFieldValue(null, null, FIELD_SUGGESTIONS_MAX_SIZE); static { SUGGESTION_SPAN_IS_SUPPORTED = CLASS_SuggestionSpan != null && CONSTRUCTOR_SuggestionSpan != null; if (LatinImeLogger.sDBG) { if (SUGGESTION_SPAN_IS_SUPPORTED - && (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null)) { + && (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null + || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null)) { throw new RuntimeException("Field is accidentially null."); } } @@ -71,7 +80,8 @@ public class SuggestionSpanUtils { public static CharSequence getTextWithAutoCorrectionIndicatorUnderline( Context context, CharSequence text) { if (TextUtils.isEmpty(text) || CONSTRUCTOR_SuggestionSpan == null - || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null) { + || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null + || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null) { return text; } final Spannable spannable = text instanceof Spannable @@ -104,6 +114,7 @@ public class SuggestionSpanUtils { spannable = new SpannableString(pickedWord); } final ArrayList<String> suggestionsList = new ArrayList<String>(); + boolean sameAsTyped = false; for (int i = 0; i < suggestedWords.size(); ++i) { if (suggestionsList.size() >= OBJ_SUGGESTIONS_MAX_SIZE) { break; @@ -111,11 +122,18 @@ public class SuggestionSpanUtils { final CharSequence word = suggestedWords.getWord(i); if (!TextUtils.equals(pickedWord, word)) { suggestionsList.add(word.toString()); + } else if (i == 0) { + sameAsTyped = true; } } + // TODO: Share the implementation for checking typed word validity between the IME + // and the spell checker. + final int flag = (sameAsTyped && !suggestedWords.mTypedWordValid) + ? ((int)OBJ_FLAG_EASY_CORRECT | (int)OBJ_FLAG_MISSPELLED) + : 0; final Object[] args = - { context, null, suggestionsList.toArray(new String[suggestionsList.size()]), 0, + { context, null, suggestionsList.toArray(new String[suggestionsList.size()]), flag, (Class<?>) SuggestionSpanPickedNotificationReceiver.class }; final Object ss = CompatUtils.newInstance(CONSTRUCTOR_SuggestionSpan, args); if (ss == null) { diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 962379016..bc48b85ef 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -278,6 +278,7 @@ public class Keyboard { } } + // TODO: Remove this method. public void setEnabled(boolean enabled) { mEnabled = enabled; } @@ -616,29 +617,10 @@ public class Keyboard { mParams = params; - setTouchPositionCorrectionData(context, params); - params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width); params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height); } - private static void setTouchPositionCorrectionData(Context context, Params params) { - final TypedArray a = context.obtainStyledAttributes( - null, R.styleable.Keyboard, R.attr.keyboardStyle, 0); - params.mThemeId = a.getInt(R.styleable.Keyboard_themeId, 0); - final int resourceId = a.getResourceId( - R.styleable.Keyboard_touchPositionCorrectionData, 0); - a.recycle(); - if (resourceId == 0) { - if (LatinImeLogger.sDBG) - Log.e(BUILDER_TAG, "touchPositionCorrectionData is not defined"); - return; - } - - final String[] data = context.getResources().getStringArray(resourceId); - params.mTouchPositionCorrection.load(data); - } - public void setAutoGenerate(KeyboardSet.KeysCache keysCache) { mParams.mKeysCache = keysCache; } @@ -660,6 +642,7 @@ public class Keyboard { return this; } + // TODO: Remove this method. public void setTouchPositionCorrectionEnabled(boolean enabled) { mParams.mTouchPositionCorrection.setEnabled(enabled); } @@ -771,6 +754,15 @@ public class Keyboard { R.styleable.Keyboard_Key_maxMoreKeysColumn, 5); params.mIconsSet.loadIcons(keyboardAttr); + + params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0); + final int resourceId = keyboardAttr.getResourceId( + R.styleable.Keyboard_touchPositionCorrectionData, 0); + params.mTouchPositionCorrection.setEnabled(resourceId != 0); + if (resourceId != 0) { + final String[] data = mResources.getStringArray(resourceId); + params.mTouchPositionCorrection.load(data); + } } finally { keyAttr.recycle(); keyboardAttr.recycle(); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java index 52096c843..bb11a9b77 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -63,8 +63,6 @@ public class KeyboardSet { new HashMap<KeyboardId, SoftReference<Keyboard>>(); private static final KeysCache sKeysCache = new KeysCache(); - private static final EditorInfo EMPTY_EDITOR_INFO = new EditorInfo(); - public static class KeyboardSetException extends RuntimeException { public final KeyboardId mKeyboardId; public KeyboardSetException(Throwable cause, KeyboardId keyboardId) { @@ -209,6 +207,8 @@ public class KeyboardSet { private final Params mParams = new Params(); + private static final EditorInfo EMPTY_EDITOR_INFO = new EditorInfo(); + public Builder(Context context, EditorInfo editorInfo) { mContext = context; mPackageName = context.getPackageName(); @@ -229,15 +229,13 @@ public class KeyboardSet { } // TODO: Use InputMethodSubtype object as argument. - public Builder setSubtype(Locale inputLocale, boolean asciiCapable, - boolean touchPositionCorrectionEnabled) { + public Builder setSubtype(Locale inputLocale, boolean asciiCapable) { final boolean deprecatedForceAscii = StringUtils.inPrivateImeOptions( mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo); final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii( mParams.mEditorInfo.imeOptions) || deprecatedForceAscii; mParams.mLocale = (forceAscii && !asciiCapable) ? Locale.US : inputLocale; - mParams.mTouchPositionCorrectionEnabled = touchPositionCorrectionEnabled; return this; } @@ -255,6 +253,10 @@ public class KeyboardSet { return this; } + public void setTouchPositionCorrectionEnabled(boolean enabled) { + mParams.mTouchPositionCorrectionEnabled = enabled; + } + public KeyboardSet build() { if (mParams.mOrientation == Configuration.ORIENTATION_UNDEFINED) throw new RuntimeException("Screen geometry is not specified"); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 42dd6206c..93d8704de 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -140,9 +140,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions { builder.setSubtype( mSubtypeSwitcher.getInputLocale(), mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( - LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE), - mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( - LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION)); + LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE)); builder.setOptions( settingsValues.isVoiceKeyEnabled(editorInfo), settingsValues.isVoiceKeyOnMain(), diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 24eb7592b..c1d11a086 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -124,6 +124,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { /** The canvas for the above mutable keyboard bitmap */ private Canvas mCanvas; private final Paint mPaint = new Paint(); + private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics(); // This map caches key label text height in pixel as value and key label text size as map key. private static final HashMap<Integer, Float> sTextHeightCache = new HashMap<Integer, Float>(); @@ -659,13 +660,14 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // The hint label is placed at top-right corner of the key. Used mainly on tablet. hintX = keyWidth - params.mKeyShiftedLetterHintPadding - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2; - hintY = -paint.ascent(); + paint.getFontMetrics(mFontMetrics); + hintY = -mFontMetrics.top + params.mKeyShiftedLetterHintPadding; paint.setTextAlign(Align.CENTER); } else { // key.hasHintLetter() // The hint label is placed at top-right corner of the key. Used mainly on phone. hintX = keyWidth - params.mKeyHintLetterPadding - getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint) / 2; - hintY = -paint.ascent(); + hintY = -paint.ascent() + params.mKeyHintLetterPadding; paint.setTextAlign(Align.CENTER); } canvas.drawText(hint, 0, hint.length(), hintX, hintY, paint); diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 3f6c37477..7194cced3 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -52,6 +52,7 @@ import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.SubtypeUtils; import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils; +import com.android.inputmethod.latin.define.ProductionFlag; import java.util.Locale; import java.util.WeakHashMap; @@ -694,15 +695,17 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke + size + "," + pressure); } } - if (ResearchLogger.sIsLogging) { - // TODO: remove redundant calculations of size and pressure by - // removing UsabilityStudyLog code once the ResearchLogger is mature enough - final float size = me.getSize(index); - final float pressure = me.getPressure(index); - if (action != MotionEvent.ACTION_MOVE) { - // Skip ACTION_MOVE events as they are logged below - ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, - y, size, pressure); + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.sIsLogging) { + // TODO: remove redundant calculations of size and pressure by + // removing UsabilityStudyLog code once the ResearchLogger is mature enough + final float size = me.getSize(index); + final float pressure = me.getPressure(index); + if (action != MotionEvent.ACTION_MOVE) { + // Skip ACTION_MOVE events as they are logged below + ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, y, + size, pressure); + } } } @@ -770,12 +773,14 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke + pointerId + "," + px + "," + py + "," + pointerSize + "," + pointerPressure); } - if (ResearchLogger.sIsLogging) { - // TODO: earlier comment about redundant calculations applies here too - final float pointerSize = me.getSize(i); - final float pointerPressure = me.getPressure(i); - ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId, - px, py, pointerSize, pointerPressure); + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.sIsLogging) { + // TODO: earlier comment about redundant calculations applies here too + final float pointerSize = me.getSize(i); + final float pointerPressure = me.getPressure(i); + ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId, + px, py, pointerSize, pointerPressure); + } } } } else { diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index a9df1ce12..c43683f2d 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -40,14 +40,13 @@ public class BinaryDictionary extends Dictionary { public static final int MAX_WORDS = 18; private static final String TAG = "BinaryDictionary"; - private static final int MAX_PROXIMITY_CHARS_SIZE = ProximityInfo.MAX_PROXIMITY_CHARS_SIZE; private static final int MAX_BIGRAMS = 60; private static final int TYPED_LETTER_MULTIPLIER = 2; private int mDicTypeId; private long mNativeDict; - private final int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_PROXIMITY_CHARS_SIZE]; + private final int[] mInputCodes = new int[MAX_WORD_LENGTH]; private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS]; private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS]; private final int[] mScores = new int[MAX_WORDS]; @@ -111,8 +110,7 @@ public class BinaryDictionary extends Dictionary { } private native long openNative(String sourceDir, long dictOffset, long dictSize, - int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, - int maxWords, int maxAlternatives); + int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords); private native void closeNative(long dict); private native boolean isValidWordNative(long dict, char[] word, int wordLength); private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates, @@ -120,7 +118,7 @@ public class BinaryDictionary extends Dictionary { int[] scores); private native int getBigramsNative(long dict, char[] prevWord, int prevWordLength, int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores, - int maxWordLength, int maxBigrams, int maxAlternatives); + int maxWordLength, int maxBigrams); private static native double calcNormalizedScoreNative( char[] before, int beforeLength, char[] after, int afterLength, int score); private static native int editDistanceNative( @@ -128,8 +126,7 @@ public class BinaryDictionary extends Dictionary { private final void loadDictionary(String path, long startOffset, long length) { mNativeDict = openNative(path, startOffset, length, - TYPED_LETTER_MULTIPLIER, FULL_WORD_SCORE_MULTIPLIER, - MAX_WORD_LENGTH, MAX_WORDS, MAX_PROXIMITY_CHARS_SIZE); + TYPED_LETTER_MULTIPLIER, FULL_WORD_SCORE_MULTIPLIER, MAX_WORD_LENGTH, MAX_WORDS); } @Override @@ -144,14 +141,11 @@ public class BinaryDictionary extends Dictionary { int codesSize = codes.size(); Arrays.fill(mInputCodes, -1); if (codesSize > 0) { - int[] alternatives = codes.getCodesAt(0); - System.arraycopy(alternatives, 0, mInputCodes, 0, - Math.min(alternatives.length, MAX_PROXIMITY_CHARS_SIZE)); + mInputCodes[0] = codes.getCodeAt(0); } int count = getBigramsNative(mNativeDict, chars, chars.length, mInputCodes, codesSize, - mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS, - MAX_PROXIMITY_CHARS_SIZE); + mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS); if (count > MAX_BIGRAMS) { count = MAX_BIGRAMS; } @@ -205,11 +199,7 @@ public class BinaryDictionary extends Dictionary { Arrays.fill(mInputCodes, WordComposer.NOT_A_CODE); for (int i = 0; i < codesSize; i++) { - final int[] alternatives = codes.getCodesAt(i); - if (alternatives == null || alternatives.length < 1) { - continue; - } - mInputCodes[i] = alternatives[0]; + mInputCodes[i] = codes.getCodeAt(i); } Arrays.fill(outputChars, (char) 0); Arrays.fill(scores, 0); diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index 8e8adc1c2..098913bef 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -28,17 +28,12 @@ import java.util.LinkedList; * be searched for suggestions and valid words. */ public class ExpandableDictionary extends Dictionary { - /** - * There is difference between what java and native code can handle. - * It uses 32 because Java stack overflows when greater value is used. - */ - protected static final int MAX_WORD_LENGTH = 32; // Bigram frequency is a fixed point number with 1 meaning 1.2 and 255 meaning 1.8. protected static final int BIGRAM_MAX_FREQUENCY = 255; private Context mContext; - private char[] mWordBuilder = new char[MAX_WORD_LENGTH]; + private char[] mWordBuilder = new char[BinaryDictionary.MAX_WORD_LENGTH]; private int mDicTypeId; private int mMaxDepth; private int mInputLength; @@ -113,7 +108,7 @@ public class ExpandableDictionary extends Dictionary { public ExpandableDictionary(Context context, int dicTypeId) { mContext = context; clearDictionary(); - mCodes = new int[MAX_WORD_LENGTH][]; + mCodes = new int[BinaryDictionary.MAX_WORD_LENGTH][]; mDicTypeId = dicTypeId; } @@ -151,10 +146,13 @@ public class ExpandableDictionary extends Dictionary { } public int getMaxWordLength() { - return MAX_WORD_LENGTH; + return BinaryDictionary.MAX_WORD_LENGTH; } public void addWord(String word, int frequency) { + if (word.length() >= BinaryDictionary.MAX_WORD_LENGTH) { + return; + } addWordRec(mRoots, word, 0, frequency, null); } @@ -201,6 +199,9 @@ public class ExpandableDictionary extends Dictionary { // Currently updating contacts, don't return any results. if (mUpdatingDictionary) return; } + if (codes.size() >= BinaryDictionary.MAX_WORD_LENGTH) { + return; + } getWordsInner(codes, callback, proximityInfo); } @@ -210,7 +211,11 @@ public class ExpandableDictionary extends Dictionary { if (mCodes.length < mInputLength) mCodes = new int[mInputLength][]; // Cache the codes so that we don't have to lookup an array list for (int i = 0; i < mInputLength; i++) { - mCodes[i] = codes.getCodesAt(i); + // TODO: Calculate proximity info here. + if (mCodes[i] == null || mCodes[i].length < 1) { + mCodes[i] = new int[1]; + } + mCodes[i][0] = codes.getCodeAt(i); } mMaxDepth = mInputLength * 3; getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, callback); @@ -319,7 +324,7 @@ public class ExpandableDictionary extends Dictionary { } } else { // Don't use alternatives if we're looking for missing characters - final int alternativesSize = skipPos >= 0? 1 : currentChars.length; + final int alternativesSize = skipPos >= 0 ? 1 : currentChars.length; for (int j = 0; j < alternativesSize; j++) { final int addedAttenuation = (j > 0 ? 1 : 2); final int currentChar = currentChars[j]; @@ -484,7 +489,7 @@ public class ExpandableDictionary extends Dictionary { } // Local to reverseLookUp, but do not allocate each time. - private final char[] mLookedUpString = new char[MAX_WORD_LENGTH]; + private final char[] mLookedUpString = new char[BinaryDictionary.MAX_WORD_LENGTH]; /** * reverseLookUp retrieves the full word given a list of terminal nodes and adds those words @@ -498,15 +503,15 @@ public class ExpandableDictionary extends Dictionary { for (NextWord nextWord : terminalNodes) { node = nextWord.mWord; freq = nextWord.getFrequency(); - int index = MAX_WORD_LENGTH; + int index = BinaryDictionary.MAX_WORD_LENGTH; do { --index; mLookedUpString[index] = node.mCode; node = node.mParent; } while (node != null); - callback.addWord(mLookedUpString, index, MAX_WORD_LENGTH - index, freq, mDicTypeId, - Dictionary.BIGRAM); + callback.addWord(mLookedUpString, index, BinaryDictionary.MAX_WORD_LENGTH - index, + freq, mDicTypeId, Dictionary.BIGRAM); } } diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java index bc0792434..af0ef4b37 100644 --- a/java/src/com/android/inputmethod/latin/LastComposedWord.java +++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java @@ -18,8 +18,6 @@ package com.android.inputmethod.latin; import android.text.TextUtils; -import java.util.ArrayList; - /** * This class encapsulates data about a word previously composed, but that has been * committed already. This is used for resuming suggestion, and cancel auto-correction. @@ -42,7 +40,7 @@ public class LastComposedWord { public static final int NOT_A_SEPARATOR = -1; - public final ArrayList<int[]> mCodes; + public final int[] mPrimaryKeyCodes; public final int[] mXCoordinates; public final int[] mYCoordinates; public final String mTypedWord; @@ -56,10 +54,10 @@ public class LastComposedWord { // Warning: this is using the passed objects as is and fully expects them to be // immutable. Do not fiddle with their contents after you passed them to this constructor. - public LastComposedWord(final ArrayList<int[]> codes, final int[] xCoordinates, + public LastComposedWord(final int[] primaryKeyCodes, final int[] xCoordinates, final int[] yCoordinates, final String typedWord, final String committedWord, final int separatorCode) { - mCodes = codes; + mPrimaryKeyCodes = primaryKeyCodes; mXCoordinates = xCoordinates; mYCoordinates = yCoordinates; mTypedWord = typedWord; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 7272006a2..86c153958 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -69,6 +69,7 @@ import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; import com.android.inputmethod.keyboard.LatinKeyboardView; import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils; +import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.suggestions.SuggestionsView; import java.io.FileDescriptor; @@ -124,12 +125,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar public static final String SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable"; /** - * The subtype extra value used to indicate that the subtype keyboard layout supports touch - * position correction. - */ - public static final String SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION = - "SupportTouchPositionCorrection"; - /** * The subtype extra value used to indicate that the subtype keyboard layout should be loaded * from the specified locale. */ @@ -439,7 +434,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); mPrefs = prefs; LatinImeLogger.init(this, prefs); - ResearchLogger.init(this, prefs); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.init(this, prefs); + } LanguageSwitcherProxy.init(this, prefs); InputMethodManagerCompatWrapper.init(this); SubtypeSwitcher.init(this); @@ -1264,8 +1261,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } mLastKeyTime = when; - if (ResearchLogger.sIsLogging) { - ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y); + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.sIsLogging) { + ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y); + } } final KeyboardSwitcher switcher = mKeyboardSwitcher; diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index 079f3b5dd..732efadd6 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -80,8 +80,4 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang public static void onPrintAllUsabilityStudyLogs() { } - - public static boolean isResearcherPackage(Context context) { - return false; - } } diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 3b110bd78..0694ffe77 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -41,7 +41,7 @@ import java.util.Date; * This class logs operations on the IME keyboard, including what the user has typed. * Data is stored locally in a file in app-specific storage. * - * This functionality is off by default. + * This functionality is off by default. See {@link ProductionFlag.IS_EXPERIMENTAL}. */ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 72391f31e..110264892 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -46,6 +46,7 @@ import com.android.inputmethod.compat.CompatUtils; import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; import com.android.inputmethod.compat.VibratorCompatWrapper; import com.android.inputmethod.deprecated.VoiceProxy; +import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethodcommon.InputMethodSettingsActivity; import java.util.Locale; @@ -238,17 +239,16 @@ public class Settings extends InputMethodSettingsActivity textCorrectionGroup.removePreference(dictionaryLink); } - final boolean isResearcherPackage = LatinImeLogger.isResearcherPackage(this); final boolean showUsabilityStudyModeOption = res.getBoolean(R.bool.config_enable_usability_study_mode_option) - || isResearcherPackage || ENABLE_EXPERIMENTAL_SETTINGS; + || ProductionFlag.IS_EXPERIMENTAL || ENABLE_EXPERIMENTAL_SETTINGS; final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE); if (!showUsabilityStudyModeOption) { if (usabilityStudyPref != null) { miscSettings.removePreference(usabilityStudyPref); } } - if (isResearcherPackage) { + if (ProductionFlag.IS_EXPERIMENTAL) { if (usabilityStudyPref instanceof CheckBoxPreference) { CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref; checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE, true)); diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java index db2cdf967..62525c205 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java @@ -247,8 +247,8 @@ public class UserHistoryDictionary extends ExpandableDictionary { // to recursive lookup if (null == word1) { super.addWord(word2, frequency); - } else if (word1.length() < MAX_WORD_LENGTH - && word2.length() < MAX_WORD_LENGTH) { + } else if (word1.length() < BinaryDictionary.MAX_WORD_LENGTH + && word2.length() < BinaryDictionary.MAX_WORD_LENGTH) { super.setBigram(word1, word2, frequency); } cursor.moveToNext(); diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index be64c2fd8..0485c881b 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -31,9 +31,7 @@ import android.os.Process; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; -import android.view.MotionEvent; -import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.io.BufferedReader; @@ -112,7 +110,6 @@ public class Utils { /* package */ static final int BUFSIZE = 20; private InputMethodService mContext; private boolean mEnabled = false; - private boolean mUsabilityStudy = false; private int mEnd = 0; /* package */ int mLength = 0; private char[] mCharBuf = new char[BUFSIZE]; @@ -129,7 +126,6 @@ public class Utils { boolean usabilityStudy) { sRingCharBuffer.mContext = context; sRingCharBuffer.mEnabled = enabled || usabilityStudy; - sRingCharBuffer.mUsabilityStudy = usabilityStudy; UsabilityStudyLogUtils.getInstance().init(context); return sRingCharBuffer; } diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index cabf68099..555a49ef4 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -21,7 +21,6 @@ import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; -import java.util.ArrayList; import java.util.Arrays; /** @@ -32,9 +31,9 @@ public class WordComposer { public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE; public static final int NOT_A_COORDINATE = -1; - final static int N = BinaryDictionary.MAX_WORD_LENGTH; + private static final int N = BinaryDictionary.MAX_WORD_LENGTH; - private ArrayList<int[]> mCodes; + private int[] mPrimaryKeyCodes; private int[] mXCoordinates; private int[] mYCoordinates; private StringBuilder mTypedWord; @@ -44,6 +43,7 @@ public class WordComposer { private int mCapsCount; private boolean mAutoCapitalized; private int mTrailingSingleQuotesCount; + private int mCodePointSize; /** * Whether the user chose to capitalize the first char of the word. @@ -51,12 +51,13 @@ public class WordComposer { private boolean mIsFirstCharCapitalized; public WordComposer() { - mCodes = new ArrayList<int[]>(N); + mPrimaryKeyCodes = new int[N]; mTypedWord = new StringBuilder(N); mXCoordinates = new int[N]; mYCoordinates = new int[N]; mAutoCorrection = null; mTrailingSingleQuotesCount = 0; + refreshSize(); } public WordComposer(WordComposer source) { @@ -64,7 +65,7 @@ public class WordComposer { } public void init(WordComposer source) { - mCodes = new ArrayList<int[]>(source.mCodes); + mPrimaryKeyCodes = Arrays.copyOf(source.mPrimaryKeyCodes, source.mPrimaryKeyCodes.length); mTypedWord = new StringBuilder(source.mTypedWord); mXCoordinates = Arrays.copyOf(source.mXCoordinates, source.mXCoordinates.length); mYCoordinates = Arrays.copyOf(source.mYCoordinates, source.mYCoordinates.length); @@ -72,18 +73,23 @@ public class WordComposer { mIsFirstCharCapitalized = source.mIsFirstCharCapitalized; mAutoCapitalized = source.mAutoCapitalized; mTrailingSingleQuotesCount = source.mTrailingSingleQuotesCount; + refreshSize(); } /** * Clear out the keys registered so far. */ public void reset() { - mCodes.clear(); mTypedWord.setLength(0); mAutoCorrection = null; mCapsCount = 0; mIsFirstCharCapitalized = false; mTrailingSingleQuotesCount = 0; + refreshSize(); + } + + public final void refreshSize() { + mCodePointSize = mTypedWord.codePointCount(0, mTypedWord.length()); } /** @@ -91,20 +97,19 @@ public class WordComposer { * @return the number of keystrokes */ public final int size() { - return mCodes.size(); + return mCodePointSize; } public final boolean isComposingWord() { - return mCodes.size() > 0; + return size() > 0; } - /** - * Returns the codes at a particular position in the word. - * @param index the position in the word - * @return the unicode for the pressed and surrounding keys - */ - public int[] getCodesAt(int index) { - return mCodes.get(index); + // TODO: make sure that the index should not exceed MAX_WORD_LENGTH + public int getCodeAt(int index) { + if (index >= BinaryDictionary.MAX_WORD_LENGTH) { + return -1; + } + return mPrimaryKeyCodes[index]; } public int[] getXCoordinates() { @@ -122,7 +127,6 @@ public class WordComposer { // TODO: remove input keyDetector public void add(int primaryCode, int x, int y, KeyDetector keyDetector) { - final int[] codes; final int keyX; final int keyY; if (null == keyDetector @@ -130,17 +134,13 @@ public class WordComposer { || y == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE || x == KeyboardActionListener.NOT_A_TOUCH_COORDINATE || y == KeyboardActionListener.NOT_A_TOUCH_COORDINATE) { - codes = new int[] { primaryCode }; keyX = x; keyY = y; } else { - final Key key = keyDetector.detectHitKey(x, y); - // TODO: Pass an integer instead of an integer array - codes = new int[] { key != null ? key.mCode : NOT_A_CODE }; keyX = keyDetector.getTouchX(x); keyY = keyDetector.getTouchY(y); } - add(primaryCode, codes, keyX, keyY); + add(primaryCode, keyX, keyY); } /** @@ -148,11 +148,13 @@ public class WordComposer { * the array containing unicode for adjacent keys, sorted by reducing probability/proximity. * @param codes the array of unicode values */ - private void add(int primaryCode, int[] codes, int keyX, int keyY) { - final int newIndex = mCodes.size(); + private void add(int primaryCode, int keyX, int keyY) { + final int newIndex = size(); mTypedWord.appendCodePoint(primaryCode); - mCodes.add(codes); + refreshSize(); if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) { + mPrimaryKeyCodes[newIndex] = primaryCode >= Keyboard.CODE_SPACE + ? Character.toLowerCase(primaryCode) : primaryCode; mXCoordinates[newIndex] = keyX; mYCoordinates[newIndex] = keyY; } @@ -175,13 +177,11 @@ public class WordComposer { if (key.mCode == codePoint) { final int x = key.mX + key.mWidth / 2; final int y = key.mY + key.mHeight / 2; - // TODO: Pass an integer instead of an integer array - add(codePoint, new int[] { key.mCode }, x, y); + add(codePoint, x, y); return; } } - add(codePoint, new int[] { codePoint }, - WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); + add(codePoint, WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); } /** @@ -201,9 +201,8 @@ public class WordComposer { * Delete the last keystroke as a result of hitting backspace. */ public void deleteLast() { - final int size = mCodes.size(); + final int size = size(); if (size > 0) { - mCodes.remove(size - 1); // Note: mTypedWord.length() and mCodes.length differ when there are surrogate pairs final int stringBuilderLength = mTypedWord.length(); if (stringBuilderLength < size) { @@ -217,9 +216,10 @@ public class WordComposer { mTypedWord.deleteCharAt(stringBuilderLength - 1); } if (Character.isUpperCase(lastChar)) mCapsCount--; + refreshSize(); } // We may have deleted the last one. - if (0 == mCodes.size()) { + if (0 == size()) { mIsFirstCharCapitalized = false; } if (mTrailingSingleQuotesCount > 0) { @@ -307,29 +307,31 @@ public class WordComposer { // Note: currently, we come here whenever we commit a word. If it's a MANUAL_PICK // or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate // the last composed word to ensure this does not happen. - final ArrayList<int[]> codes = mCodes; + final int[] primaryKeyCodes = mPrimaryKeyCodes; final int[] xCoordinates = mXCoordinates; final int[] yCoordinates = mYCoordinates; - mCodes = new ArrayList<int[]>(N); + mPrimaryKeyCodes = new int[N]; mXCoordinates = new int[N]; mYCoordinates = new int[N]; - final LastComposedWord lastComposedWord = new LastComposedWord(codes, + final LastComposedWord lastComposedWord = new LastComposedWord(primaryKeyCodes, xCoordinates, yCoordinates, mTypedWord.toString(), committedWord, separatorCode); if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD && type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) { lastComposedWord.deactivate(); } mTypedWord.setLength(0); + refreshSize(); mAutoCorrection = null; return lastComposedWord; } public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) { - mCodes = lastComposedWord.mCodes; + mPrimaryKeyCodes = lastComposedWord.mPrimaryKeyCodes; mXCoordinates = lastComposedWord.mXCoordinates; mYCoordinates = lastComposedWord.mYCoordinates; mTypedWord.setLength(0); mTypedWord.append(lastComposedWord.mTypedWord); + refreshSize(); mAutoCorrection = null; // This will be filled by the next call to updateSuggestion. } } diff --git a/java/src/com/android/inputmethod/latin/define/JniLibName.java b/java/src/com/android/inputmethod/latin/define/JniLibName.java index 3e94a3c07..e23e1a968 100644 --- a/java/src/com/android/inputmethod/latin/define/JniLibName.java +++ b/java/src/com/android/inputmethod/latin/define/JniLibName.java @@ -16,6 +16,10 @@ package com.android.inputmethod.latin.define; -public class JniLibName { +public final class JniLibName { + private JniLibName() { + // This class is not publicly instantiable. + } + public static final String JNI_LIB_NAME = "jni_latinime"; } diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java index cfb1d09cc..de2057669 100644 --- a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java +++ b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java @@ -16,6 +16,10 @@ package com.android.inputmethod.latin.define; -public class ProductionFlag { +public final class ProductionFlag { + private ProductionFlag() { + // This class is not publicly instantiable. + } + public static final boolean IS_EXPERIMENTAL = false; } |