aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java26
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java1
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java7
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java5
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java11
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsFragment.java31
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsValues.java2
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeLocale.java43
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java3
-rw-r--r--java/src/com/android/inputmethod/research/FixedLogBuffer.java5
-rw-r--r--java/src/com/android/inputmethod/research/LogUnit.java94
-rw-r--r--java/src/com/android/inputmethod/research/MainLogBuffer.java27
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLogger.java19
13 files changed, 211 insertions, 63 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 28a22f35c..cf89ef210 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -65,6 +65,7 @@ import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.ResourceUtils;
+import com.android.inputmethod.latin.Settings;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
import com.android.inputmethod.latin.StringUtils;
import com.android.inputmethod.latin.SubtypeLocale;
@@ -205,8 +206,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
private final int mKeyRepeatStartTimeout;
private final int mKeyRepeatInterval;
- private final int mLongPressKeyTimeout;
- private final int mLongPressShiftKeyTimeout;
+ private final int mLongPressShiftLockTimeout;
private final int mIgnoreAltCodeKeyTimeout;
private final int mGestureRecognitionUpdateTime;
@@ -218,10 +218,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
R.styleable.MainKeyboardView_keyRepeatStartTimeout, 0);
mKeyRepeatInterval = mainKeyboardViewAttr.getInt(
R.styleable.MainKeyboardView_keyRepeatInterval, 0);
- mLongPressKeyTimeout = mainKeyboardViewAttr.getInt(
- R.styleable.MainKeyboardView_longPressKeyTimeout, 0);
- mLongPressShiftKeyTimeout = mainKeyboardViewAttr.getInt(
- R.styleable.MainKeyboardView_longPressShiftKeyTimeout, 0);
+ mLongPressShiftLockTimeout = mainKeyboardViewAttr.getInt(
+ R.styleable.MainKeyboardView_longPressShiftLockTimeout, 0);
mIgnoreAltCodeKeyTimeout = mainKeyboardViewAttr.getInt(
R.styleable.MainKeyboardView_ignoreAltCodeKeyTimeout, 0);
mGestureRecognitionUpdateTime = mainKeyboardViewAttr.getInt(
@@ -285,7 +283,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
final int delay;
switch (code) {
case Constants.CODE_SHIFT:
- delay = mLongPressShiftKeyTimeout;
+ delay = mLongPressShiftLockTimeout;
break;
default:
delay = 0;
@@ -306,15 +304,17 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
final int delay;
switch (key.mCode) {
case Constants.CODE_SHIFT:
- delay = mLongPressShiftKeyTimeout;
+ delay = mLongPressShiftLockTimeout;
break;
default:
+ final int longpressTimeout =
+ Settings.getInstance().getCurrent().mKeyLongpressTimeout;
if (KeyboardSwitcher.getInstance().isInMomentarySwitchState()) {
// We use longer timeout for sliding finger input started from the symbols
// mode key.
- delay = mLongPressKeyTimeout * 3;
+ delay = longpressTimeout * 3;
} else {
- delay = mLongPressKeyTimeout;
+ delay = longpressTimeout;
}
break;
}
@@ -1371,7 +1371,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
private String layoutLanguageOnSpacebar(final Paint paint, final InputMethodSubtype subtype,
final int width) {
// Choose appropriate language name to fit into the width.
- final String fullText = getFullDisplayName(subtype, getResources());
+ final String fullText = getFullDisplayName(subtype);
if (fitsTextIntoWidth(width, fullText, paint)) {
return fullText;
}
@@ -1445,12 +1445,12 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
// zz azerty T AZERTY AZERTY
// Get InputMethodSubtype's full display name in its locale.
- static String getFullDisplayName(final InputMethodSubtype subtype, final Resources res) {
+ static String getFullDisplayName(final InputMethodSubtype subtype) {
if (SubtypeLocale.isNoLanguage(subtype)) {
return SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype);
}
- return SubtypeLocale.getSubtypeDisplayName(subtype, res);
+ return SubtypeLocale.getSubtypeDisplayName(subtype);
}
// Get InputMethodSubtype's short display name in its locale.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java
index 0954a7a5d..28655a930 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java
@@ -157,6 +157,7 @@ public class GestureFloatingPreviewText extends AbstractDrawingPreview {
*/
protected void updatePreviewPosition() {
if (mSuggestedWords.isEmpty() || TextUtils.isEmpty(mSuggestedWords.getWord(0))) {
+ getDrawingView().invalidate();
return;
}
final String text = mSuggestedWords.getWord(0);
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
index 9e5e18353..a56c78bcd 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
@@ -103,7 +103,7 @@ public final class AdditionalSubtypeSettings extends PreferenceFragment {
if (DEBUG_SUBTYPE_ID) {
android.util.Log.d(TAG, String.format("%-6s 0x%08x %11d %s",
subtype.getLocale(), subtype.hashCode(), subtype.hashCode(),
- SubtypeLocale.getSubtypeDisplayName(subtype, context.getResources())));
+ SubtypeLocale.getSubtypeDisplayName(subtype)));
}
if (subtype.containsExtraValueKey(ASCII_CAPABLE)) {
items.add(createItem(context, subtype.getLocale()));
@@ -205,8 +205,7 @@ public final class AdditionalSubtypeSettings extends PreferenceFragment {
setDialogTitle(R.string.add_style);
setKey(KEY_NEW_SUBTYPE);
} else {
- final String displayName = SubtypeLocale.getSubtypeDisplayName(
- subtype, getContext().getResources());
+ final String displayName = SubtypeLocale.getSubtypeDisplayName(subtype);
setTitle(displayName);
setDialogTitle(displayName);
setKey(KEY_PREFIX + subtype.getLocale() + "_"
@@ -498,7 +497,7 @@ public final class AdditionalSubtypeSettings extends PreferenceFragment {
final Context context = getActivity();
final Resources res = context.getResources();
final String message = res.getString(R.string.custom_input_style_already_exists,
- SubtypeLocale.getSubtypeDisplayName(subtype, res));
+ SubtypeLocale.getSubtypeDisplayName(subtype));
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index fc9953ac0..70eb6e657 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1647,7 +1647,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mExpectingUpdateSelection = true;
mConnection.endBatchEdit();
if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_onEndBatchInput(batchInputText, 0);
+ ResearchLogger.latinIME_onEndBatchInput(batchInputText, 0, suggestedWords);
}
// Space state must be updated before calling updateShiftState
mSpaceState = SPACE_STATE_PHANTOM;
@@ -2123,8 +2123,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
Stats.onAutoCorrection(typedWord, autoCorrection, separatorString, mWordComposer);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
+ final SuggestedWords suggestedWords = mSuggestionStripView.getSuggestions();
ResearchLogger.latinIme_commitCurrentAutoCorrection(typedWord, autoCorrection,
- separatorString, mWordComposer.isBatchMode());
+ separatorString, mWordComposer.isBatchMode(), suggestedWords);
}
mExpectingUpdateSelection = true;
commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD,
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index aa705da56..408ea4a49 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -55,6 +55,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction";
public static final String PREF_GESTURE_SETTINGS = "gesture_typing_settings";
public static final String PREF_GESTURE_INPUT = "gesture_input";
+ public static final String PREF_KEY_LONGPRESS_TIMEOUT = "pref_key_longpress_timeout";
public static final String PREF_VIBRATION_DURATION_SETTINGS =
"pref_vibration_duration_settings";
public static final String PREF_KEYPRESS_SOUND_VOLUME =
@@ -175,6 +176,16 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
ResourceUtils.getDeviceOverrideValue(res, R.array.keypress_volumes));
}
+ public static int readKeyLongpressTimeout(final SharedPreferences prefs,
+ final Resources res) {
+ final int ms = prefs.getInt(PREF_KEY_LONGPRESS_TIMEOUT, -1);
+ return (ms >= 0) ? ms : readDefaultKeyLongpressTimeout(res);
+ }
+
+ public static int readDefaultKeyLongpressTimeout(final Resources res) {
+ return res.getInteger(R.integer.config_default_longpress_key_timeout);
+ }
+
public static int readKeypressVibrationDuration(final SharedPreferences prefs,
final Resources res) {
final int ms = prefs.getInt(PREF_VIBRATION_DURATION_SETTINGS, -1);
diff --git a/java/src/com/android/inputmethod/latin/SettingsFragment.java b/java/src/com/android/inputmethod/latin/SettingsFragment.java
index afe6f3594..3ba24fb65 100644
--- a/java/src/com/android/inputmethod/latin/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/SettingsFragment.java
@@ -164,6 +164,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment
getPreferenceScreen().removePreference(gestureTypingSettings);
}
+ setupKeyLongpressTimeoutSettings(prefs, res);
setupKeypressVibrationDurationSettings(prefs, res);
setupKeypressSoundVolumeSettings(prefs, res);
refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, res);
@@ -236,7 +237,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment
final StringBuilder styles = new StringBuilder();
for (final InputMethodSubtype subtype : subtypes) {
if (styles.length() > 0) styles.append(", ");
- styles.append(SubtypeLocale.getSubtypeDisplayName(subtype, res));
+ styles.append(SubtypeLocale.getSubtypeDisplayName(subtype));
}
customInputStyles.setSummary(styles);
}
@@ -298,6 +299,34 @@ public final class SettingsFragment extends InputMethodSettingsFragment
});
}
+ private void setupKeyLongpressTimeoutSettings(final SharedPreferences sp,
+ final Resources res) {
+ final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
+ Settings.PREF_KEY_LONGPRESS_TIMEOUT);
+ if (pref == null) {
+ return;
+ }
+ pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
+ @Override
+ public void writeValue(final int value, final String key) {
+ sp.edit().putInt(key, value).apply();
+ }
+
+ @Override
+ public int readValue(final String key) {
+ return Settings.readKeyLongpressTimeout(sp, res);
+ }
+
+ @Override
+ public int readDefaultValue(final String key) {
+ return Settings.readDefaultKeyLongpressTimeout(res);
+ }
+
+ @Override
+ public void feedbackValue(final int value) {}
+ });
+ }
+
private void setupKeypressSoundVolumeSettings(final SharedPreferences sp, final Resources res) {
final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
Settings.PREF_KEYPRESS_SOUND_VOLUME);
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index d6556d617..29e79e4cc 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -59,6 +59,7 @@ public final class SettingsValues {
public final boolean mGestureInputEnabled;
public final boolean mGesturePreviewTrailEnabled;
public final boolean mGestureFloatingPreviewTextEnabled;
+ public final int mKeyLongpressTimeout;
// From the input box
public final InputAttributes mInputAttributes;
@@ -121,6 +122,7 @@ public final class SettingsValues {
mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res);
// Compute other readable settings
+ mKeyLongpressTimeout = Settings.readKeyLongpressTimeout(prefs, res);
mKeypressVibrationDuration = Settings.readKeypressVibrationDuration(prefs, res);
mKeypressSoundVolume = Settings.readKeypressSoundVolume(prefs, res);
mKeyPreviewPopupDismissDelay = Settings.readKeyPreviewPopupDismissDelay(prefs, res);
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index 370a6594b..068c34ed6 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -42,6 +42,7 @@ public final class SubtypeLocale {
public static final int UNKNOWN_KEYBOARD_LAYOUT = R.string.subtype_generic;
private static boolean sInitialized = false;
+ private static Resources sResources;
private static String[] sPredefinedKeyboardLayoutSet;
// Keyboard layout to its display name map.
private static final HashMap<String, String> sKeyboardLayoutToDisplayNameMap =
@@ -71,10 +72,11 @@ public final class SubtypeLocale {
}
// Note that this initialization method can be called multiple times.
- public static synchronized void init(Context context) {
+ public static synchronized void init(final Context context) {
if (sInitialized) return;
final Resources res = context.getResources();
+ sResources = res;
final String[] predefinedLayoutSet = res.getStringArray(R.array.predefined_layouts);
sPredefinedKeyboardLayoutSet = predefinedLayoutSet;
@@ -121,15 +123,15 @@ public final class SubtypeLocale {
return sPredefinedKeyboardLayoutSet;
}
- public static boolean isExceptionalLocale(String localeString) {
+ public static boolean isExceptionalLocale(final String localeString) {
return sExceptionalLocaleToWithLayoutNameIdsMap.containsKey(localeString);
}
- private static final String getNoLanguageLayoutKey(String keyboardLayoutName) {
+ private static final String getNoLanguageLayoutKey(final String keyboardLayoutName) {
return NO_LANGUAGE + "_" + keyboardLayoutName;
}
- public static int getSubtypeNameId(String localeString, String keyboardLayoutName) {
+ public static int getSubtypeNameId(final String localeString, final String keyboardLayoutName) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& isExceptionalLocale(localeString)) {
return sExceptionalLocaleToWithLayoutNameIdsMap.get(localeString);
@@ -141,7 +143,7 @@ public final class SubtypeLocale {
return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId;
}
- public static String getSubtypeLocaleDisplayName(String localeString) {
+ public static String getSubtypeLocaleDisplayName(final String localeString) {
final String exceptionalValue = sExceptionalDisplayNamesMap.get(localeString);
if (exceptionalValue != null) {
return exceptionalValue;
@@ -166,12 +168,17 @@ public final class SubtypeLocale {
// en_US azerty T English (US) (AZERTY)
// 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 >= Build.VERSION_CODES.JELLY_BEAN
- && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME))
- ? subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
- : getSubtypeLocaleDisplayName(subtype.getLocale());
+ private static String getReplacementString(final InputMethodSubtype subtype) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
+ && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
+ return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
+ } else {
+ return getSubtypeLocaleDisplayName(subtype.getLocale());
+ }
+ }
+
+ public static String getSubtypeDisplayName(final InputMethodSubtype subtype) {
+ final String replacementString = getReplacementString(subtype);
final int nameResId = subtype.getNameResId();
final RunInLocale<String> getSubtypeName = new RunInLocale<String>() {
@Override
@@ -190,30 +197,30 @@ public final class SubtypeLocale {
}
};
final Locale locale = isNoLanguage(subtype)
- ? res.getConfiguration().locale : getSubtypeLocale(subtype);
- return getSubtypeName.runInLocale(res, locale);
+ ? sResources.getConfiguration().locale : getSubtypeLocale(subtype);
+ return getSubtypeName.runInLocale(sResources, locale);
}
- public static boolean isNoLanguage(InputMethodSubtype subtype) {
+ public static boolean isNoLanguage(final InputMethodSubtype subtype) {
final String localeString = subtype.getLocale();
return localeString.equals(NO_LANGUAGE);
}
- public static Locale getSubtypeLocale(InputMethodSubtype subtype) {
+ public static Locale getSubtypeLocale(final InputMethodSubtype subtype) {
final String localeString = subtype.getLocale();
return LocaleUtils.constructLocaleFromString(localeString);
}
- public static String getKeyboardLayoutSetDisplayName(InputMethodSubtype subtype) {
+ public static String getKeyboardLayoutSetDisplayName(final InputMethodSubtype subtype) {
final String layoutName = getKeyboardLayoutSetName(subtype);
return getKeyboardLayoutSetDisplayName(layoutName);
}
- public static String getKeyboardLayoutSetDisplayName(String layoutName) {
+ public static String getKeyboardLayoutSetDisplayName(final String layoutName) {
return sKeyboardLayoutToDisplayNameMap.get(layoutName);
}
- public static String getKeyboardLayoutSetName(InputMethodSubtype subtype) {
+ public static String getKeyboardLayoutSetName(final InputMethodSubtype subtype) {
String keyboardLayoutSet = subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET);
if (keyboardLayoutSet == null) {
// This subtype doesn't have a keyboardLayoutSet extra value, so lookup its keyboard
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index eb0ec3990..2f9e34ff1 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -151,8 +151,7 @@ public final class SubtypeSwitcher {
// Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
public void onSubtypeChanged(final InputMethodSubtype newSubtype) {
if (DBG) {
- Log.w(TAG, "onSubtypeChanged: " + SubtypeLocale.getSubtypeDisplayName(
- newSubtype, mResources));
+ Log.w(TAG, "onSubtypeChanged: " + SubtypeLocale.getSubtypeDisplayName(newSubtype));
}
final Locale newLocale = SubtypeLocale.getSubtypeLocale(newSubtype);
diff --git a/java/src/com/android/inputmethod/research/FixedLogBuffer.java b/java/src/com/android/inputmethod/research/FixedLogBuffer.java
index 73f284a73..78dc59562 100644
--- a/java/src/com/android/inputmethod/research/FixedLogBuffer.java
+++ b/java/src/com/android/inputmethod/research/FixedLogBuffer.java
@@ -61,7 +61,7 @@ public class FixedLogBuffer extends LogBuffer {
*/
@Override
public void shiftIn(final LogUnit newLogUnit) {
- if (newLogUnit.getWord() == null) {
+ if (!newLogUnit.hasWord()) {
// This LogUnit isn't a word, so it doesn't count toward the word-limit.
super.shiftIn(newLogUnit);
return;
@@ -153,8 +153,7 @@ public class FixedLogBuffer extends LogBuffer {
for (int i = 0; i < length && n > 0; i++) {
final LogUnit logUnit = logUnits.get(i);
list.add(logUnit);
- final String word = logUnit.getWord();
- if (word != null) {
+ if (logUnit.hasWord()) {
n--;
}
}
diff --git a/java/src/com/android/inputmethod/research/LogUnit.java b/java/src/com/android/inputmethod/research/LogUnit.java
index 715000d28..638b7d9d4 100644
--- a/java/src/com/android/inputmethod/research/LogUnit.java
+++ b/java/src/com/android/inputmethod/research/LogUnit.java
@@ -17,6 +17,7 @@
package com.android.inputmethod.research;
import android.content.SharedPreferences;
+import android.text.TextUtils;
import android.util.JsonWriter;
import android.util.Log;
import android.view.MotionEvent;
@@ -57,16 +58,32 @@ import java.util.Map;
// Assume that mTimeList is sorted in increasing order. Do not insert null values into
// mTimeList.
private final ArrayList<Long> mTimeList;
+ // Word that this LogUnit generates. Should be null if the LogUnit does not generate a genuine
+ // word (i.e. separators alone do not count as a word). Should never be empty.
private String mWord;
private boolean mMayContainDigit;
private boolean mIsPartOfMegaword;
private boolean mContainsCorrection;
+ // mCorrectionType indicates whether the word was corrected at all, and if so, whether it was
+ // to a different word or just a "typo" correction. It is considered a "typo" if the final
+ // word was listed in the suggestions available the first time the word was gestured or
+ // tapped.
+ private int mCorrectionType;
+ public static final int CORRECTIONTYPE_NO_CORRECTION = 0;
+ public static final int CORRECTIONTYPE_CORRECTION = 1;
+ public static final int CORRECTIONTYPE_DIFFERENT_WORD = 2;
+ public static final int CORRECTIONTYPE_TYPO = 3;
+
+ private SuggestedWords mSuggestedWords;
+
public LogUnit() {
mLogStatementList = new ArrayList<LogStatement>();
mValuesList = new ArrayList<Object[]>();
mTimeList = new ArrayList<Long>();
mIsPartOfMegaword = false;
+ mCorrectionType = CORRECTIONTYPE_NO_CORRECTION;
+ mSuggestedWords = null;
}
private LogUnit(final ArrayList<LogStatement> logStatementList,
@@ -77,6 +94,8 @@ import java.util.Map;
mValuesList = valuesList;
mTimeList = timeList;
mIsPartOfMegaword = isPartOfMegaword;
+ mCorrectionType = CORRECTIONTYPE_NO_CORRECTION;
+ mSuggestedWords = null;
}
private static final Object[] NULL_VALUES = new Object[0];
@@ -167,6 +186,7 @@ import java.util.Map;
private static final String UPTIME_KEY = "_ut";
private static final String EVENT_TYPE_KEY = "_ty";
private static final String WORD_KEY = "_wo";
+ private static final String CORRECTION_TYPE_KEY = "_corType";
private static final String LOG_UNIT_BEGIN_KEY = "logUnitStart";
private static final String LOG_UNIT_END_KEY = "logUnitEnd";
@@ -177,6 +197,7 @@ import java.util.Map;
jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis());
if (canIncludePrivateData) {
jsonWriter.name(WORD_KEY).value(getWord());
+ jsonWriter.name(CORRECTION_TYPE_KEY).value(getCorrectionType());
}
jsonWriter.name(EVENT_TYPE_KEY).value(LOG_UNIT_BEGIN_KEY);
jsonWriter.endObject();
@@ -254,7 +275,33 @@ import java.util.Map;
return true;
}
- public void setWord(String word) {
+ /**
+ * Mark the current logUnit as containing data to generate {@code word}.
+ *
+ * If {@code setWord()} was previously called for this LogUnit, then the method will try to
+ * determine what kind of correction it is, and update its internal state of the correctionType
+ * accordingly.
+ *
+ * @param word The word this LogUnit generates. Caller should not pass null or the empty
+ * string.
+ */
+ public void setWord(final String word) {
+ if (hasWord()) {
+ // The word was already set once, and it is now being changed. See if the new word
+ // is close to the old word. If so, then the change is probably a typo correction.
+ // If not, the user may have decided to enter a different word, so flag it.
+ if (mSuggestedWords != null) {
+ if (isInSuggestedWords(word, mSuggestedWords)) {
+ mCorrectionType = CORRECTIONTYPE_TYPO;
+ } else {
+ mCorrectionType = CORRECTIONTYPE_DIFFERENT_WORD;
+ }
+ } else {
+ // No suggested words, so it's not clear whether it's a typo or different word.
+ // Mark it as a generic correction.
+ mCorrectionType = CORRECTIONTYPE_CORRECTION;
+ }
+ }
mWord = word;
}
@@ -263,7 +310,7 @@ import java.util.Map;
}
public boolean hasWord() {
- return mWord != null;
+ return mWord != null && !TextUtils.isEmpty(mWord.trim());
}
public void setMayContainDigit() {
@@ -282,6 +329,14 @@ import java.util.Map;
return mContainsCorrection;
}
+ public void setCorrectionType(final int correctionType) {
+ mCorrectionType = correctionType;
+ }
+
+ public int getCorrectionType() {
+ return mCorrectionType;
+ }
+
public boolean isEmpty() {
return mLogStatementList.isEmpty();
}
@@ -328,8 +383,43 @@ import java.util.Map;
mValuesList.addAll(logUnit.mValuesList);
mTimeList.addAll(logUnit.mTimeList);
mWord = null;
+ if (logUnit.mWord != null) {
+ setWord(logUnit.mWord);
+ }
mMayContainDigit = mMayContainDigit || logUnit.mMayContainDigit;
mContainsCorrection = mContainsCorrection || logUnit.mContainsCorrection;
mIsPartOfMegaword = false;
}
+
+ public SuggestedWords getSuggestions() {
+ return mSuggestedWords;
+ }
+
+ /**
+ * Initialize the suggestions.
+ *
+ * Once set to a non-null value, the suggestions may not be changed again. This is to keep
+ * track of the list of words that are close to the user's initial effort to type the word.
+ * Only words that are close to the initial effort are considered typo corrections.
+ */
+ public void initializeSuggestions(final SuggestedWords suggestedWords) {
+ if (mSuggestedWords == null) {
+ mSuggestedWords = suggestedWords;
+ }
+ }
+
+ private static boolean isInSuggestedWords(final String queryWord,
+ final SuggestedWords suggestedWords) {
+ if (TextUtils.isEmpty(queryWord)) {
+ return false;
+ }
+ final int size = suggestedWords.size();
+ for (int i = 0; i < size; i++) {
+ final SuggestedWordInfo wordInfo = suggestedWords.getInfo(i);
+ if (queryWord.equals(wordInfo.mWord)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/java/src/com/android/inputmethod/research/MainLogBuffer.java b/java/src/com/android/inputmethod/research/MainLogBuffer.java
index 57d5c41d7..3a87bf1df 100644
--- a/java/src/com/android/inputmethod/research/MainLogBuffer.java
+++ b/java/src/com/android/inputmethod/research/MainLogBuffer.java
@@ -117,20 +117,19 @@ public abstract class MainLogBuffer extends FixedLogBuffer {
if (IS_LOGGING_EVERYTHING) {
if (mIsStopping) {
return true;
- } else {
- // Only check that it is the right length. If not, wait for later words to make
- // complete n-grams.
- int numWordsInLogUnitList = 0;
- final int length = logUnits.size();
- for (int i = 0; i < length; i++) {
- final LogUnit logUnit = logUnits.get(i);
- final String word = logUnit.getWord();
- if (word != null) {
- numWordsInLogUnitList++;
- }
+ }
+ // Only check that it is the right length. If not, wait for later words to make
+ // complete n-grams.
+ int numWordsInLogUnitList = 0;
+ final int length = logUnits.size();
+ for (int i = 0; i < length; i++) {
+ final LogUnit logUnit = logUnits.get(i);
+ final String word = logUnit.getWord();
+ if (word != null) {
+ numWordsInLogUnitList++;
}
- return numWordsInLogUnitList >= minNGramSize;
}
+ return numWordsInLogUnitList >= minNGramSize;
}
// Check that we are not sampling too frequently. Having sampled recently might disclose
@@ -157,14 +156,14 @@ public abstract class MainLogBuffer extends FixedLogBuffer {
final int length = logUnits.size();
for (int i = 0; i < length; i++) {
final LogUnit logUnit = logUnits.get(i);
- final String word = logUnit.getWord();
- if (word == null) {
+ if (!logUnit.hasWord()) {
// Digits outside words are a privacy threat.
if (logUnit.mayContainDigit()) {
return false;
}
} else {
numWordsInLogUnitList++;
+ final String word = logUnit.getWord();
// Words not in the dictionary are a privacy threat.
if (ResearchLogger.hasLetters(word) && !(dictionary.isValidWord(word))) {
if (DEBUG) {
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index 2da571d5a..dbf2d2982 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -785,6 +785,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mCurrentLogUnit.setContainsCorrection();
}
+ private void setCurrentLogUnitCorrectionType(final int correctionType) {
+ mCurrentLogUnit.setCorrectionType(correctionType);
+ }
+
/* package for test */ void commitCurrentLogUnit() {
if (DEBUG) {
Log.d(TAG, "commitCurrentLogUnit" + (mCurrentLogUnit.hasWord() ?
@@ -1234,13 +1238,17 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
"suggestion", "x", "y");
public static void latinIME_pickSuggestionManually(final String replacedWord,
final int index, final String suggestion, final boolean isBatchMode) {
- final String scrubbedWord = scrubDigitsFromString(suggestion);
final ResearchLogger researchLogger = getInstance();
+ if (!replacedWord.equals(suggestion.toString())) {
+ // The user choose something other than what was already there.
+ researchLogger.setCurrentLogUnitContainsCorrection();
+ researchLogger.setCurrentLogUnitCorrectionType(LogUnit.CORRECTIONTYPE_TYPO);
+ }
+ final String scrubbedWord = scrubDigitsFromString(suggestion);
researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_PICKSUGGESTIONMANUALLY,
scrubDigitsFromString(replacedWord), index,
suggestion == null ? null : scrubbedWord, Constants.SUGGESTION_STRIP_COORDINATE,
Constants.SUGGESTION_STRIP_COORDINATE);
- researchLogger.setCurrentLogUnitContainsCorrection();
researchLogger.commitCurrentLogUnitAsWord(scrubbedWord, Long.MAX_VALUE, isBatchMode);
researchLogger.mStatistics.recordManualSuggestion(SystemClock.uptimeMillis());
}
@@ -1530,10 +1538,12 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
new LogStatement("LatinIMECommitCurrentAutoCorrection", true, true, "typedWord",
"autoCorrection", "separatorString");
public static void latinIme_commitCurrentAutoCorrection(final String typedWord,
- final String autoCorrection, final String separatorString, final boolean isBatchMode) {
+ final String autoCorrection, final String separatorString, final boolean isBatchMode,
+ final SuggestedWords suggestedWords) {
final String scrubbedTypedWord = scrubDigitsFromString(typedWord);
final String scrubbedAutoCorrection = scrubDigitsFromString(autoCorrection);
final ResearchLogger researchLogger = getInstance();
+ researchLogger.mCurrentLogUnit.initializeSuggestions(suggestedWords);
researchLogger.commitCurrentLogUnitAsWord(scrubbedAutoCorrection, Long.MAX_VALUE,
isBatchMode);
@@ -1731,10 +1741,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
new LogStatement("LatinIMEOnEndBatchInput", true, false, "enteredText",
"enteredWordPos");
public static void latinIME_onEndBatchInput(final CharSequence enteredText,
- final int enteredWordPos) {
+ final int enteredWordPos, final SuggestedWords suggestedWords) {
final ResearchLogger researchLogger = getInstance();
researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONENDBATCHINPUT, enteredText,
enteredWordPos);
+ researchLogger.mCurrentLogUnit.initializeSuggestions(suggestedWords);
researchLogger.mStatistics.recordGestureInput(enteredText.length(),
SystemClock.uptimeMillis());
}