Add a safety net for auto-correction.

Bug: 3353956

Change-Id: I6a32632b2f986f0d9a07aa72f256a2c41cc09873
This commit is contained in:
satok 2011-01-18 17:22:01 +09:00
parent 08ca36d038
commit 82411d47ba
4 changed files with 58 additions and 20 deletions

View file

@ -45,23 +45,22 @@ import android.widget.TextView;
import java.util.ArrayList;
public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener {
private LatinIME mService;
private final ArrayList<View> mWords = new ArrayList<View>();
private final TextView mPreviewText;
private final PopupWindow mPreviewPopup;
private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
private static final int MAX_SUGGESTIONS = 16;
private final ArrayList<View> mWords = new ArrayList<View>();
private final boolean mConfigCandidateHighlightFontColorEnabled;
private final CharacterStyle mInvertedForegroundColorSpan;
private final CharacterStyle mInvertedBackgroundColorSpan;
private final int mColorNormal;
private final int mColorRecommended;
private final int mColorOther;
private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
private final CharacterStyle mInvertedForegroundColorSpan;
private final CharacterStyle mInvertedBackgroundColorSpan;
private final PopupWindow mPreviewPopup;
private final TextView mPreviewText;
private LatinIME mService;
private SuggestedWords mSuggestions = SuggestedWords.EMPTY;
private boolean mShowingAutoCorrectionInverted;
private boolean mShowingAddToDictionary;
@ -186,9 +185,10 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
final TextView tv = (TextView)v.findViewById(R.id.candidate_word);
final TextView dv = (TextView)v.findViewById(R.id.candidate_debug_info);
tv.setTextColor(mColorNormal);
// TODO: Needs safety net?
if (suggestions.mHasMinimalSuggestion
&& ((i == 1 && !suggestions.mTypedWordValid) ||
(i == 0 && suggestions.mTypedWordValid))) {
&& ((i == 1 && !suggestions.mTypedWordValid)
|| (i == 0 && suggestions.mTypedWordValid))) {
final CharacterStyle style;
if (mConfigCandidateHighlightFontColorEnabled) {
style = BOLD_SPAN;

View file

@ -1537,7 +1537,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) {
setSuggestions(suggestedWords);
if (suggestedWords.size() > 0) {
if (suggestedWords.hasAutoCorrectionWord()) {
if (Utils.shouldBlockedBySafetyNetForAutoCorrection(suggestedWords)) {
mBestWord = typedWord;
} else if (suggestedWords.hasAutoCorrectionWord()) {
mBestWord = suggestedWords.getWord(1);
} else {
mBestWord = typedWord;

View file

@ -31,7 +31,7 @@ import java.util.Arrays;
*/
public class Suggest implements Dictionary.WordCallback {
public static final String TAG = "Suggest";
public static final String TAG = Suggest.class.getSimpleName();
public static final int APPROX_MAX_WORD_LENGTH = 32;
@ -64,6 +64,8 @@ public class Suggest implements Dictionary.WordCallback {
static final int LARGE_DICTIONARY_THRESHOLD = 200 * 1000;
private static boolean DBG = LatinImeLogger.sDBG;
private BinaryDictionary mMainDict;
private Dictionary mUserDictionary;
@ -93,7 +95,7 @@ public class Suggest implements Dictionary.WordCallback {
private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>();
private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>();
private boolean mHaveCorrection;
private boolean mHaveAutoCorrection;
private String mLowerOriginalWord;
// TODO: Remove these member variables by passing more context to addWord() callback method
@ -198,7 +200,7 @@ public class Suggest implements Dictionary.WordCallback {
public SuggestedWords.Builder getSuggestedWordBuilder(View view, WordComposer wordComposer,
CharSequence prevWordForBigram) {
LatinImeLogger.onStartSuggestion(prevWordForBigram);
mHaveCorrection = false;
mHaveAutoCorrection = false;
mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
mIsAllUpperCase = wordComposer.isAllUpperCase();
collectGarbage(mSuggestions, mPrefMaxSuggestions);
@ -273,7 +275,10 @@ public class Suggest implements Dictionary.WordCallback {
if (mSuggestions.size() > 0 && isValidWord(typedWord)
&& (mCorrectionMode == CORRECTION_FULL
|| mCorrectionMode == CORRECTION_FULL_BIGRAM)) {
mHaveCorrection = true;
if (DBG) {
Log.d(TAG, "Auto corrected by CORRECTION_FULL.");
}
mHaveAutoCorrection = true;
}
}
if (mMainDict != null) mMainDict.getWords(wordComposer, this, mNextLettersFrequencies);
@ -289,7 +294,10 @@ public class Suggest implements Dictionary.WordCallback {
+ "(" + mAutoCorrectionThreshold + ")");
}
if (normalizedScore >= mAutoCorrectionThreshold) {
mHaveCorrection = true;
if (DBG) {
Log.d(TAG, "Auto corrected by S-threthhold.");
}
mHaveAutoCorrection = true;
}
}
}
@ -331,7 +339,10 @@ public class Suggest implements Dictionary.WordCallback {
canAdd &= !TextUtils.equals(autoText, mSuggestions.get(i + 1));
}
if (canAdd) {
mHaveCorrection = true;
if (DBG) {
Log.d(TAG, "Auto corrected by AUTOTEXT.");
}
mHaveAutoCorrection = true;
mSuggestions.add(i + 1, autoText);
i++;
}
@ -374,7 +385,7 @@ public class Suggest implements Dictionary.WordCallback {
}
public boolean hasMinimalCorrection() {
return mHaveCorrection;
return mHaveAutoCorrection;
}
private boolean compareCaseInsensitive(final String mLowerOriginalWord,

View file

@ -36,6 +36,8 @@ import java.text.SimpleDateFormat;
import java.util.Date;
public class Utils {
private static final String TAG = Utils.class.getSimpleName();
private static boolean DBG = LatinImeLogger.sDBG;
/**
* Cancel an {@link AsyncTask}.
@ -95,6 +97,29 @@ public class Utils {
|| imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
}
public static boolean shouldBlockedBySafetyNetForAutoCorrection(SuggestedWords suggestions) {
// Safety net for auto correction.
// Actually if we hit this safety net, it's actually a bug.
if (suggestions.size() <= 1 || suggestions.mTypedWordValid) return false;
CharSequence typedWord = suggestions.getWord(0);
CharSequence candidateWord = suggestions.getWord(1);
final int typedWordLength = typedWord.length();
final int maxEditDistanceOfNativeDictionary = typedWordLength < 5 ? 2 : typedWordLength / 2;
final int distance = Utils.editDistance(typedWord, candidateWord);
if (DBG) {
Log.d(TAG, "Autocorrected edit distance = " + distance
+ ", " + maxEditDistanceOfNativeDictionary);
}
if (distance > maxEditDistanceOfNativeDictionary) {
Log.w(TAG, "(Error) The edit distance of this correction exceeds limit. "
+ "Turning off auto-correction.");
return true;
} else {
return false;
}
}
/* package */ static class RingCharBuffer {
private static RingCharBuffer sRingCharBuffer = new RingCharBuffer();
private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC';