Call getSuggestedWords asynchronously.

Change-Id: Ia8a21b53f4d12b759d9ef5a5181ed04875e4d198
main
Yuichiro Hanada 2013-09-02 16:49:32 +09:00
parent 8616e4c03d
commit 908fc4f1c3
1 changed files with 100 additions and 39 deletions

View File

@ -107,6 +107,8 @@ import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Locale; import java.util.Locale;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/** /**
* Input method implementation for Qwerty'ish keyboard. * Input method implementation for Qwerty'ish keyboard.
@ -129,6 +131,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2; private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2;
private static final int GET_SUGGESTED_WORDS_TIMEOUT = 500;
/** /**
* The name of the scheme used by the Package Manager to warn of a new package installation, * The name of the scheme used by the Package Manager to warn of a new package installation,
* replacement or removal. * replacement or removal.
@ -221,6 +225,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private final boolean mIsHardwareAcceleratedDrawingEnabled; private final boolean mIsHardwareAcceleratedDrawingEnabled;
public final UIHandler mHandler = new UIHandler(this); public final UIHandler mHandler = new UIHandler(this);
private InputUpdater mInputUpdater;
public static final class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { public static final class UIHandler extends StaticInnerHandlerWrapper<LatinIME> {
private static final int MSG_UPDATE_SHIFT_STATE = 0; private static final int MSG_UPDATE_SHIFT_STATE = 0;
@ -229,8 +234,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private static final int MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP = 3; 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_RESUME_SUGGESTIONS = 4;
private static final int MSG_REOPEN_DICTIONARIES = 5; private static final int MSG_REOPEN_DICTIONARIES = 5;
private static final int MSG_ON_END_BATCH_INPUT = 6;
private static final int ARG1_NOT_GESTURE_INPUT = 0;
private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1; private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
private static final int ARG1_SHOW_GESTURE_FLOATING_PREVIEW_TEXT = 2;
private int mDelayUpdateSuggestions; private int mDelayUpdateSuggestions;
private int mDelayUpdateShiftState; private int mDelayUpdateShiftState;
@ -263,8 +271,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
switcher.updateShiftState(); switcher.updateShiftState();
break; break;
case MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP: case MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP:
latinIme.showGesturePreviewAndSuggestionStrip((SuggestedWords)msg.obj, if (msg.arg1 == ARG1_NOT_GESTURE_INPUT) {
msg.arg1 == ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT); latinIme.showSuggestionStrip((SuggestedWords) msg.obj);
} else {
latinIme.showGesturePreviewAndSuggestionStrip((SuggestedWords) msg.obj,
msg.arg1 == ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT);
}
break; break;
case MSG_RESUME_SUGGESTIONS: case MSG_RESUME_SUGGESTIONS:
latinIme.restartSuggestionsOnWordTouchedByCursor(); latinIme.restartSuggestionsOnWordTouchedByCursor();
@ -276,6 +288,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// get any suggestions. Wait one frame. // get any suggestions. Wait one frame.
postUpdateSuggestionStrip(); postUpdateSuggestionStrip();
break; break;
case MSG_ON_END_BATCH_INPUT:
latinIme.onEndBatchInputAsyncInternal((SuggestedWords) msg.obj);
break;
} }
} }
@ -317,11 +332,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final boolean dismissGestureFloatingPreviewText) { final boolean dismissGestureFloatingPreviewText) {
removeMessages(MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP); removeMessages(MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP);
final int arg1 = dismissGestureFloatingPreviewText final int arg1 = dismissGestureFloatingPreviewText
? ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT : 0; ? ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT
: ARG1_SHOW_GESTURE_FLOATING_PREVIEW_TEXT;
obtainMessage(MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP, arg1, 0, suggestedWords) obtainMessage(MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP, arg1, 0, suggestedWords)
.sendToTarget(); .sendToTarget();
} }
public void showSuggestionStrip(final SuggestedWords suggestedWords) {
removeMessages(MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP);
obtainMessage(MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP,
ARG1_NOT_GESTURE_INPUT, 0, suggestedWords).sendToTarget();
}
public void onEndBatchInput(final SuggestedWords suggestedWords) {
obtainMessage(MSG_ON_END_BATCH_INPUT, suggestedWords).sendToTarget();
}
public void startDoubleSpacePeriodTimer() { public void startDoubleSpacePeriodTimer() {
mDoubleSpacePeriodTimerStart = SystemClock.uptimeMillis(); mDoubleSpacePeriodTimerStart = SystemClock.uptimeMillis();
} }
@ -514,6 +540,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final IntentFilter newDictFilter = new IntentFilter(); final IntentFilter newDictFilter = new IntentFilter();
newDictFilter.addAction(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION); newDictFilter.addAction(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION);
registerReceiver(mDictionaryPackInstallReceiver, newDictFilter); registerReceiver(mDictionaryPackInstallReceiver, newDictFilter);
mInputUpdater = new InputUpdater(this);
} }
// Has to be package-visible for unit tests // Has to be package-visible for unit tests
@ -650,6 +678,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
PersonalizationDictionarySessionRegister.onDestroy(this); PersonalizationDictionarySessionRegister.onDestroy(this);
LatinImeLogger.commit(); LatinImeLogger.commit();
LatinImeLogger.onDestroy(); LatinImeLogger.onDestroy();
if (mInputUpdater != null) {
mInputUpdater.onDestroy();
mInputUpdater = null;
}
super.onDestroy(); super.onDestroy();
} }
@ -1668,7 +1700,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override @Override
public void onStartBatchInput() { public void onStartBatchInput() {
BatchInputUpdater.getInstance().onStartBatchInput(this); mInputUpdater.onStartBatchInput();
mHandler.cancelUpdateSuggestionStrip(); mHandler.cancelUpdateSuggestionStrip();
mConnection.beginBatchEdit(); mConnection.beginBatchEdit();
final SettingsValues settingsValues = mSettings.getCurrent(); final SettingsValues settingsValues = mSettings.getCurrent();
@ -1708,46 +1740,41 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode()); mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode());
} }
private static final class BatchInputUpdater implements Handler.Callback { private static final class InputUpdater implements Handler.Callback {
private final Handler mHandler; private final Handler mHandler;
private LatinIME mLatinIme; private final LatinIME mLatinIme;
private final Object mLock = new Object(); private final Object mLock = new Object();
private boolean mInBatchInput; // synchronized using {@link #mLock}. private boolean mInBatchInput; // synchronized using {@link #mLock}.
private BatchInputUpdater() { private InputUpdater(final LatinIME latinIme) {
final HandlerThread handlerThread = new HandlerThread( final HandlerThread handlerThread = new HandlerThread(
BatchInputUpdater.class.getSimpleName()); InputUpdater.class.getSimpleName());
handlerThread.start(); handlerThread.start();
mHandler = new Handler(handlerThread.getLooper(), this); mHandler = new Handler(handlerThread.getLooper(), this);
} mLatinIme = latinIme;
// Initialization-on-demand holder
private static final class OnDemandInitializationHolder {
public static final BatchInputUpdater sInstance = new BatchInputUpdater();
}
public static BatchInputUpdater getInstance() {
return OnDemandInitializationHolder.sInstance;
} }
private static final int MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP = 1; private static final int MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP = 1;
private static final int MSG_GET_SUGGESTED_WORDS = 2;
@Override @Override
public boolean handleMessage(final Message msg) { public boolean handleMessage(final Message msg) {
switch (msg.what) { switch (msg.what) {
case MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP: case MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP:
updateBatchInput((InputPointers)msg.obj); updateBatchInput((InputPointers)msg.obj);
break; break;
case MSG_GET_SUGGESTED_WORDS:
mLatinIme.getSuggestedWords(msg.arg1, (OnGetSuggestedWordsCallback) msg.obj);
break;
} }
return true; return true;
} }
// Run in the UI thread. // Run in the UI thread.
public void onStartBatchInput(final LatinIME latinIme) { public void onStartBatchInput() {
synchronized (mLock) { synchronized (mLock) {
mHandler.removeMessages(MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP); mHandler.removeMessages(MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP);
mInBatchInput = true; mInBatchInput = true;
mLatinIme = latinIme;
mLatinIme.mHandler.showGesturePreviewAndSuggestionStrip( mLatinIme.mHandler.showGesturePreviewAndSuggestionStrip(
SuggestedWords.EMPTY, false /* dismissGestureFloatingPreviewText */); SuggestedWords.EMPTY, false /* dismissGestureFloatingPreviewText */);
} }
@ -1766,7 +1793,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void onGetSuggestedWords(final SuggestedWords suggestedWords) { public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
mLatinIme.mHandler.showGesturePreviewAndSuggestionStrip( mLatinIme.mHandler.showGesturePreviewAndSuggestionStrip(
suggestedWords, false /* dismissGestureFloatingPreviewText */); suggestedWords, false /* dismissGestureFloatingPreviewText */);
}}); }
});
} }
} }
@ -1797,7 +1825,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mInBatchInput = false; mInBatchInput = false;
mLatinIme.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWords, mLatinIme.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWords,
true /* dismissGestureFloatingPreviewText */); true /* dismissGestureFloatingPreviewText */);
mLatinIme.onEndBatchInputAsyncInternal(suggestedWords); mLatinIme.mHandler.onEndBatchInput(suggestedWords);
} }
}); });
} }
@ -1808,7 +1836,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void getSuggestedWordsGestureLocked(final InputPointers batchPointers, private void getSuggestedWordsGestureLocked(final InputPointers batchPointers,
final OnGetSuggestedWordsCallback callback) { final OnGetSuggestedWordsCallback callback) {
mLatinIme.mWordComposer.setBatchInputPointers(batchPointers); mLatinIme.mWordComposer.setBatchInputPointers(batchPointers);
mLatinIme.getSuggestedWordsOrOlderSuggestions(Suggest.SESSION_GESTURE, mLatinIme.getSuggestedWordsOrOlderSuggestionsAsync(Suggest.SESSION_GESTURE,
new OnGetSuggestedWordsCallback() { new OnGetSuggestedWordsCallback() {
@Override @Override
public void onGetSuggestedWords(SuggestedWords suggestedWords) { public void onGetSuggestedWords(SuggestedWords suggestedWords) {
@ -1823,8 +1851,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
}); });
} }
public void getSuggestedWords(final int sessionId,
final OnGetSuggestedWordsCallback callback) {
mHandler.obtainMessage(MSG_GET_SUGGESTED_WORDS, sessionId, 0, callback).sendToTarget();
}
private void onDestroy() {
mHandler.removeMessages(MSG_GET_SUGGESTED_WORDS);
mHandler.removeMessages(MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP);
mHandler.getLooper().quit();
}
} }
// This method must run in UI Thread.
private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords, private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
final boolean dismissGestureFloatingPreviewText) { final boolean dismissGestureFloatingPreviewText) {
showSuggestionStrip(suggestedWords); showSuggestionStrip(suggestedWords);
@ -1843,9 +1883,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO: implement auto-commit // TODO: implement auto-commit
} }
} }
BatchInputUpdater.getInstance().onUpdateBatchInput(batchPointers); mInputUpdater.onUpdateBatchInput(batchPointers);
} }
// This method must run in UI Thread.
public void onEndBatchInputAsyncInternal(final SuggestedWords suggestedWords) { public void onEndBatchInputAsyncInternal(final SuggestedWords suggestedWords) {
final String batchInputText = suggestedWords.isEmpty() final String batchInputText = suggestedWords.isEmpty()
? null : suggestedWords.getWord(0); ? null : suggestedWords.getWord(0);
@ -1870,7 +1911,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override @Override
public void onEndBatchInput(final InputPointers batchPointers) { public void onEndBatchInput(final InputPointers batchPointers) {
BatchInputUpdater.getInstance().onEndBatchInput(batchPointers); mInputUpdater.onEndBatchInput(batchPointers);
} }
private String specificTldProcessingOnTextInput(final String text) { private String specificTldProcessingOnTextInput(final String text) {
@ -1908,7 +1949,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override @Override
public void onCancelBatchInput() { public void onCancelBatchInput() {
BatchInputUpdater.getInstance().onCancelBatchInput(); mInputUpdater.onCancelBatchInput();
} }
private void handleBackspace(final int spaceState) { private void handleBackspace(final int spaceState) {
@ -2343,13 +2384,31 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return; return;
} }
getSuggestedWordsOrOlderSuggestions(Suggest.SESSION_TYPING, final CountDownLatch latch = new CountDownLatch(1);
final SuggestedWords[] suggestedWordsArray = new SuggestedWords[1];
getSuggestedWordsOrOlderSuggestionsAsync(Suggest.SESSION_TYPING,
new OnGetSuggestedWordsCallback() { new OnGetSuggestedWordsCallback() {
@Override @Override
public void onGetSuggestedWords(SuggestedWords suggestedWords) { public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
showSuggestionStrip(suggestedWords); suggestedWordsArray[0] = suggestedWords;
} latch.countDown();
}); }
}
);
try {
// Wait for the result of getSuggestedWords
// We set the time out to avoid ANR.
latch.await(GET_SUGGESTED_WORDS_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// TODO: Cancel all pending "getSuggestedWords" tasks when it failed. We may want to add
// "onGetSuggestionFailed" to "OnGetSuggestedWordsCallback".
Log.e(TAG, "InterruptedException while waiting for getSuggestedWords.", e);
return;
}
if (suggestedWordsArray[0] != null) {
showSuggestionStrip(suggestedWordsArray[0]);
}
} }
private void getSuggestedWords(final int sessionId, private void getSuggestedWords(final int sessionId,
@ -2380,9 +2439,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
additionalFeaturesOptions, sessionId, callback); additionalFeaturesOptions, sessionId, callback);
} }
private void getSuggestedWordsOrOlderSuggestions(final int sessionId, private void getSuggestedWordsOrOlderSuggestionsAsync(final int sessionId,
final OnGetSuggestedWordsCallback callback) { final OnGetSuggestedWordsCallback callback) {
getSuggestedWords(sessionId, new OnGetSuggestedWordsCallback() { mInputUpdater.getSuggestedWords(sessionId, new OnGetSuggestedWordsCallback() {
@Override @Override
public void onGetSuggestedWords(SuggestedWords suggestedWords) { public void onGetSuggestedWords(SuggestedWords suggestedWords) {
callback.onGetSuggestedWords(maybeRetrieveOlderSuggestions( callback.onGetSuggestedWords(maybeRetrieveOlderSuggestions(
@ -2689,9 +2748,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (suggestions.isEmpty()) { if (suggestions.isEmpty()) {
// We come here if there weren't any suggestion spans on this word. We will try to // We come here if there weren't any suggestion spans on this word. We will try to
// compute suggestions for it instead. // compute suggestions for it instead.
getSuggestedWords(Suggest.SESSION_TYPING, new OnGetSuggestedWordsCallback() { mInputUpdater.getSuggestedWords(Suggest.SESSION_TYPING,
new OnGetSuggestedWordsCallback() {
@Override @Override
public void onGetSuggestedWords(SuggestedWords suggestedWordsIncludingTypedWord) { public void onGetSuggestedWords(
final SuggestedWords suggestedWordsIncludingTypedWord) {
final SuggestedWords suggestedWords; final SuggestedWords suggestedWords;
if (suggestedWordsIncludingTypedWord.size() > 1) { if (suggestedWordsIncludingTypedWord.size() > 1) {
// We were able to compute new suggestions for this word. // We were able to compute new suggestions for this word.
@ -2729,7 +2790,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// the text to adapt it. // the text to adapt it.
// TODO: remove mIsAutoCorrectionIndicatorOn (see comment on definition) // TODO: remove mIsAutoCorrectionIndicatorOn (see comment on definition)
mIsAutoCorrectionIndicatorOn = false; mIsAutoCorrectionIndicatorOn = false;
showSuggestionStrip(suggestedWords); mHandler.showSuggestionStrip(suggestedWords);
} }
/** /**