aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java41
-rw-r--r--java/src/com/android/inputmethod/event/Event.java78
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java8
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java23
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/LanguageOnSpacebarHelper.java68
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/NeedsToDisplayLanguage.java44
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java35
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java4
-rw-r--r--java/src/com/android/inputmethod/latin/Dictionary.java14
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryCollection.java9
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java17
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java34
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java11
-rw-r--r--java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java9
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java13
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java5
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java5
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java30
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java30
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java2
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java3
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java3
22 files changed, 301 insertions, 185 deletions
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index 8badaf4b9..4a8fa51ee 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -45,10 +45,8 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
// This is the first released version of the database that implements CLIENTID. It is
// used to identify the versions for upgrades. This should never change going forward.
private static final int METADATA_DATABASE_VERSION_WITH_CLIENTID = 6;
- // This is the current database version. It should be updated when the database schema
- // gets updated. It is passed to the framework constructor of SQLiteOpenHelper, so
- // that's what the framework uses to track our database version.
- private static final int METADATA_DATABASE_VERSION = 6;
+ // The current database version.
+ private static final int CURRENT_METADATA_DATABASE_VERSION = 7;
private final static long NOT_A_DOWNLOAD_ID = -1;
@@ -169,7 +167,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
private MetadataDbHelper(final Context context, final String clientId) {
super(context,
METADATA_DATABASE_NAME_STEM + (TextUtils.isEmpty(clientId) ? "" : "." + clientId),
- null, METADATA_DATABASE_VERSION);
+ null, CURRENT_METADATA_DATABASE_VERSION);
mContext = context;
mClientId = clientId;
}
@@ -219,22 +217,45 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
/**
* Upgrade the database. Upgrade from version 3 is supported.
+ * Version 3 has a DB named METADATA_DATABASE_NAME_STEM containing a table METADATA_TABLE_NAME.
+ * Version 6 and above has a DB named METADATA_DATABASE_NAME_STEM containing a
+ * table CLIENT_TABLE_NAME, and for each client a table called METADATA_TABLE_STEM + "." + the
+ * name of the client and contains a table METADATA_TABLE_NAME.
+ * For schemas, see the above create statements. The schemas have never changed so far.
+ *
+ * This method is called by the framework. See {@link SQLiteOpenHelper#onUpgrade}
+ * @param db The database we are upgrading
+ * @param oldVersion The old database version (the one on the disk)
+ * @param newVersion The new database version as supplied to the constructor of SQLiteOpenHelper
*/
@Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
if (METADATA_DATABASE_INITIAL_VERSION == oldVersion
- && METADATA_DATABASE_VERSION_WITH_CLIENTID == newVersion) {
+ && METADATA_DATABASE_VERSION_WITH_CLIENTID <= newVersion
+ && CURRENT_METADATA_DATABASE_VERSION >= newVersion) {
// Upgrade from version METADATA_DATABASE_INITIAL_VERSION to version
// METADATA_DATABASE_VERSION_WITH_CLIENT_ID
+ // Only the default database should contain the client table, so we test for mClientId.
if (TextUtils.isEmpty(mClientId)) {
- // Only the default database should contain the client table.
- // Anyway in version 3 only the default table existed so the emptyness
+ // Anyway in version 3 only the default table existed so the emptiness
// test should always be true, but better check to be sure.
createClientTable(db);
}
+ } else if (METADATA_DATABASE_VERSION_WITH_CLIENTID < newVersion
+ && CURRENT_METADATA_DATABASE_VERSION >= newVersion) {
+ // Here we drop the client table, so that all clients send us their information again.
+ // The client table contains the URL to hit to update the available dictionaries list,
+ // but the info about the dictionaries themselves is stored in the table called
+ // METADATA_TABLE_NAME and we want to keep it, so we only drop the client table.
+ db.execSQL("DROP TABLE IF EXISTS " + CLIENT_TABLE_NAME);
+ // Only the default database should contain the client table, so we test for mClientId.
+ if (TextUtils.isEmpty(mClientId)) {
+ createClientTable(db);
+ }
} else {
- // Version 3 was the earliest version, so we should never come here. If we do, we
- // have no idea what this database is, so we'd better wipe it off.
+ // If we're not in the above case, either we are upgrading from an earlier versionCode
+ // and we should wipe the database, or we are handling a version we never heard about
+ // (can only be a bug) so it's safer to wipe the database.
db.execSQL("DROP TABLE IF EXISTS " + METADATA_TABLE_NAME);
db.execSQL("DROP TABLE IF EXISTS " + CLIENT_TABLE_NAME);
onCreate(db);
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index 646590948..6535d2d76 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -36,25 +36,25 @@ public class Event {
// Should the types below be represented by separate classes instead? It would be cleaner
// but probably a bit too much
// An event we don't handle in Latin IME, for example pressing Ctrl on a hardware keyboard.
- final public static int EVENT_NOT_HANDLED = 0;
+ final public static int EVENT_TYPE_NOT_HANDLED = 0;
// A key press that is part of input, for example pressing an alphabetic character on a
// hardware qwerty keyboard. It may be part of a sequence that will be re-interpreted later
// through combination.
- final public static int EVENT_INPUT_KEYPRESS = 1;
+ final public static int EVENT_TYPE_INPUT_KEYPRESS = 1;
// A toggle event is triggered by a key that affects the previous character. An example would
// be a numeric key on a 10-key keyboard, which would toggle between 1 - a - b - c with
// repeated presses.
- final public static int EVENT_TOGGLE = 2;
+ final public static int EVENT_TYPE_TOGGLE = 2;
// A mode event instructs the combiner to change modes. The canonical example would be the
// hankaku/zenkaku key on a Japanese keyboard, or even the caps lock key on a qwerty keyboard
// if handled at the combiner level.
- final public static int EVENT_MODE_KEY = 3;
+ final public static int EVENT_TYPE_MODE_KEY = 3;
// An event corresponding to a gesture.
- final public static int EVENT_GESTURE = 4;
+ final public static int EVENT_TYPE_GESTURE = 4;
// An event corresponding to the manual pick of a suggestion.
- final public static int EVENT_SUGGESTION_PICKED = 5;
+ final public static int EVENT_TYPE_SUGGESTION_PICKED = 5;
// An event corresponding to a string generated by some software process.
- final public static int EVENT_SOFTWARE_GENERATED_STRING = 6;
+ final public static int EVENT_TYPE_SOFTWARE_GENERATED_STRING = 6;
// 0 is a valid code point, so we use -1 here.
final public static int NOT_A_CODE_POINT = -1;
@@ -66,7 +66,7 @@ public class Event {
// or dead-abovering.
final private static int FLAG_DEAD = 0x1;
- final private int mType; // The type of event - one of the constants above
+ final private int mEventType; // The type of event - one of the constants above
// The code point associated with the event, if relevant. This is a unicode code point, and
// has nothing to do with other representations of the key. It is only relevant if this event
// is of KEYPRESS type, but for a mode key like hankaku/zenkaku or ctrl, there is no code point
@@ -94,7 +94,7 @@ public class Event {
// Some flags that can't go into the key code. It's a bit field of FLAG_*
final private int mFlags;
- // If this is of type EVENT_SUGGESTION_PICKED, this must not be null (and must be null in
+ // If this is of type EVENT_TYPE_SUGGESTION_PICKED, this must not be null (and must be null in
// other cases).
final public SuggestedWordInfo mSuggestedWordInfo;
@@ -105,7 +105,7 @@ public class Event {
private Event(final int type, final CharSequence text, final int codePoint, final int keyCode,
final int x, final int y, final SuggestedWordInfo suggestedWordInfo, final int flags,
final Event next) {
- mType = type;
+ mEventType = type;
mText = text;
mCodePoint = codePoint;
mKeyCode = keyCode;
@@ -116,7 +116,7 @@ public class Event {
mNextEvent = next;
// Sanity checks
// mSuggestedWordInfo is non-null if and only if the type is SUGGESTION_PICKED
- if (EVENT_SUGGESTION_PICKED == mType) {
+ if (EVENT_TYPE_SUGGESTION_PICKED == mEventType) {
if (null == mSuggestedWordInfo) {
throw new RuntimeException("Wrong event: SUGGESTION_PICKED event must have a "
+ "non-null SuggestedWordInfo");
@@ -131,13 +131,13 @@ public class Event {
public static Event createSoftwareKeypressEvent(final int codePoint, final int keyCode,
final int x, final int y) {
- return new Event(EVENT_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, x, y,
- null /* suggestedWordInfo */, FLAG_NONE, null);
+ return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, x, y,
+ null /* suggestedWordInfo */, FLAG_NONE, null /* next */);
}
public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode,
final Event next) {
- return new Event(EVENT_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
+ return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE,
null /* suggestedWordInfo */, FLAG_NONE, next);
}
@@ -145,7 +145,7 @@ public class Event {
// This creates an input event for a dead character. @see {@link #FLAG_DEAD}
public static Event createDeadEvent(final int codePoint, final int keyCode, final Event next) {
// TODO: add an argument or something if we ever create a software layout with dead keys.
- return new Event(EVENT_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
+ return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE,
null /* suggestedWordInfo */, FLAG_DEAD, next);
}
@@ -159,7 +159,7 @@ public class Event {
*/
public static Event createEventForCodePointFromUnknownSource(final int codePoint) {
// TODO: should we have a different type of event for this? After all, it's not a key press.
- return new Event(EVENT_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE,
+ return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
null /* suggestedWordInfo */, FLAG_NONE, null /* next */);
}
@@ -175,8 +175,8 @@ public class Event {
public static Event createEventForCodePointFromAlreadyTypedText(final int codePoint,
final int x, final int y) {
// TODO: should we have a different type of event for this? After all, it's not a key press.
- return new Event(EVENT_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE, x, y,
- null /* suggestedWordInfo */, FLAG_NONE, null /* next */);
+ return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE,
+ x, y, null /* suggestedWordInfo */, FLAG_NONE, null /* next */);
}
/**
@@ -184,10 +184,10 @@ public class Event {
* @return an event for this suggestion pick.
*/
public static Event createSuggestionPickedEvent(final SuggestedWordInfo suggestedWordInfo) {
- return new Event(EVENT_SUGGESTION_PICKED, suggestedWordInfo.mWord,
+ return new Event(EVENT_TYPE_SUGGESTION_PICKED, suggestedWordInfo.mWord,
NOT_A_CODE_POINT, NOT_A_KEY_CODE,
Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE,
- suggestedWordInfo, FLAG_NONE, null);
+ suggestedWordInfo, FLAG_NONE, null /* next */);
}
/**
@@ -199,13 +199,26 @@ public class Event {
* @return an event for this text.
*/
public static Event createSoftwareTextEvent(final CharSequence text, final int keyCode) {
- return new Event(EVENT_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode,
+ return new Event(EVENT_TYPE_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
null /* suggestedWordInfo */, FLAG_NONE, null /* next */);
}
+ /**
+ * Creates an input event representing the manual pick of a punctuation suggestion.
+ * @return an event for this suggestion pick.
+ */
+ public static Event createPunctuationSuggestionPickedEvent(
+ final SuggestedWordInfo suggestedWordInfo) {
+ final int primaryCode = suggestedWordInfo.mWord.charAt(0);
+ return new Event(EVENT_TYPE_SUGGESTION_PICKED, suggestedWordInfo.mWord, primaryCode,
+ NOT_A_KEY_CODE, Constants.SUGGESTION_STRIP_COORDINATE,
+ Constants.SUGGESTION_STRIP_COORDINATE, suggestedWordInfo, FLAG_NONE,
+ null /* next */);
+ }
+
public static Event createNotHandledEvent() {
- return new Event(EVENT_NOT_HANDLED, null /* text */, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
+ return new Event(EVENT_TYPE_NOT_HANDLED, null /* text */, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
null /* suggestedWordInfo */, FLAG_NONE, null);
}
@@ -218,25 +231,26 @@ public class Event {
// Returns whether this is a fake key press from the suggestion strip. This happens with
// punctuation signs selected from the suggestion strip.
public boolean isSuggestionStripPress() {
- return EVENT_INPUT_KEYPRESS == mType && Constants.SUGGESTION_STRIP_COORDINATE == mX;
+ return EVENT_TYPE_SUGGESTION_PICKED == mEventType;
}
public boolean isHandled() {
- return EVENT_NOT_HANDLED != mType;
+ return EVENT_TYPE_NOT_HANDLED != mEventType;
}
public CharSequence getTextToCommit() {
- switch (mType) {
- case EVENT_MODE_KEY:
- case EVENT_NOT_HANDLED:
- case EVENT_TOGGLE:
+ switch (mEventType) {
+ case EVENT_TYPE_MODE_KEY:
+ case EVENT_TYPE_NOT_HANDLED:
+ case EVENT_TYPE_TOGGLE:
return "";
- case EVENT_INPUT_KEYPRESS:
+ case EVENT_TYPE_INPUT_KEYPRESS:
return StringUtils.newSingleCodePointString(mCodePoint);
- case EVENT_GESTURE:
- case EVENT_SOFTWARE_GENERATED_STRING:
+ case EVENT_TYPE_GESTURE:
+ case EVENT_TYPE_SOFTWARE_GENERATED_STRING:
+ case EVENT_TYPE_SUGGESTION_PICKED:
return mText;
}
- throw new RuntimeException("Unknown event type: " + mType);
+ throw new RuntimeException("Unknown event type: " + mEventType);
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 37a4bf8f6..fd0be6f92 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -204,10 +204,12 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
keyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
final boolean subtypeChanged = (oldKeyboard == null)
|| !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
- final boolean needsToDisplayLanguage = mSubtypeSwitcher.needsToDisplayLanguage(
+ final int languageOnSpacebarFormatType = mSubtypeSwitcher.getLanguageOnSpacebarFormatType(
keyboard.mId.mSubtype);
- keyboardView.startDisplayLanguageOnSpacebar(subtypeChanged, needsToDisplayLanguage,
- RichInputMethodManager.getInstance().hasMultipleEnabledIMEsOrSubtypes(true));
+ final boolean hasMultipleEnabledIMEsOrSubtypes = RichInputMethodManager.getInstance()
+ .hasMultipleEnabledIMEsOrSubtypes(true /* shouldIncludeAuxiliarySubtypes */);
+ keyboardView.startDisplayLanguageOnSpacebar(subtypeChanged, languageOnSpacebarFormatType,
+ hasMultipleEnabledIMEsOrSubtypes);
}
public Keyboard getKeyboard() {
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 03425ef1f..0f9c39a80 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -49,6 +49,7 @@ import com.android.inputmethod.keyboard.internal.GestureTrailsDrawingPreview;
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
import com.android.inputmethod.keyboard.internal.KeyPreviewChoreographer;
import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams;
+import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
import com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper;
import com.android.inputmethod.keyboard.internal.SlidingKeyInputDrawingPreview;
import com.android.inputmethod.keyboard.internal.TimerHandler;
@@ -123,7 +124,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
// Stuff to draw language name on spacebar.
private final int mLanguageOnSpacebarFinalAlpha;
private ObjectAnimator mLanguageOnSpacebarFadeoutAnimator;
- private boolean mNeedsToDisplayLanguage;
+ private int mLanguageOnSpacebarFormatType;
private boolean mHasMultipleEnabledIMEsOrSubtypes;
private int mLanguageOnSpacebarAnimAlpha = Constants.Color.ALPHA_OPAQUE;
private final float mLanguageOnSpacebarTextRatio;
@@ -811,14 +812,16 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
}
public void startDisplayLanguageOnSpacebar(final boolean subtypeChanged,
- final boolean needsToDisplayLanguage, final boolean hasMultipleEnabledIMEsOrSubtypes) {
- mNeedsToDisplayLanguage = needsToDisplayLanguage;
+ final int languageOnSpacebarFormatType,
+ final boolean hasMultipleEnabledIMEsOrSubtypes) {
+ mLanguageOnSpacebarFormatType = languageOnSpacebarFormatType;
mHasMultipleEnabledIMEsOrSubtypes = hasMultipleEnabledIMEsOrSubtypes;
final ObjectAnimator animator = mLanguageOnSpacebarFadeoutAnimator;
if (animator == null) {
- mNeedsToDisplayLanguage = false;
+ mLanguageOnSpacebarFormatType = LanguageOnSpacebarHelper.FORMAT_TYPE_NONE;
} else {
- if (subtypeChanged && needsToDisplayLanguage) {
+ if (subtypeChanged
+ && languageOnSpacebarFormatType != LanguageOnSpacebarHelper.FORMAT_TYPE_NONE) {
setLanguageOnSpacebarAnimAlpha(Constants.Color.ALPHA_OPAQUE);
if (animator.isStarted()) {
animator.cancel();
@@ -919,9 +922,11 @@ 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 = SpacebarLanguageUtils.getFullDisplayName(subtype);
- if (fitsTextIntoWidth(width, fullText, paint)) {
- return fullText;
+ if (mLanguageOnSpacebarFormatType == LanguageOnSpacebarHelper.FORMAT_TYPE_FULL_LOCALE) {
+ final String fullText = SpacebarLanguageUtils.getFullDisplayName(subtype);
+ if (fitsTextIntoWidth(width, fullText, paint)) {
+ return fullText;
+ }
}
final String middleText = SpacebarLanguageUtils.getMiddleDisplayName(subtype);
@@ -937,7 +942,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
final int height = key.getHeight();
// If input language are explicitly selected.
- if (mNeedsToDisplayLanguage) {
+ if (mLanguageOnSpacebarFormatType != LanguageOnSpacebarHelper.FORMAT_TYPE_NONE) {
paint.setTextAlign(Align.CENTER);
paint.setTypeface(Typeface.DEFAULT);
paint.setTextSize(mLanguageOnSpacebarTextSize);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/LanguageOnSpacebarHelper.java b/java/src/com/android/inputmethod/keyboard/internal/LanguageOnSpacebarHelper.java
new file mode 100644
index 000000000..6400a2440
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/LanguageOnSpacebarHelper.java
@@ -0,0 +1,68 @@
+/*
+ * 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.keyboard.internal;
+
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This class determines that the language name on the spacebar should be displayed in what format.
+ */
+public final class LanguageOnSpacebarHelper {
+ public static final int FORMAT_TYPE_NONE = 0;
+ public static final int FORMAT_TYPE_LANGUAGE_ONLY = 1;
+ public static final int FORMAT_TYPE_FULL_LOCALE = 2;
+
+ private List<InputMethodSubtype> mEnabledSubtypes = Collections.emptyList();
+ private boolean mIsSystemLanguageSameAsInputLanguage;
+
+ public int getLanguageOnSpacebarFormatType(final InputMethodSubtype subtype) {
+ if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+ return FORMAT_TYPE_FULL_LOCALE;
+ }
+ // Only this subtype is enabled and equals to the system locale.
+ if (mEnabledSubtypes.size() < 2 && mIsSystemLanguageSameAsInputLanguage) {
+ return FORMAT_TYPE_NONE;
+ }
+ final String keyboardLanguage = SubtypeLocaleUtils.getSubtypeLocale(subtype).getLanguage();
+ final String keyboardLayout = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype);
+ int sameLanguageAndLayoutCount = 0;
+ for (final InputMethodSubtype ims : mEnabledSubtypes) {
+ final String language = SubtypeLocaleUtils.getSubtypeLocale(ims).getLanguage();
+ if (keyboardLanguage.equals(language) && keyboardLayout.equals(
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(ims))) {
+ sameLanguageAndLayoutCount++;
+ }
+ }
+ // Display full locale name only when there are multiple subtypes that have the same
+ // locale and keyboard layout. Otherwise displaying language name is enough.
+ return sameLanguageAndLayoutCount > 1 ? FORMAT_TYPE_FULL_LOCALE
+ : FORMAT_TYPE_LANGUAGE_ONLY;
+ }
+
+ public void updateEnabledSubtypes(final List<InputMethodSubtype> enabledSubtypes) {
+ mEnabledSubtypes = enabledSubtypes;
+ }
+
+ public void updateIsSystemLanguageSameAsInputLanguage(final boolean isSame) {
+ mIsSystemLanguageSameAsInputLanguage = isSame;
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/NeedsToDisplayLanguage.java b/java/src/com/android/inputmethod/keyboard/internal/NeedsToDisplayLanguage.java
deleted file mode 100644
index e548de589..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/NeedsToDisplayLanguage.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.keyboard.internal;
-
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
-
-/**
- * This class determines that the language name on the spacebar should be displayed or not.
- */
-public final class NeedsToDisplayLanguage {
- private int mEnabledSubtypeCount;
- private boolean mIsSystemLanguageSameAsInputLanguage;
-
- public boolean needsToDisplayLanguage(final InputMethodSubtype subtype) {
- if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
- return true;
- }
- return mEnabledSubtypeCount >= 2 || !mIsSystemLanguageSameAsInputLanguage;
- }
-
- public void updateEnabledSubtypeCount(final int count) {
- mEnabledSubtypeCount = count;
- }
-
- public void updateIsSystemLanguageSameAsInputLanguage(final boolean isSame) {
- mIsSystemLanguageSameAsInputLanguage = isSame;
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 60ac1ba48..30c2dfedb 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -89,6 +89,8 @@ public final class BinaryDictionary extends Dictionary {
private final long mDictSize;
private final String mDictFilePath;
private final boolean mIsUpdatable;
+ private boolean mHasUpdated;
+
private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
private final int[] mOutputSuggestionCount = new int[1];
private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS];
@@ -97,6 +99,7 @@ public final class BinaryDictionary extends Dictionary {
private final int[] mOutputTypes = new int[MAX_RESULTS];
// Only one result is ever used
private final int[] mOutputAutoCommitFirstWordConfidence = new int[1];
+ private final float[] mInputOutputLanguageWeight = new float[1];
private final NativeSuggestOptions mNativeSuggestOptions = new NativeSuggestOptions();
@@ -137,6 +140,7 @@ public final class BinaryDictionary extends Dictionary {
mDictSize = length;
mDictFilePath = filename;
mIsUpdatable = isUpdatable;
+ mHasUpdated = false;
mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
loadDictionary(filename, offset, length, isUpdatable);
}
@@ -167,7 +171,7 @@ public final class BinaryDictionary extends Dictionary {
int[] pointerIds, int[] inputCodePoints, int inputSize, int[] suggestOptions,
int[] prevWordCodePointArray, int[] outputSuggestionCount, int[] outputCodePoints,
int[] outputScores, int[] outputIndices, int[] outputTypes,
- int[] outputAutoCommitFirstWordConfidence);
+ int[] outputAutoCommitFirstWordConfidence, float[] inOutLanguageWeight);
private static native void addUnigramWordNative(long dict, int[] word, int probability,
int[] shortcutTarget, int shortcutProbability, boolean isNotAWord,
boolean isBlacklisted, int timestamp);
@@ -184,6 +188,7 @@ public final class BinaryDictionary extends Dictionary {
// TODO: Move native dict into session
private final void loadDictionary(final String path, final long startOffset,
final long length, final boolean isUpdatable) {
+ mHasUpdated = false;
mNativeDict = openNative(path, startOffset, length, isUpdatable);
}
@@ -231,16 +236,17 @@ public final class BinaryDictionary extends Dictionary {
@Override
public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
- final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+ final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+ final float[] inOutLanguageWeight) {
return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords,
- additionalFeaturesOptions, 0 /* sessionId */);
+ additionalFeaturesOptions, 0 /* sessionId */, inOutLanguageWeight);
}
@Override
public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
- final int sessionId) {
+ final int sessionId, final float[] inOutLanguageWeight) {
if (!isValidDictionary()) return null;
Arrays.fill(mInputCodePoints, Constants.NOT_A_CODE);
@@ -261,13 +267,22 @@ public final class BinaryDictionary extends Dictionary {
final int inputSize = isGesture ? ips.getPointerSize() : composerSize;
mNativeSuggestOptions.setIsGesture(isGesture);
mNativeSuggestOptions.setAdditionalFeaturesOptions(additionalFeaturesOptions);
+ if (inOutLanguageWeight != null) {
+ mInputOutputLanguageWeight[0] = inOutLanguageWeight[0];
+ } else {
+ mInputOutputLanguageWeight[0] = Dictionary.NOT_A_LANGUAGE_WEIGHT;
+ }
// proximityInfo and/or prevWordForBigrams may not be null.
getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
getTraverseSession(sessionId).getSession(), ips.getXCoordinates(),
ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(), mInputCodePoints,
inputSize, mNativeSuggestOptions.getOptions(),
prevWordCodePointArray, mOutputSuggestionCount, mOutputCodePoints, mOutputScores,
- mSpaceIndices, mOutputTypes, mOutputAutoCommitFirstWordConfidence);
+ mSpaceIndices, mOutputTypes, mOutputAutoCommitFirstWordConfidence,
+ mInputOutputLanguageWeight);
+ if (inOutLanguageWeight != null) {
+ inOutLanguageWeight[0] = mInputOutputLanguageWeight[0];
+ }
final int count = mOutputSuggestionCount[0];
final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList();
for (int j = 0; j < count; ++j) {
@@ -390,6 +405,7 @@ public final class BinaryDictionary extends Dictionary {
StringUtils.toCodePointArray(shortcutTarget) : null;
addUnigramWordNative(mNativeDict, codePoints, probability, shortcutTargetCodePoints,
shortcutProbability, isNotAWord, isBlacklisted, timestamp);
+ mHasUpdated = true;
}
// Add a bigram entry to binary dictionary with timestamp in native code.
@@ -401,6 +417,7 @@ public final class BinaryDictionary extends Dictionary {
final int[] codePoints0 = StringUtils.toCodePointArray(word0);
final int[] codePoints1 = StringUtils.toCodePointArray(word1);
addBigramWordsNative(mNativeDict, codePoints0, codePoints1, probability, timestamp);
+ mHasUpdated = true;
}
// Remove a bigram entry form binary dictionary in native code.
@@ -411,6 +428,7 @@ public final class BinaryDictionary extends Dictionary {
final int[] codePoints0 = StringUtils.toCodePointArray(word0);
final int[] codePoints1 = StringUtils.toCodePointArray(word1);
removeBigramWordsNative(mNativeDict, codePoints0, codePoints1);
+ mHasUpdated = true;
}
public void addMultipleDictionaryEntries(final LanguageModelParam[] languageModelParams) {
@@ -422,6 +440,7 @@ public final class BinaryDictionary extends Dictionary {
}
processedParamCount = addMultipleDictionaryEntriesNative(mNativeDict,
languageModelParams, processedParamCount);
+ mHasUpdated = true;
if (processedParamCount <= 0) {
return;
}
@@ -440,8 +459,10 @@ public final class BinaryDictionary extends Dictionary {
public void flush() {
if (!isValidDictionary()) return;
- flushNative(mNativeDict, mDictFilePath);
- reopen();
+ if (mHasUpdated) {
+ flushNative(mNativeDict, mDictFilePath);
+ reopen();
+ }
}
public void flushWithGC() {
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 4e17f8389..d5873d70f 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -100,10 +100,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
});
}
- public void reopen(final Context context) {
- registerObserver(context);
- }
-
@Override
public synchronized void close() {
if (mObserver != null) {
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index e04524843..0742fbde9 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
*/
public abstract class Dictionary {
public static final int NOT_A_PROBABILITY = -1;
+ public static final float NOT_A_LANGUAGE_WEIGHT = -1.0f;
// The following types do not actually come from real dictionary instances, so we create
// corresponding instances.
@@ -70,22 +71,26 @@ public abstract class Dictionary {
* @param proximityInfo the object for key proximity. May be ignored by some implementations.
* @param blockOffensiveWords whether to block potentially offensive words
* @param additionalFeaturesOptions options about additional features used for the suggestion.
+ * @param inOutLanguageWeight the language weight used for generating suggestions.
+ * inOutLanguageWeight is a float array that has only one element. This can be updated when the
+ * different language weight is used.
* @return the list of suggestions (possibly null if none)
*/
// TODO: pass more context than just the previous word, to enable better suggestions (n-gram
// and more)
abstract public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
- final boolean blockOffensiveWords, final int[] additionalFeaturesOptions);
+ final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+ final float[] inOutLanguageWeight);
// The default implementation of this method ignores sessionId.
// Subclasses that want to use sessionId need to override this method.
public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
- final int sessionId) {
+ final int sessionId, final float[] inOutLanguageWeight) {
return getSuggestions(composer, prevWord, proximityInfo, blockOffensiveWords,
- additionalFeaturesOptions);
+ additionalFeaturesOptions, inOutLanguageWeight);
}
/**
@@ -159,7 +164,8 @@ public abstract class Dictionary {
@Override
public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
- final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+ final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+ final float[] inOutLanguageWeight) {
return null;
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index bf075140e..16173fffc 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -58,18 +58,21 @@ public final class DictionaryCollection extends Dictionary {
@Override
public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
- final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+ final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+ final float[] inOutLanguageWeight) {
final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries;
if (dictionaries.isEmpty()) return null;
// To avoid creating unnecessary objects, we get the list out of the first
// dictionary and add the rest to it if not null, hence the get(0)
ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getSuggestions(composer,
- prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions);
+ prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions,
+ inOutLanguageWeight);
if (null == suggestions) suggestions = CollectionUtils.newArrayList();
final int length = dictionaries.size();
for (int i = 1; i < length; ++ i) {
final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getSuggestions(composer,
- prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions);
+ prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions,
+ inOutLanguageWeight);
if (null != sugg) suggestions.addAll(sugg);
}
return suggestions;
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index ae2d7c9c6..7cb218fbe 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -36,7 +36,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
-import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -54,6 +53,15 @@ public class DictionaryFacilitatorForSuggest {
// To synchronize assigning mDictionaries to ensure closing dictionaries.
private Object mLock = new Object();
+ private static final String[] dictTypesOrderedToGetSuggestion =
+ new String[] {
+ Dictionary.TYPE_MAIN,
+ Dictionary.TYPE_USER_HISTORY,
+ Dictionary.TYPE_PERSONALIZATION,
+ Dictionary.TYPE_USER,
+ Dictionary.TYPE_CONTACTS
+ };
+
/**
* Class contains dictionaries for a locale.
*/
@@ -453,11 +461,14 @@ public class DictionaryFacilitatorForSuggest {
final Map<String, Dictionary> dictMap = dictionaries.mDictMap;
final SuggestionResults suggestionResults =
new SuggestionResults(dictionaries.mLocale, SuggestedWords.MAX_SUGGESTIONS);
- for (final Dictionary dictionary : dictMap.values()) {
+ final float[] languageWeight = new float[] { Dictionary.NOT_A_LANGUAGE_WEIGHT };
+ for (final String dictType : dictTypesOrderedToGetSuggestion) {
+ final Dictionary dictionary = dictMap.get(dictType);
if (null == dictionary) continue;
final ArrayList<SuggestedWordInfo> dictionarySuggestions =
dictionary.getSuggestionsWithSessionId(composer, prevWord, proximityInfo,
- blockOffensiveWords, additionalFeaturesOptions, sessionId);
+ blockOffensiveWords, additionalFeaturesOptions, sessionId,
+ languageWeight);
if (null == dictionarySuggestions) continue;
suggestionResults.addAll(dictionarySuggestions);
if (null != rawSuggestions) {
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 92b535458..64e9d2b51 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -262,6 +262,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
@Override
public void run() {
+ if (mBinaryDictionary == null) {
+ return;
+ }
runGCAfterAllPrioritizedTasksIfRequiredLocked(mindsBlockByGC);
}
});
@@ -274,9 +277,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
}
private void runGCAfterAllPrioritizedTasksIfRequiredLocked(final boolean mindsBlockByGC) {
- if (mBinaryDictionary == null) {
- return;
- }
// needsToRunGC() have to be called with lock.
if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) {
if (setProcessingLargeTaskIfNot()) {
@@ -301,9 +301,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
protected void addWordDynamically(final String word, final int frequency,
final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord,
final boolean isBlacklisted, final int timestamp) {
+ reloadDictionaryIfRequired();
ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
@Override
public void run() {
+ if (mBinaryDictionary == null) {
+ return;
+ }
runGCAfterAllPrioritizedTasksIfRequiredLocked(true /* mindsBlockByGC */);
addWordDynamicallyLocked(word, frequency, shortcutTarget, shortcutFreq,
isNotAWord, isBlacklisted, timestamp);
@@ -323,9 +327,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
*/
protected void addBigramDynamically(final String word0, final String word1,
final int frequency, final int timestamp) {
+ reloadDictionaryIfRequired();
ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
@Override
public void run() {
+ if (mBinaryDictionary == null) {
+ return;
+ }
runGCAfterAllPrioritizedTasksIfRequiredLocked(true /* mindsBlockByGC */);
addBigramDynamicallyLocked(word0, word1, frequency, timestamp);
}
@@ -341,9 +349,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
* Dynamically remove a word bigram in the dictionary.
*/
protected void removeBigramDynamically(final String word0, final String word1) {
+ reloadDictionaryIfRequired();
ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
@Override
public void run() {
+ if (mBinaryDictionary == null) {
+ return;
+ }
runGCAfterAllPrioritizedTasksIfRequiredLocked(true /* mindsBlockByGC */);
mBinaryDictionary.removeBigramWords(word0, word1);
}
@@ -360,14 +372,15 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
protected void addMultipleDictionaryEntriesDynamically(
final ArrayList<LanguageModelParam> languageModelParams,
final AddMultipleDictionaryEntriesCallback callback) {
+ reloadDictionaryIfRequired();
ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
@Override
public void run() {
+ if (mBinaryDictionary == null) {
+ return;
+ }
final boolean locked = setProcessingLargeTaskIfNot();
try {
- if (mBinaryDictionary == null) {
- return;
- }
mBinaryDictionary.addMultipleDictionaryEntries(
languageModelParams.toArray(
new LanguageModelParam[languageModelParams.size()]));
@@ -387,7 +400,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
- final int sessionId) {
+ final int sessionId, final float[] inOutLanguageWeight) {
reloadDictionaryIfRequired();
if (processingLargeTask()) {
return null;
@@ -404,7 +417,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
final ArrayList<SuggestedWordInfo> binarySuggestion =
mBinaryDictionary.getSuggestionsWithSessionId(composer, prevWord,
proximityInfo, blockOffensiveWords, additionalFeaturesOptions,
- sessionId);
+ sessionId, inOutLanguageWeight);
holder.set(binarySuggestion);
if (mBinaryDictionary.isCorrupted()) {
removeBinaryDictionaryLocked();
@@ -417,9 +430,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
@Override
public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
- final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+ final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+ final float[] inOutLanguageWeight) {
return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords,
- additionalFeaturesOptions, 0 /* sessionId */);
+ additionalFeaturesOptions, 0 /* sessionId */, inOutLanguageWeight);
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 53e6232b6..b4807b01a 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -156,7 +156,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private static final int MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP = 3;
private static final int MSG_RESUME_SUGGESTIONS = 4;
private static final int MSG_REOPEN_DICTIONARIES = 5;
- private static final int MSG_ON_END_BATCH_INPUT = 6;
+ private static final int MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED = 6;
private static final int MSG_RESET_CACHES = 7;
// Update this when adding new messages
private static final int MSG_LAST = MSG_RESET_CACHES;
@@ -220,8 +220,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// get any suggestions. Wait one frame.
postUpdateSuggestionStrip();
break;
- case MSG_ON_END_BATCH_INPUT:
- latinIme.mInputLogic.endBatchInputInternal(latinIme.mSettings.getCurrent(),
+ case MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED:
+ latinIme.mInputLogic.onUpdateTailBatchInputCompleted(
+ latinIme.mSettings.getCurrent(),
(SuggestedWords) msg.obj, latinIme.mKeyboardSwitcher);
break;
case MSG_RESET_CACHES:
@@ -304,8 +305,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
ARG1_NOT_GESTURE_INPUT, ARG2_UNUSED, suggestedWords).sendToTarget();
}
- public void onEndBatchInput(final SuggestedWords suggestedWords) {
- obtainMessage(MSG_ON_END_BATCH_INPUT, suggestedWords).sendToTarget();
+ public void showTailBatchInputResult(final SuggestedWords suggestedWords) {
+ obtainMessage(MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED, suggestedWords).sendToTarget();
}
// Working variables for the following methods.
diff --git a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
index 68505ce38..9f61d6c37 100644
--- a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
@@ -51,20 +51,21 @@ public final class ReadOnlyBinaryDictionary extends Dictionary {
@Override
public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
- final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+ final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+ final float[] inOutLanguageWeight) {
return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords,
- additionalFeaturesOptions, 0 /* sessionId */);
+ additionalFeaturesOptions, 0 /* sessionId */, inOutLanguageWeight);
}
@Override
public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
- final int sessionId) {
+ final int sessionId, final float[] inOutLanguageWeight) {
if (mLock.readLock().tryLock()) {
try {
return mBinaryDictionary.getSuggestions(composer, prevWord, proximityInfo,
- blockOffensiveWords, additionalFeaturesOptions);
+ blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight);
} finally {
mLock.readLock().unlock();
}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index d4301229c..021133945 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -34,7 +34,7 @@ import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.internal.NeedsToDisplayLanguage;
+import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
import com.android.inputmethod.latin.utils.LocaleUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
@@ -54,7 +54,8 @@ public final class SubtypeSwitcher {
private /* final */ Resources mResources;
private /* final */ ConnectivityManager mConnectivityManager;
- private final NeedsToDisplayLanguage mNeedsToDisplayLanguage = new NeedsToDisplayLanguage();
+ private final LanguageOnSpacebarHelper mLanguageOnSpacebarHelper =
+ new LanguageOnSpacebarHelper();
private InputMethodInfo mShortcutInputMethodInfo;
private InputMethodSubtype mShortcutSubtype;
private InputMethodSubtype mNoLanguageSubtype;
@@ -127,7 +128,7 @@ public final class SubtypeSwitcher {
public void updateParametersOnStartInputView() {
final List<InputMethodSubtype> enabledSubtypesOfThisIme =
mRichImm.getMyEnabledInputMethodSubtypeList(true);
- mNeedsToDisplayLanguage.updateEnabledSubtypeCount(enabledSubtypesOfThisIme.size());
+ mLanguageOnSpacebarHelper.updateEnabledSubtypes(enabledSubtypesOfThisIme);
updateShortcutIME();
}
@@ -176,7 +177,7 @@ public final class SubtypeSwitcher {
final boolean sameLanguage = systemLocale.getLanguage().equals(newLocale.getLanguage());
final boolean implicitlyEnabled =
mRichImm.checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(newSubtype);
- mNeedsToDisplayLanguage.updateIsSystemLanguageSameAsInputLanguage(
+ mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(
sameLocale || (sameLanguage && implicitlyEnabled));
updateShortcutIME();
@@ -249,8 +250,8 @@ public final class SubtypeSwitcher {
// Subtype Switching functions //
//////////////////////////////////
- public boolean needsToDisplayLanguage(final InputMethodSubtype subtype) {
- return mNeedsToDisplayLanguage.needsToDisplayLanguage(subtype);
+ public int getLanguageOnSpacebarFormatType(final InputMethodSubtype subtype) {
+ return mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(subtype);
}
public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() {
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
index 9c095e4b1..c24ee4033 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
@@ -34,10 +34,11 @@ public final class SynchronouslyLoadedContactsBinaryDictionary extends ContactsB
@Override
public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer codes,
final String prevWordForBigrams, final ProximityInfo proximityInfo,
- final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+ final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+ final float[] inOutLanguageWeight) {
synchronized (mLock) {
return super.getSuggestions(codes, prevWordForBigrams, proximityInfo,
- blockOffensiveWords, additionalFeaturesOptions);
+ blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight);
}
}
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
index 801fb5b89..1d29d7ad0 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
@@ -39,10 +39,11 @@ public final class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDic
@Override
public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer codes,
final String prevWordForBigrams, final ProximityInfo proximityInfo,
- final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+ final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+ final float[] inOutLanguageWeight) {
synchronized (mLock) {
return super.getSuggestions(codes, prevWordForBigrams, proximityInfo,
- blockOffensiveWords, additionalFeaturesOptions);
+ blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight);
}
}
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index ec6bd289a..ee31c4628 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -210,22 +210,12 @@ public final class InputLogic {
// So, LatinImeLogger logs "" as a user's input.
LatinImeLogger.logOnManualSuggestion("", suggestion, index, suggestedWords);
// Rely on onCodeInput to do the complicated swapping/stripping logic consistently.
- final int primaryCode = suggestion.charAt(0);
- // TODO: we should be using createSuggestionPickedEvent here, but for legacy reasons,
- // onCodeInput is expected a software keypress event for a suggested punctuation
- // because the current code is descended from a time where this information used not
- // to be available. Fix this.
- final Event event = Event.createSoftwareKeypressEvent(primaryCode,
- Event.NOT_A_KEY_CODE /* keyCode*/,
- Constants.SUGGESTION_STRIP_COORDINATE /* x */,
- Constants.SUGGESTION_STRIP_COORDINATE /* y */);
- final InputTransaction completeTransaction = onCodeInput(settingsValues, event,
- keyboardShiftState, handler);
+ final Event event = Event.createPunctuationSuggestionPickedEvent(suggestionInfo);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_punctuationSuggestion(index, suggestion,
false /* isBatchMode */, suggestedWords.mIsPrediction);
}
- return completeTransaction;
+ return onCodeInput(settingsValues, event, keyboardShiftState, handler);
}
final Event event = Event.createSuggestionPickedEvent(suggestionInfo);
@@ -601,7 +591,7 @@ public final class InputLogic {
}
public void onEndBatchInput(final InputPointers batchPointers) {
- mInputLogicHandler.onEndBatchInput(batchPointers, mAutoCommitSequenceNumber);
+ mInputLogicHandler.updateTailBatchInput(batchPointers, mAutoCommitSequenceNumber);
++mAutoCommitSequenceNumber;
}
@@ -833,13 +823,11 @@ public final class InputLogic {
}
if (Constants.CODE_SPACE == codePoint) {
- if (inputTransaction.mSettingsValues.isSuggestionsRequested()) {
- if (maybeDoubleSpacePeriod(inputTransaction)) {
- inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
- mSpaceState = SpaceState.DOUBLE;
- } else if (!mSuggestedWords.isPunctuationSuggestions()) {
- mSpaceState = SpaceState.WEAK;
- }
+ if (maybeDoubleSpacePeriod(inputTransaction)) {
+ inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+ mSpaceState = SpaceState.DOUBLE;
+ } else if (!mSuggestedWords.isPunctuationSuggestions()) {
+ mSpaceState = SpaceState.WEAK;
}
startDoubleSpacePeriodCountdown(inputTransaction);
@@ -1794,7 +1782,7 @@ public final class InputLogic {
* @param settingsValues the current values of the settings.
* @param suggestedWords suggestedWords to use.
*/
- public void endBatchInputInternal(final SettingsValues settingsValues,
+ public void onUpdateTailBatchInputCompleted(final SettingsValues settingsValues,
final SuggestedWords suggestedWords,
// TODO: remove this argument
final KeyboardSwitcher keyboardSwitcher) {
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
index 42f0d7c00..e3b8ab465 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
@@ -54,7 +54,8 @@ class InputLogicHandler implements Handler.Callback {
@Override
public void onCancelBatchInput() {}
@Override
- public void onEndBatchInput(final InputPointers batchPointers, final int sequenceNumber) {}
+ public void updateTailBatchInput(final InputPointers batchPointers,
+ final int sequenceNumber) {}
@Override
public void getSuggestedWords(final int sessionId, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {}
@@ -106,7 +107,7 @@ class InputLogicHandler implements Handler.Callback {
* Fetch suggestions corresponding to an update of a batch input.
* @param batchPointers the updated pointers, including the part that was passed last time.
* @param sequenceNumber the sequence number associated with this batch input.
- * @param forEnd true if this is the end of a batch input, false if it's an update.
+ * @param isTailBatchInput true if this is the end of a batch input, false if it's an update.
*/
// This method can be called from any thread and will see to it that the correct threads
// are used for parts that require it. This method will send a message to the Non-UI handler
@@ -115,7 +116,7 @@ class InputLogicHandler implements Handler.Callback {
// send a message to the UI handler in LatinIME so that showing suggestions can be done on
// the UI thread.
private void updateBatchInput(final InputPointers batchPointers,
- final int sequenceNumber, final boolean forEnd) {
+ final int sequenceNumber, final boolean isTailBatchInput) {
synchronized (mLock) {
if (!mInBatchInput) {
// Batch input has ended or canceled while the message was being delivered.
@@ -136,12 +137,12 @@ class InputLogicHandler implements Handler.Callback {
suggestedWords = mInputLogic.mSuggestedWords;
}
mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWords,
- forEnd /* dismissGestureFloatingPreviewText */);
- if (forEnd) {
+ isTailBatchInput /* dismissGestureFloatingPreviewText */);
+ if (isTailBatchInput) {
mInBatchInput = false;
// The following call schedules onEndBatchInputInternal
// to be called on the UI thread.
- mLatinIME.mHandler.onEndBatchInput(suggestedWords);
+ mLatinIME.mHandler.showTailBatchInputResult(suggestedWords);
}
}
});
@@ -159,13 +160,13 @@ class InputLogicHandler implements Handler.Callback {
// Called on the UI thread by InputLogic.
public void onUpdateBatchInput(final InputPointers batchPointers,
final int sequenceNumber) {
- updateBatchInput(batchPointers, sequenceNumber, false /* forEnd */);
+ updateBatchInput(batchPointers, sequenceNumber, false /* isTailBatchInput */);
}
/**
* Cancel a batch input.
*
- * Note that as opposed to onEndBatchInput, we do the UI side of this immediately on the
+ * Note that as opposed to updateTailBatchInput, we do the UI side of this immediately on the
* same thread, rather than get this to call a method in LatinIME. This is because
* canceling a batch input does not necessitate the long operation of pulling suggestions.
*/
@@ -177,17 +178,20 @@ class InputLogicHandler implements Handler.Callback {
}
/**
- * Finish a batch input.
+ * Trigger an update for a tail batch input.
*
- * This fetches suggestions, updates the suggestion strip and commits the first suggestion.
- * It also dismisses the floating text preview.
+ * A tail batch input is the last update for a gesture, the one that is triggered after the
+ * user lifts their finger. This method schedules fetching suggestions on the non-UI thread,
+ * then when the suggestions are computed it comes back on the UI thread to update the
+ * suggestion strip, commit the first suggestion, and dismiss the floating text preview.
*
* @param batchPointers the updated batch pointers.
* @param sequenceNumber the sequence number associated with this batch input.
*/
// Called on the UI thread by InputLogic.
- public void onEndBatchInput(final InputPointers batchPointers, final int sequenceNumber) {
- updateBatchInput(batchPointers, sequenceNumber, true /* forEnd */);
+ public void updateTailBatchInput(final InputPointers batchPointers,
+ final int sequenceNumber) {
+ updateBatchInput(batchPointers, sequenceNumber, true /* isTailBatchInput */);
}
public void getSuggestedWords(final int sessionId, final int sequenceNumber,
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 6f84e1f10..712e314a8 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -66,7 +66,7 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
}
// Flush pending writes.
flush();
- // TODO: Quit depending on finalize() and really close the dictionary file.
+ super.close();
}
public void flush() {
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index 3947019ca..69d092751 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -327,7 +327,8 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
final ArrayList<SuggestedWordInfo> suggestions =
dictInfo.mDictionary.getSuggestions(composer, prevWord,
dictInfo.getProximityInfo(), true /* blockOffensiveWords */,
- null /* additionalFeaturesOptions */);
+ null /* additionalFeaturesOptions */,
+ null /* inOutLanguageWeight */);
if (suggestions != null) {
for (final SuggestedWordInfo suggestion : suggestions) {
final String suggestionStr = suggestion.mWord;
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
index b7a5a4026..c99264347 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
@@ -53,7 +53,8 @@ public final class DictionaryPool extends LinkedBlockingQueue<DictAndKeyboard> {
@Override
public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
final String prevWord, final ProximityInfo proximityInfo,
- final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+ final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+ final float[] inOutLanguageWeight) {
return noSuggestions;
}
@Override