Merge "Update useless n-gram entry detection logic during GC."
diff --git a/java-overridable/src/com/android/inputmethod/latin/accounts/AccountStateChangedListener.java b/java-overridable/src/com/android/inputmethod/latin/accounts/AccountStateChangedListener.java
new file mode 100644
index 0000000..c0a599c
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/accounts/AccountStateChangedListener.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014 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.accounts;
+
+import android.support.annotation.NonNull;
+
+import javax.annotation.Nullable;
+
+/**
+ * Handles changes to account used to sign in to the keyboard.
+ * e.g. account switching/sign-in/sign-out from the keyboard
+ * user toggling the sync preference.
+ */
+public class AccountStateChangedListener {
+
+ /**
+ * Called when the current account being used in keyboard is signed out.
+ *
+ * @param oldAccount the account that was signed out of.
+ */
+ public static void onAccountSignedOut(@NonNull String oldAccount) {
+ }
+
+ /**
+ * Called when the user signs-in to the keyboard.
+ * This may be called when the user switches accounts to sign in with a different account.
+ *
+ * @param oldAccount the previous account that was being used for sign-in.
+ * May be null for a fresh sign-in.
+ * @param newAccount the account being used for sign-in.
+ */
+ public static void onAccountSignedIn(@Nullable String oldAccount, @NonNull String newAccount) {
+ }
+
+ /**
+ * Called when the user toggles the sync preference.
+ *
+ * @param account the account being used for sync.
+ * @param syncEnabled indicates whether sync has been enabled or not.
+ */
+ public static void onSyncPreferenceChanged(@Nullable String account, boolean syncEnabled) {
+ }
+
+ /**
+ * Forces an immediate sync to happen.
+ * This should only be used for debugging purposes.
+ *
+ * @param account the account to use for sync.
+ */
+ public static void forceSync(@Nullable String account) {
+ }
+}
diff --git a/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
index 747a3b0..f9ebb97 100644
--- a/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.res.Resources;
import android.preference.PreferenceFragment;
import android.view.inputmethod.InputMethodSubtype;
@@ -48,7 +49,8 @@
public static RichInputMethodSubtype createRichInputMethodSubtype(
@Nonnull final RichInputMethodManager imm,
- @Nonnull final InputMethodSubtype subtype) {
+ @Nonnull final InputMethodSubtype subtype,
+ final Resources resources) {
return new RichInputMethodSubtype(subtype);
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index 52b9284..1c66c37 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -28,6 +28,7 @@
import android.util.SparseArray;
import android.util.Xml;
import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.compat.EditorInfoCompatUtils;
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
@@ -39,6 +40,7 @@
import com.android.inputmethod.latin.RichInputMethodSubtype;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.define.DebugFlags;
+import com.android.inputmethod.latin.utils.DebugLogUtils;
import com.android.inputmethod.latin.utils.InputTypeUtils;
import com.android.inputmethod.latin.utils.ScriptUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
@@ -313,23 +315,78 @@
return this;
}
+ private final static HashMap<InputMethodSubtype, Integer> sScriptIdsForSubtypes =
+ new HashMap<>();
+ public static int getScriptId(final Resources resources, final InputMethodSubtype subtype) {
+ final Integer value = sScriptIdsForSubtypes.get(subtype);
+ if (null == value) {
+ final int scriptId = readScriptId(resources, subtype);
+ sScriptIdsForSubtypes.put(subtype, scriptId);
+ return scriptId;
+ }
+ return value;
+ }
+
+ // Super redux version of reading the script ID for some subtype from Xml.
+ private static int readScriptId(final Resources resources,
+ final InputMethodSubtype subtype) {
+ final String layoutSetName = KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX
+ + SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype);
+ final int xmlId = getXmlId(resources, layoutSetName);
+ final XmlResourceParser parser = resources.getXml(xmlId);
+ try {
+ while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+ // Bovinate through the XML stupidly searching for TAG_FEATURE, and read
+ // the script Id from it.
+ parser.next();
+ final String tag = parser.getName();
+ if (TAG_FEATURE.equals(tag)) {
+ return readScriptIdFromTagFeature(resources, parser);
+ }
+ }
+ } catch (final IOException | XmlPullParserException e) {
+ throw new RuntimeException(e.getMessage() + " in " + layoutSetName, e);
+ } finally {
+ parser.close();
+ }
+ // If the tag is not found, then the default script is Latin.
+ return ScriptUtils.SCRIPT_LATIN;
+ }
+
+ private static int readScriptIdFromTagFeature(final Resources resources,
+ final XmlPullParser parser) throws IOException, XmlPullParserException {
+ final TypedArray featureAttr = resources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.KeyboardLayoutSet_Feature);
+ try {
+ final int scriptId =
+ featureAttr.getInt(R.styleable.KeyboardLayoutSet_Feature_supportedScript,
+ ScriptUtils.SCRIPT_UNKNOWN);
+ XmlParseUtils.checkEndTag(TAG_FEATURE, parser);
+ return scriptId;
+ } finally {
+ featureAttr.recycle();
+ }
+ }
+
public KeyboardLayoutSet build() {
if (mParams.mSubtype == null)
throw new RuntimeException("KeyboardLayoutSet subtype is not specified");
- final String packageName = mResources.getResourcePackageName(
- R.xml.keyboard_layout_set_qwerty);
- final String keyboardLayoutSetName = mParams.mKeyboardLayoutSetName;
- final int xmlId = mResources.getIdentifier(keyboardLayoutSetName, "xml", packageName);
+ final int xmlId = getXmlId(mResources, mParams.mKeyboardLayoutSetName);
try {
parseKeyboardLayoutSet(mResources, xmlId);
- } catch (final IOException e) {
- throw new RuntimeException(e.getMessage() + " in " + keyboardLayoutSetName, e);
- } catch (final XmlPullParserException e) {
- throw new RuntimeException(e.getMessage() + " in " + keyboardLayoutSetName, e);
+ } catch (final IOException | XmlPullParserException e) {
+ throw new RuntimeException(e.getMessage() + " in " + mParams.mKeyboardLayoutSetName,
+ e);
}
return new KeyboardLayoutSet(mContext, mParams);
}
+ private static int getXmlId(final Resources resources, final String keyboardLayoutSetName) {
+ final String packageName = resources.getResourcePackageName(
+ R.xml.keyboard_layout_set_qwerty);
+ return resources.getIdentifier(keyboardLayoutSetName, "xml", packageName);
+ }
+
private void parseKeyboardLayoutSet(final Resources res, final int resId)
throws XmlPullParserException, IOException {
final XmlResourceParser parser = res.getXml(resId);
@@ -407,17 +464,8 @@
private void parseKeyboardLayoutSetFeature(final XmlPullParser parser)
throws XmlPullParserException, IOException {
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.KeyboardLayoutSet_Feature);
- try {
- final int scriptId = a.getInt(
- R.styleable.KeyboardLayoutSet_Feature_supportedScript,
- ScriptUtils.SCRIPT_LATIN);
- XmlParseUtils.checkEndTag(TAG_FEATURE, parser);
- setScriptId(scriptId);
- } finally {
- a.recycle();
- }
+ final int scriptId = readScriptIdFromTagFeature(mResources, parser);
+ setScriptId(scriptId);
}
private static int getKeyboardMode(final EditorInfo editorInfo) {
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecorator.java b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
index ddc65bf..2b7d2ce 100644
--- a/java/src/com/android/inputmethod/keyboard/TextDecorator.java
+++ b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
@@ -303,7 +303,7 @@
*/
private static final class LayoutInvalidator {
private final HandlerImpl mHandler;
- public LayoutInvalidator(final TextDecorator ownerInstance) {
+ public LayoutInvalidator(@Nonnull final TextDecorator ownerInstance) {
mHandler = new HandlerImpl(ownerInstance);
}
@@ -311,7 +311,7 @@
private static final class HandlerImpl
extends LeakGuardHandlerWrapper<TextDecorator> {
- public HandlerImpl(final TextDecorator ownerInstance) {
+ public HandlerImpl(@Nonnull final TextDecorator ownerInstance) {
super(ownerInstance);
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java b/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java
index 4f8a105..1a55359 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java
@@ -23,6 +23,8 @@
import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
+import javax.annotation.Nonnull;
+
// TODO: Separate this class into KeyPreviewHandler and BatchInputPreviewHandler or so.
public class DrawingHandler extends LeakGuardHandlerWrapper<Callbacks> {
public interface Callbacks {
@@ -34,7 +36,7 @@
private static final int MSG_DISMISS_KEY_PREVIEW = 0;
private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
- public DrawingHandler(final Callbacks ownerInstance) {
+ public DrawingHandler(@Nonnull final Callbacks ownerInstance) {
super(ownerInstance);
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
index ec7b9b0..80b299b 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
@@ -27,6 +27,8 @@
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
+import javax.annotation.Nonnull;
+
// TODO: Separate this class into KeyTimerHandler and BatchInputTimerHandler or so.
public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> implements TimerProxy {
public interface Callbacks {
@@ -45,7 +47,7 @@
private final int mIgnoreAltCodeKeyTimeout;
private final int mGestureRecognitionUpdateTime;
- public TimerHandler(final Callbacks ownerInstance, final int ignoreAltCodeKeyTimeout,
+ public TimerHandler(@Nonnull final Callbacks ownerInstance, final int ignoreAltCodeKeyTimeout,
final int gestureRecognitionUpdateTime) {
super(ownerInstance);
mIgnoreAltCodeKeyTimeout = ignoreAltCodeKeyTimeout;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 77016cb..f968a6c 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -110,6 +110,8 @@
import java.util.Locale;
import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
+
/**
* Input method implementation for Qwerty'ish keyboard.
*/
@@ -208,7 +210,7 @@
private int mDelayInMillisecondsToUpdateSuggestions;
private int mDelayInMillisecondsToUpdateShiftState;
- public UIHandler(final LatinIME ownerInstance) {
+ public UIHandler(@Nonnull final LatinIME ownerInstance) {
super(ownerInstance);
}
@@ -1073,7 +1075,8 @@
// with cursor movement when we have a hardware keyboard since we are not in charge.
final SettingsValues settingsValues = mSettings.getCurrent();
if ((!settingsValues.mHasHardwareKeyboard || ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED)
- && mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd)) {
+ && mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
+ settingsValues)) {
mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
getCurrentRecapitalizeState());
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index 3fcae58..b0c0725 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.res.Resources;
import android.os.Build;
import android.os.IBinder;
import android.preference.PreferenceManager;
@@ -51,6 +52,7 @@
private static final RichInputMethodManager sInstance = new RichInputMethodManager();
+ private Resources mResources;
private InputMethodManagerCompatWrapper mImmWrapper;
private InputMethodInfoCache mInputMethodInfoCache;
final HashMap<InputMethodInfo, List<InputMethodSubtype>>
@@ -84,6 +86,7 @@
return;
}
mImmWrapper = new InputMethodManagerCompatWrapper(context);
+ mResources = context.getResources();
mInputMethodInfoCache = new InputMethodInfoCache(
mImmWrapper.mImm, context.getPackageName());
@@ -305,7 +308,8 @@
public RichInputMethodSubtype createCurrentRichInputMethodSubtype(
final InputMethodSubtype rawSubtype) {
- return AdditionalFeaturesSettingUtils.createRichInputMethodSubtype(this, rawSubtype);
+ return AdditionalFeaturesSettingUtils.createRichInputMethodSubtype(this, rawSubtype,
+ mResources);
}
public boolean hasMultipleEnabledIMEsOrSubtypes(final boolean shouldIncludeAuxiliarySubtypes) {
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 0d742e9..13f79b4 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -36,7 +36,6 @@
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
import com.android.inputmethod.latin.define.DebugFlags;
-import com.android.inputmethod.latin.utils.LocaleUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.HashSet;
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index f67b8de..5cc61db 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -371,10 +371,11 @@
* @param oldSelEnd old selection end
* @param newSelStart new selection start
* @param newSelEnd new selection end
+ * @param settingsValues the current values of the settings.
* @return whether the cursor has moved as a result of user interaction.
*/
public boolean onUpdateSelection(final int oldSelStart, final int oldSelEnd,
- final int newSelStart, final int newSelEnd) {
+ final int newSelStart, final int newSelEnd, final SettingsValues settingsValues) {
if (mConnection.isBelatedExpectedUpdate(oldSelStart, newSelStart, oldSelEnd, newSelEnd)) {
return false;
}
@@ -399,8 +400,9 @@
// should be true, but that is if the framework had taken that wrong cursor position
// into account, which means we have to reset the entire composing state whenever there
// is or was a selection regardless of whether it changed or not.
- if (hasOrHadSelection || (selectionChangedOrSafeToReset
- && !mWordComposer.moveCursorByAndReturnIfInsideComposingWord(moveAmount))) {
+ if (hasOrHadSelection || !settingsValues.needsToLookupSuggestions()
+ || (selectionChangedOrSafeToReset
+ && !mWordComposer.moveCursorByAndReturnIfInsideComposingWord(moveAmount))) {
// If we are composing a word and moving the cursor, we would want to set a
// suggestion span for recorrection to work correctly. Unfortunately, that
// would involve the keyboard committing some new text, which would move the
diff --git a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
index 5e6521f..4bd15d0 100644
--- a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
@@ -19,9 +19,7 @@
import static com.android.inputmethod.latin.settings.LocalSettingsConstants.PREF_ACCOUNT_NAME;
import static com.android.inputmethod.latin.settings.LocalSettingsConstants.PREF_ENABLE_CLOUD_SYNC;
-import android.accounts.Account;
import android.app.AlertDialog;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
@@ -37,6 +35,7 @@
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.accounts.LoginAccountUtils;
+import com.android.inputmethod.latin.accounts.AccountStateChangedListener;
import com.android.inputmethod.latin.define.ProductionFlags;
import javax.annotation.Nullable;
@@ -52,7 +51,6 @@
public final class AccountsSettingsFragment extends SubScreenFragment {
private static final String PREF_SYNC_NOW = "pref_beanstalk";
- @UsedForTesting static final String AUTHORITY = "com.android.inputmethod.latin.provider";
static final String PREF_ACCCOUNT_SWITCHER = "account_switcher";
private final DialogInterface.OnClickListener mAccountChangedListener =
@@ -111,7 +109,8 @@
prefs.getString(PREF_ACCOUNT_NAME, null));
} else if (TextUtils.equals(key, PREF_ENABLE_CLOUD_SYNC)) {
final boolean syncEnabled = prefs.getBoolean(PREF_ENABLE_CLOUD_SYNC, false);
- updateSyncPolicy(syncEnabled, getSignedInAccountName());
+ AccountStateChangedListener.onSyncPreferenceChanged(
+ getSignedInAccountName(), syncEnabled);
}
}
@@ -177,36 +176,6 @@
syncPreference.setSummary(R.string.cloud_sync_summary_disabled_signed_out);
}
- /**
- * Given a non-null accountToUse, this method looks at the enabled value to either
- * set or unset the syncable property of the sync authority.
- * If the account is null, this method is a no-op currently, but we may want
- * to perform some cleanup in the future.
- *
- * @param enabled indicates whether the sync preference is enabled or not.
- * @param accountToUse indicaes the account to be used for sync, or null if the user
- * is not logged in.
- */
- @UsedForTesting
- void updateSyncPolicy(boolean enabled, @Nullable String accountToUse) {
- if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
- return;
- }
-
- if (accountToUse != null) {
- final int syncable = enabled ? 1 : 0;
- ContentResolver.setIsSyncable(
- new Account(accountToUse, LoginAccountUtils.ACCOUNT_TYPE),
- AUTHORITY, syncable);
- // TODO: Also add a periodic sync here.
- // See ContentResolver.addPeriodicSync
- } else {
- // Without an account, we cannot really set the sync to off.
- // Hopefully the account sign-out listener would have taken care of that for us.
- // But cases such as clear data are still not handled cleanly.
- }
- }
-
@Nullable
String getSignedInAccountName() {
return getSharedPreferences().getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
@@ -261,22 +230,20 @@
class AccountChangedListener implements DialogInterface.OnClickListener {
@Override
public void onClick(DialogInterface dialog, int which) {
+ final String oldAccount = getSignedInAccountName();
switch (which) {
case DialogInterface.BUTTON_POSITIVE: // Signed in
final ListView lv = ((AlertDialog)dialog).getListView();
- final Object selectedItem = lv.getItemAtPosition(lv.getCheckedItemPosition());
+ final String newAccount =
+ (String) lv.getItemAtPosition(lv.getCheckedItemPosition());
getSharedPreferences()
.edit()
- .putString(PREF_ACCOUNT_NAME, (String) selectedItem)
+ .putString(PREF_ACCOUNT_NAME, newAccount)
.apply();
- // Attempt starting sync for the new account if sync was
- // previously enabled.
- // If not, stop it.
- updateSyncPolicy(isSyncEnabled(), getSignedInAccountName());
+ AccountStateChangedListener.onAccountSignedIn(oldAccount, newAccount);
break;
case DialogInterface.BUTTON_NEUTRAL: // Signed out
- // Stop sync for the account that's being signed out of.
- updateSyncPolicy(false, getSignedInAccountName());
+ AccountStateChangedListener.onAccountSignedOut(oldAccount);
getSharedPreferences()
.edit()
.remove(PREF_ACCOUNT_NAME)
@@ -292,9 +259,7 @@
class SyncNowListener implements Preference.OnPreferenceClickListener {
@Override
public boolean onPreferenceClick(final Preference preference) {
- ContentResolver.requestSync(
- new Account(getSignedInAccountName(), LoginAccountUtils.ACCOUNT_TYPE),
- AUTHORITY, Bundle.EMPTY);
+ AccountStateChangedListener.forceSync(getSignedInAccountName());
return true;
}
}
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
index 54562f3..c3b30dc 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
@@ -42,6 +42,8 @@
import java.util.ArrayList;
+import javax.annotation.Nonnull;
+
// TODO: Use Fragment to implement welcome screen and setup steps.
public final class SetupWizardActivity extends Activity implements View.OnClickListener {
static final String TAG = SetupWizardActivity.class.getSimpleName();
@@ -82,7 +84,7 @@
private final InputMethodManager mImmInHandler;
- public SettingsPoolingHandler(final SetupWizardActivity ownerInstance,
+ public SettingsPoolingHandler(@Nonnull final SetupWizardActivity ownerInstance,
final InputMethodManager imm) {
super(ownerInstance);
mImmInHandler = imm;
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index 0c84414..7b66bbb 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -321,18 +321,6 @@
} else {
color = mColorSuggested;
}
- if (DebugFlags.DEBUG_ENABLED && suggestedWords.size() > 1) {
- // If we auto-correct, then the autocorrection is in slot 0 and the typed word
- // is in slot 1.
- if (indexInSuggestedWords == SuggestedWords.INDEX_OF_AUTO_CORRECTION
- && suggestedWords.mWillAutoCorrect
- && AutoCorrectionUtils.shouldBlockAutoCorrectionBySafetyNet(
- suggestedWords.getLabel(SuggestedWords.INDEX_OF_AUTO_CORRECTION),
- suggestedWords.getLabel(SuggestedWords.INDEX_OF_TYPED_WORD))) {
- return 0xFFFF0000;
- }
- }
-
if (suggestedWords.mIsObsoleteSuggestions && !isTypedWord) {
return applyAlpha(color, mAlphaObsoleted);
}
diff --git a/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java b/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java
index 156fcf5..cba7695 100644
--- a/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java
@@ -52,41 +52,9 @@
if (DBG) {
Log.d(TAG, "Auto corrected by S-threshold.");
}
- return !shouldBlockAutoCorrectionBySafetyNet(consideredWord, suggestion.mWord);
+ return true;
}
}
return false;
}
-
- // TODO: Resolve the inconsistencies between the native auto correction algorithms and
- // this safety net
- public static boolean shouldBlockAutoCorrectionBySafetyNet(final String typedWord,
- final String suggestion) {
- // Safety net for auto correction.
- // Actually if we hit this safety net, it's a bug.
- // If user selected aggressive auto correction mode, there is no need to use the safety
- // net.
- // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH,
- // we should not use net because relatively edit distance can be big.
- final int typedWordLength = typedWord.length();
- if (typedWordLength < MINIMUM_SAFETY_NET_CHAR_LENGTH) {
- return false;
- }
- final int maxEditDistanceOfNativeDictionary = (typedWordLength / 2) + 1;
- final int distance = BinaryDictionaryUtils.editDistance(typedWord, suggestion);
- if (DBG) {
- Log.d(TAG, "Autocorrected edit distance = " + distance
- + ", " + maxEditDistanceOfNativeDictionary);
- }
- if (distance > maxEditDistanceOfNativeDictionary) {
- if (DBG) {
- Log.e(TAG, "Safety net: before = " + typedWord + ", after = " + suggestion);
- Log.e(TAG, "(Error) The edit distance of this correction exceeds limit. "
- + "Turning off auto-correction.");
- }
- return true;
- } else {
- return false;
- }
- }
}
diff --git a/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java b/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java
index 5d7deba..ce25fe6 100644
--- a/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java
@@ -43,7 +43,6 @@
private static native boolean createEmptyDictFileNative(String filePath, long dictVersion,
String locale, String[] attributeKeyStringArray, String[] attributeValueStringArray);
private static native float calcNormalizedScoreNative(int[] before, int[] after, int score);
- private static native int editDistanceNative(int[] before, int[] after);
private static native int setCurrentTimeForTestNative(int currentTime);
public static DictionaryHeader getHeader(final File dictFile)
@@ -112,14 +111,6 @@
StringUtils.toCodePointArray(after), score);
}
- public static int editDistance(final String before, final String after) {
- if (before == null || after == null) {
- throw new IllegalArgumentException();
- }
- return editDistanceNative(StringUtils.toCodePointArray(before),
- StringUtils.toCodePointArray(after));
- }
-
/**
* Control the current time to be used in the native code. If currentTime >= 0, this method sets
* the current time and gets into test mode.
diff --git a/java/src/com/android/inputmethod/latin/utils/LeakGuardHandlerWrapper.java b/java/src/com/android/inputmethod/latin/utils/LeakGuardHandlerWrapper.java
index dd6fac6..9a5be99 100644
--- a/java/src/com/android/inputmethod/latin/utils/LeakGuardHandlerWrapper.java
+++ b/java/src/com/android/inputmethod/latin/utils/LeakGuardHandlerWrapper.java
@@ -21,21 +21,22 @@
import java.lang.ref.WeakReference;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
public class LeakGuardHandlerWrapper<T> extends Handler {
private final WeakReference<T> mOwnerInstanceRef;
- public LeakGuardHandlerWrapper(final T ownerInstance) {
+ public LeakGuardHandlerWrapper(@Nonnull final T ownerInstance) {
this(ownerInstance, Looper.myLooper());
}
- public LeakGuardHandlerWrapper(final T ownerInstance, final Looper looper) {
+ public LeakGuardHandlerWrapper(@Nonnull final T ownerInstance, final Looper looper) {
super(looper);
- if (ownerInstance == null) {
- throw new NullPointerException("ownerInstance is null");
- }
mOwnerInstanceRef = new WeakReference<>(ownerInstance);
}
+ @Nullable
public T getOwnerInstance() {
return mOwnerInstanceRef.get();
}
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp
index 0a34b78..68bf417 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp
@@ -68,18 +68,6 @@
afterCodePoints, afterLength, score);
}
-static jint latinime_BinaryDictionaryUtils_editDistance(JNIEnv *env, jclass clazz, jintArray before,
- jintArray after) {
- jsize beforeLength = env->GetArrayLength(before);
- jsize afterLength = env->GetArrayLength(after);
- int beforeCodePoints[beforeLength];
- int afterCodePoints[afterLength];
- env->GetIntArrayRegion(before, 0, beforeLength, beforeCodePoints);
- env->GetIntArrayRegion(after, 0, afterLength, afterCodePoints);
- return AutocorrectionThresholdUtils::editDistance(beforeCodePoints, beforeLength,
- afterCodePoints, afterLength);
-}
-
static int latinime_BinaryDictionaryUtils_setCurrentTimeForTest(JNIEnv *env, jclass clazz,
jint currentTime) {
if (currentTime >= 0) {
@@ -104,11 +92,6 @@
reinterpret_cast<void *>(latinime_BinaryDictionaryUtils_calcNormalizedScore)
},
{
- const_cast<char *>("editDistanceNative"),
- const_cast<char *>("([I[I)I"),
- reinterpret_cast<void *>(latinime_BinaryDictionaryUtils_editDistance)
- },
- {
const_cast<char *>("setCurrentTimeForTestNative"),
const_cast<char *>("(I)I"),
reinterpret_cast<void *>(latinime_BinaryDictionaryUtils_setCurrentTimeForTest)
diff --git a/native/jni/src/suggest/core/policy/weighting.cpp b/native/jni/src/suggest/core/policy/weighting.cpp
index c202b81..a06e7d0 100644
--- a/native/jni/src/suggest/core/policy/weighting.cpp
+++ b/native/jni/src/suggest/core/policy/weighting.cpp
@@ -110,10 +110,14 @@
return weighting->getOmissionCost(parentDicNode, dicNode);
case CT_ADDITIONAL_PROXIMITY:
// only used for typing
- return weighting->getAdditionalProximityCost();
+ // TODO: Quit calling getMatchedCost().
+ return weighting->getAdditionalProximityCost()
+ + weighting->getMatchedCost(traverseSession, dicNode, inputStateG);
case CT_SUBSTITUTION:
// only used for typing
- return weighting->getSubstitutionCost();
+ // TODO: Quit calling getMatchedCost().
+ return weighting->getSubstitutionCost()
+ + weighting->getMatchedCost(traverseSession, dicNode, inputStateG);
case CT_NEW_WORD_SPACE_OMISSION:
return weighting->getNewWordSpatialCost(traverseSession, dicNode, inputStateG);
case CT_MATCH:
@@ -176,9 +180,9 @@
case CT_OMISSION:
return 0;
case CT_ADDITIONAL_PROXIMITY:
- return 0; /* 0 because CT_MATCH will be called */
+ return 1;
case CT_SUBSTITUTION:
- return 0; /* 0 because CT_MATCH will be called */
+ return 1;
case CT_NEW_WORD_SPACE_OMISSION:
return 0;
case CT_MATCH:
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index cf2df86..c715262 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -284,7 +284,6 @@
// not treat the node as a terminal. There is no need to pass the bigram map in these cases.
Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_ADDITIONAL_PROXIMITY,
traverseSession, dicNode, childDicNode, 0 /* multiBigramMap */);
- weightChildNode(traverseSession, childDicNode);
processExpandedDicNode(traverseSession, childDicNode);
}
@@ -292,7 +291,6 @@
DicNode *dicNode, DicNode *childDicNode) const {
Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_SUBSTITUTION, traverseSession,
dicNode, childDicNode, 0 /* multiBigramMap */);
- weightChildNode(traverseSession, childDicNode);
processExpandedDicNode(traverseSession, childDicNode);
}
@@ -403,7 +401,7 @@
if (dicNode->isCompletion(inputSize)) {
Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_COMPLETION, traverseSession,
0 /* parentDicNode */, dicNode, 0 /* multiBigramMap */);
- } else { // completion
+ } else {
Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_MATCH, traverseSession,
0 /* parentDicNode */, dicNode, 0 /* multiBigramMap */);
}
diff --git a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
index b621eef..6a2db68 100644
--- a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
@@ -49,7 +49,7 @@
const float ScoringParams::INSERTION_COST_FIRST_CHAR = 0.639f;
const float ScoringParams::TRANSPOSITION_COST = 0.5608f;
const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.334f;
-const float ScoringParams::ADDITIONAL_PROXIMITY_COST = 0.4576f;
+const float ScoringParams::ADDITIONAL_PROXIMITY_COST = 0.37972f;
const float ScoringParams::SUBSTITUTION_COST = 0.3806f;
const float ScoringParams::COST_NEW_WORD = 0.0314f;
const float ScoringParams::COST_SECOND_OR_LATER_WORD_FIRST_CHAR_UPPERCASE = 0.3224f;
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
index 1d590c3..db7a39e 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
@@ -68,7 +68,8 @@
}
break;
case CT_ADDITIONAL_PROXIMITY:
- return ErrorTypeUtils::PROXIMITY_CORRECTION;
+ // TODO: Change to EDIT_CORRECTION.
+ return ErrorTypeUtils::PROXIMITY_CORRECTION;
case CT_OMISSION:
if (parentDicNode->canBeIntentionalOmission()) {
return ErrorTypeUtils::INTENTIONAL_OMISSION;
@@ -77,6 +78,8 @@
}
break;
case CT_SUBSTITUTION:
+ // TODO: Quit settng PROXIMITY_CORRECTION.
+ return ErrorTypeUtils::EDIT_CORRECTION | ErrorTypeUtils::PROXIMITY_CORRECTION;
case CT_INSERTION:
case CT_TERMINAL_INSERTION:
case CT_TRANSPOSITION:
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 26195d3..c7a9e13 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -21,7 +21,8 @@
<uses-permission android:name="android.permission.READ_CONTACTS" />
- <application>
+ <application android:label="@string/app_name"
+ android:icon="@drawable/ic_app">
<uses-library android:name="android.test.runner" />
<!-- meta-data android:name="com.android.contacts.iconset" android:resource="@xml/iconset" /-->
</application>
diff --git a/tests/res/drawable-hdpi/ic_app.png b/tests/res/drawable-hdpi/ic_app.png
new file mode 100644
index 0000000..345c23d
--- /dev/null
+++ b/tests/res/drawable-hdpi/ic_app.png
Binary files differ
diff --git a/tests/res/values/strings.xml b/tests/res/values/strings.xml
new file mode 100644
index 0000000..5cc48b6
--- /dev/null
+++ b/tests/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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.
+*/
+-->
+<resources>
+ <string name="app_name" translatable="false">LatinIMETests</string>
+</resources>
diff --git a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
index 30b0881..ae5cc5c 100644
--- a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
+++ b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
@@ -28,7 +28,7 @@
final int EXPECTED_SPAN_START = 0;
final int EXPECTED_SPAN_END = 4;
type(STRING_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
assertEquals("show blue underline, span start", EXPECTED_SPAN_START, span.mStart);
@@ -42,7 +42,7 @@
final int EXPECTED_SPAN_START = 0;
final int EXPECTED_SPAN_END = 5;
type(STRING_1_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
type(STRING_2_TO_TYPE);
// We haven't have time to look into the dictionary yet, so the line should still be
@@ -51,7 +51,7 @@
assertEquals("extend blue underline, span start", EXPECTED_SPAN_START, spanBefore.mStart);
assertEquals("extend blue underline, span end", EXPECTED_SPAN_END, spanBefore.mEnd);
assertTrue("extend blue underline, span color", spanBefore.isAutoCorrectionIndicator());
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
// Now we have been able to re-evaluate the word, there shouldn't be an auto-correction span
final SpanGetter spanAfter = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
@@ -65,18 +65,18 @@
final int EXPECTED_UNDERLINE_SPAN_START = 0;
final int EXPECTED_UNDERLINE_SPAN_END = 3;
type(STRING_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
type(Constants.CODE_SPACE);
// typedLength + 1 because we also typed a space
mLatinIME.onUpdateSelection(0, 0, typedLength + 1, typedLength + 1, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
type(Constants.CODE_DELETE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
type(Constants.CODE_DELETE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
final SpanGetter suggestionSpan = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
assertFalse("show no blue underline after backspace, span should not be the auto-"
@@ -93,7 +93,7 @@
final int typedLength = STRING_TO_TYPE.length();
final int NEW_CURSOR_POSITION = 0;
type(STRING_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
// Simulate the onUpdateSelection() event
mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
runMessages();
@@ -103,7 +103,7 @@
mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION);
mLatinIME.onUpdateSelection(typedLength, typedLength,
NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
assertFalse("blue underline removed when cursor is moved",
@@ -113,7 +113,7 @@
public void testComposingStopsOnSpace() {
final String STRING_TO_TYPE = "this ";
type(STRING_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
// Simulate the onUpdateSelection() event
mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
runMessages();
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index ec249da..99dc9a2 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
+import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
import android.view.inputmethod.BaseInputConnection;
@@ -487,7 +488,7 @@
public void testPredictionsAfterSpace() {
final String WORD_TO_TYPE = "Barack ";
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Test the first prediction is displayed
final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -499,17 +500,17 @@
mLatinIME.clearPersonalizedDictionariesForTest();
final String WORD_TO_TYPE = "Barack ";
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// No need to test here, testPredictionsAfterSpace is testing it already
type(" ");
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Test the predictions have been cleared
SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
assertEquals("predictions cleared after double-space-to-period", suggestedWords.size(), 0);
type(Constants.CODE_DELETE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Test the first prediction is displayed
suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -522,7 +523,7 @@
type(WORD_TO_TYPE);
// Choose the auto-correction. For "Barack", the auto-correction should be "Barack".
pickSuggestionManually(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Test the first prediction is displayed
final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -534,13 +535,13 @@
mLatinIME.clearPersonalizedDictionariesForTest();
final String WORD_TO_TYPE = "Barack. ";
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
assertEquals("No prediction after period after inputting once.", 0, suggestedWords.size());
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
suggestedWords = mLatinIME.getSuggestedWordsForTest();
assertEquals("Beginning-of-Sentence prediction after inputting 2 times.", "Barack",
@@ -565,18 +566,18 @@
type(" ");
mLatinIME.onUpdateSelection(endOfSuggestion, endOfSuggestion,
endOfSuggestion + 1, endOfSuggestion + 1, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Simulate a manual cursor move
mInputConnection.setSelection(indexForManualCursor, indexForManualCursor);
mLatinIME.onUpdateSelection(endOfSuggestion + 1, endOfSuggestion + 1,
indexForManualCursor, indexForManualCursor, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
pickSuggestionManually(WORD_TO_TYPE);
mLatinIME.onUpdateSelection(indexForManualCursor, indexForManualCursor,
endOfWord, endOfWord, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Test the first prediction is displayed
final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -624,7 +625,7 @@
for (int i = 0; i < WORD_TO_TYPE.length(); ++i) {
type(WORD_TO_TYPE.substring(i, i+1));
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
}
assertEquals("type many trailing single quotes one by one", EXPECTED_RESULT,
@@ -636,7 +637,7 @@
final String EXPECTED_RESULT = WORD_TO_TYPE;
for (int i = 0; i < WORD_TO_TYPE.length(); ++i) {
type(WORD_TO_TYPE.substring(i, i+1));
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
}
assertEquals("type words letter by letter", EXPECTED_RESULT,
@@ -652,10 +653,30 @@
changeLanguage("fr");
runMessages();
type(WORD_TO_TYPE_SECOND_PART);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
assertEquals("Suggestions updated after switching languages",
EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(1) : null);
}
+
+ public void testBasicGesture() {
+ gesture("this");
+ assertEquals("gesture \"this\"", "this", mEditText.getText().toString());
+ }
+
+ public void testGestureGesture() {
+ gesture("this");
+ gesture("is");
+ assertEquals("gesture \"this is\"", "this is", mEditText.getText().toString());
+ }
+
+ public void testGestureBackspaceGestureAgain() {
+ gesture("this");
+ type(Constants.CODE_DELETE);
+ assertEquals("gesture then backspace", "", mEditText.getText().toString());
+ gesture("this");
+ MoreAsserts.assertNotEqual("gesture twice the same thing", "this",
+ mEditText.getText().toString());
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
index 2560407..c16372a 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
@@ -74,7 +74,7 @@
mInputConnection.setSelection(CURSOR_POS, CURSOR_POS);
mLatinIME.onUpdateSelection(typedLength, typedLength,
CURSOR_POS, CURSOR_POS, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
assertEquals("start composing inside text", -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
@@ -91,7 +91,7 @@
final String WORD_TO_TYPE = "Barack ";
changeKeyboardLocaleAndDictLocale("th", "en_US");
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Make sure there is no space
assertEquals("predictions in lang without spaces", "Barack",
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
index 715d449..842b54f 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
@@ -70,7 +70,7 @@
try {
changeLanguage("fr");
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
assertTrue("type word then type space should display punctuation strip",
mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
@@ -95,7 +95,7 @@
try {
changeLanguage("fr");
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
assertEquals("type word then type space yields predictions for French",
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index ee79424..dd900a2 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.SharedPreferences;
+import android.graphics.Point;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.test.ServiceTestCase;
@@ -45,6 +46,7 @@
import com.android.inputmethod.latin.settings.DebugSettings;
import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.utils.LocaleUtils;
+import com.android.inputmethod.latin.utils.StringUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.Locale;
@@ -58,9 +60,11 @@
private static final String DEFAULT_AUTO_CORRECTION_THRESHOLD = "1";
// The message that sets the underline is posted with a 500 ms delay
- protected static final int DELAY_TO_WAIT_FOR_UNDERLINE = 500;
+ protected static final int DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS = 500;
// The message that sets predictions is posted with a 200 ms delay
- protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS = 200;
+ protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS = 200;
+ // We wait for gesture computation for this delay
+ protected static final int DELAY_TO_WAIT_FOR_GESTURE_MILLIS = 200;
private final int TIMEOUT_TO_WAIT_FOR_LOADING_MAIN_DICTIONARY_IN_SECONDS = 60;
// Type for a test phony dictionary
@@ -217,7 +221,7 @@
// Run messages to avoid the messages enqueued by startInputView() and its friends
// to run on a later call and ruin things. We need to wait first because some of them
// can be posted with a delay (notably, MSG_RESUME_SUGGESTIONS)
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
}
@@ -301,6 +305,47 @@
}
}
+ protected Point getXY(final int codePoint) {
+ final Key key = mKeyboard.getKey(codePoint);
+ if (key == null) {
+ throw new RuntimeException("Code point not on the keyboard");
+ } else {
+ return new Point(key.getX() + key.getWidth() / 2, key.getY() + key.getHeight() / 2);
+ }
+ }
+
+ protected void gesture(final String stringToGesture) {
+ if (StringUtils.codePointCount(stringToGesture) < 2) {
+ throw new RuntimeException("Can't gesture strings less than 2 chars long");
+ }
+
+ mLatinIME.onStartBatchInput();
+ final int startCodePoint = stringToGesture.codePointAt(0);
+ Point oldPoint = getXY(startCodePoint);
+ int timestamp = 0; // In milliseconds since the start of the gesture
+ final InputPointers pointers = new InputPointers(Constants.DEFAULT_GESTURE_POINTS_CAPACITY);
+ pointers.addPointer(oldPoint.x, oldPoint.y, 0 /* pointerId */, timestamp);
+
+ for (int i = Character.charCount(startCodePoint); i < stringToGesture.length();
+ i = stringToGesture.offsetByCodePoints(i, 1)) {
+ final Point newPoint = getXY(stringToGesture.codePointAt(i));
+ // Arbitrarily 0.5s between letters and 0.1 between events. Refine this later if needed.
+ final int STEPS = 5;
+ for (int j = 0; j < STEPS; ++j) {
+ timestamp += 100;
+ pointers.addPointer(oldPoint.x + ((newPoint.x - oldPoint.x) * j) / STEPS,
+ oldPoint.y + ((newPoint.y - oldPoint.y) * j) / STEPS,
+ 0 /* pointerId */, timestamp);
+ }
+ oldPoint.x = newPoint.x;
+ oldPoint.y = newPoint.y;
+ mLatinIME.onUpdateBatchInput(pointers);
+ }
+ mLatinIME.onEndBatchInput(pointers);
+ sleep(DELAY_TO_WAIT_FOR_GESTURE_MILLIS);
+ runMessages();
+ }
+
protected void waitForDictionariesToBeLoaded() {
try {
mLatinIME.waitForLoadingDictionaries(
diff --git a/tests/src/com/android/inputmethod/latin/PunctuationTests.java b/tests/src/com/android/inputmethod/latin/PunctuationTests.java
index 64750fb..3537918 100644
--- a/tests/src/com/android/inputmethod/latin/PunctuationTests.java
+++ b/tests/src/com/android/inputmethod/latin/PunctuationTests.java
@@ -38,7 +38,7 @@
try {
mLatinIME.loadSettings();
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
assertTrue("type word then type space should display punctuation strip",
mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
diff --git a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
index db3c9ba..8ba0174 100644
--- a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
+++ b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
@@ -75,7 +75,7 @@
repeatKey(Constants.CODE_DELETE);
}
assertFalse("Caps immediately after repeating Backspace a lot", isCapsModeAutoShifted());
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
assertTrue("Caps after a while after repeating Backspace a lot", isCapsModeAutoShifted());
}
diff --git a/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
index 273d7fa..2ef8b54 100644
--- a/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
+++ b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
@@ -16,21 +16,14 @@
package com.android.inputmethod.latin.settings;
-import static com.android.inputmethod.latin.settings.AccountsSettingsFragment.AUTHORITY;
-
-import android.accounts.Account;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.content.ContentResolver;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.MediumTest;
import android.view.View;
import android.widget.ListView;
-import com.android.inputmethod.latin.accounts.LoginAccountUtils;
-import com.android.inputmethod.latin.define.ProductionFlags;
-
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -39,9 +32,6 @@
extends ActivityInstrumentationTestCase2<TestFragmentActivity> {
private static final String FRAG_NAME = AccountsSettingsFragment.class.getName();
private static final long TEST_TIMEOUT_MILLIS = 5000;
- private static final String TEST_ACCOUNT_NAME = "AccountsSettingsFragmentTests";
- private static final Account TEST_ACCOUNT =
- new Account(TEST_ACCOUNT_NAME, LoginAccountUtils.ACCOUNT_TYPE);
private AlertDialog mDialog;
@@ -57,13 +47,6 @@
setActivityIntent(intent);
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- // reset the syncable state to unknown
- ContentResolver.setIsSyncable(TEST_ACCOUNT, AUTHORITY, -1);
- }
-
public void testEmptyAccounts() {
final AccountsSettingsFragment fragment =
(AccountsSettingsFragment) getActivity().mFragment;
@@ -146,57 +129,4 @@
assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_NEGATIVE).getVisibility());
assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_POSITIVE).getVisibility());
}
-
- public void testUpdateSyncPolicy_enable() {
- // This test is a no-op when ENABLE_PERSONAL_DICTIONARY_SYNC is not enabled
- if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
- return;
- }
- // Should be unknown by default.
- assertTrue(ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY) < 0);
-
- final AccountsSettingsFragment fragment =
- (AccountsSettingsFragment) getActivity().mFragment;
- fragment.updateSyncPolicy(true, TEST_ACCOUNT_NAME);
-
- // Should be syncable now.
- assertEquals(1, ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY));
- }
-
- public void testUpdateSyncPolicy_disable() {
- // This test is a no-op when ENABLE_PERSONAL_DICTIONARY_SYNC is not enabled
- if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
- return;
- }
- // Should be unknown by default.
- assertTrue(ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY) < 0);
-
- final AccountsSettingsFragment fragment =
- (AccountsSettingsFragment) getActivity().mFragment;
- fragment.updateSyncPolicy(false, TEST_ACCOUNT_NAME);
-
- // Should not be syncable now.
- assertEquals(0, ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY));
- }
-
- public void testUpdateSyncPolicy_enableDisable() {
- // This test is a no-op when ENABLE_PERSONAL_DICTIONARY_SYNC is not enabled
- if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
- return;
- }
- // Should be unknown by default.
- assertTrue(ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY) < 0);
-
- final AccountsSettingsFragment fragment =
- (AccountsSettingsFragment) getActivity().mFragment;
- fragment.updateSyncPolicy(true, TEST_ACCOUNT_NAME);
-
- // Should be syncable now.
- assertEquals(1, ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY));
-
- fragment.updateSyncPolicy(false, TEST_ACCOUNT_NAME);
-
- // Should not be syncable now.
- assertEquals(0, ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY));
- }
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java b/tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java
deleted file mode 100644
index 5831226..0000000
--- a/tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2010 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.utils;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-@SmallTest
-public class EditDistanceTests extends AndroidTestCase {
- /*
- * dist(kitten, sitting) == 3
- *
- * kitten-
- * .|||.|
- * sitting
- */
- public void testExample1() {
- final int dist = BinaryDictionaryUtils.editDistance("kitten", "sitting");
- assertEquals("edit distance between 'kitten' and 'sitting' is 3",
- 3, dist);
- }
-
- /*
- * dist(Sunday, Saturday) == 3
- *
- * Saturday
- * | |.|||
- * S--unday
- */
- public void testExample2() {
- final int dist = BinaryDictionaryUtils.editDistance("Saturday", "Sunday");
- assertEquals("edit distance between 'Saturday' and 'Sunday' is 3",
- 3, dist);
- }
-
- public void testBothEmpty() {
- final int dist = BinaryDictionaryUtils.editDistance("", "");
- assertEquals("when both string are empty, no edits are needed",
- 0, dist);
- }
-
- public void testFirstArgIsEmpty() {
- final int dist = BinaryDictionaryUtils.editDistance("", "aaaa");
- assertEquals("when only one string of the arguments is empty,"
- + " the edit distance is the length of the other.",
- 4, dist);
- }
-
- public void testSecoondArgIsEmpty() {
- final int dist = BinaryDictionaryUtils.editDistance("aaaa", "");
- assertEquals("when only one string of the arguments is empty,"
- + " the edit distance is the length of the other.",
- 4, dist);
- }
-
- public void testSameStrings() {
- final String arg1 = "The quick brown fox jumps over the lazy dog.";
- final String arg2 = "The quick brown fox jumps over the lazy dog.";
- final int dist = BinaryDictionaryUtils.editDistance(arg1, arg2);
- assertEquals("when same strings are passed, distance equals 0.",
- 0, dist);
- }
-
- public void testSameReference() {
- final String arg = "The quick brown fox jumps over the lazy dog.";
- final int dist = BinaryDictionaryUtils.editDistance(arg, arg);
- assertEquals("when same string references are passed, the distance equals 0.",
- 0, dist);
- }
-
- public void testNullArg() {
- try {
- BinaryDictionaryUtils.editDistance(null, "aaa");
- fail("IllegalArgumentException should be thrown.");
- } catch (Exception e) {
- assertTrue(e instanceof IllegalArgumentException);
- }
- try {
- BinaryDictionaryUtils.editDistance("aaa", null);
- fail("IllegalArgumentException should be thrown.");
- } catch (Exception e) {
- assertTrue(e instanceof IllegalArgumentException);
- }
- }
-}