diff options
Diffstat (limited to 'java/src')
6 files changed, 79 insertions, 54 deletions
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/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 43a44221d..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]; @@ -138,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); } @@ -185,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); } @@ -401,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. @@ -412,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. @@ -422,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) { @@ -433,6 +440,7 @@ public final class BinaryDictionary extends Dictionary { } processedParamCount = addMultipleDictionaryEntriesNative(mNativeDict, languageModelParams, processedParamCount); + mHasUpdated = true; if (processedParamCount <= 0) { return; } @@ -451,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/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index aea4811a9..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()])); diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 2fd8ace93..c89be35ad 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -210,15 +210,7 @@ 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 Event event = Event.createPunctuationSuggestionPickedEvent(suggestionInfo); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_punctuationSuggestion(index, suggestion, false /* isBatchMode */, suggestedWords.mIsPrediction); 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() { |