diff options
author | 2015-06-22 13:43:32 -0700 | |
---|---|---|
committer | 2015-06-23 10:34:44 -0700 | |
commit | 912016b69f1c0e26ec58ee9d17c8ac7e5711d70d (patch) | |
tree | 08ea2fedab96e7958edef6115c5d5d266f716779 /java/src/com/android/inputmethod/latin/RichInputConnection.java | |
parent | 73aaf6833780c1915dd4ab7d3f0f55e3af130f99 (diff) | |
download | latinime-912016b69f1c0e26ec58ee9d17c8ac7e5711d70d.tar.gz latinime-912016b69f1c0e26ec58ee9d17c8ac7e5711d70d.tar.xz latinime-912016b69f1c0e26ec58ee9d17c8ac7e5711d70d.zip |
Workaround for preserving responsiveness on a slow InputConnection.
1. Add mechanism to detect a slow or non-resonsive InputConnection (IC)
2. When IC slowness is detected, skip certain IC calls that are known
to be expensive (e.g., getTextAfterCursor).
3. Similarly, disables learning / unlearning on a slow IC.
4. IC slowness flag is reset when starting input on a new TextView or
when a fixed amount of time has passed.
Note: These are mostly temporary workarounds. The permanent solution is
to refactor RichInputConnection so that it is less sensitive to IC
slowness in general.
Bug: 21926256
Change-Id: I383fab0516d3f3a8e0f71e5d760a8336a7730f7c
Diffstat (limited to 'java/src/com/android/inputmethod/latin/RichInputConnection.java')
-rw-r--r-- | java/src/com/android/inputmethod/latin/RichInputConnection.java | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index 9f5a7223c..064db6a25 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -46,6 +46,8 @@ import com.android.inputmethod.latin.utils.SpannableStringUtils; import com.android.inputmethod.latin.utils.StatsUtils; import com.android.inputmethod.latin.utils.TextRange; +import java.util.concurrent.TimeUnit; + import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -65,7 +67,12 @@ public final class RichInputConnection implements PrivateCommandPerformer { private static final int NUM_CHARS_TO_GET_BEFORE_CURSOR = 40; private static final int NUM_CHARS_TO_GET_AFTER_CURSOR = 40; private static final int INVALID_CURSOR_POSITION = -1; - private static final long SLOW_INPUTCONNECTION_MS = 100; + + /** + * The amount of time an InputConnection call needs to take for the keyboard to enter + * the SlowInputConnection state. + */ + private static final long SLOW_INPUTCONNECTION_MS = 200; private static final int OPERATION_GET_TEXT_BEFORE_CURSOR = 0; private static final int OPERATION_GET_TEXT_AFTER_CURSOR = 1; private static final int OPERATION_GET_WORD_RANGE_AT_CURSOR = 2; @@ -77,6 +84,12 @@ public final class RichInputConnection implements PrivateCommandPerformer { "RELOAD_TEXT_CACHE"}; /** + * The amount of time the keyboard will persist in the 'hasSlowInputConnection' state + * after observing a slow InputConnection event. + */ + private static final long SLOW_INPUTCONNECTION_PERSIST_MS = TimeUnit.MINUTES.toMillis(10); + + /** * This variable contains an expected value for the selection start position. This is where the * cursor or selection start may end up after all the keyboard-triggered updates have passed. We * keep this to compare it to the actual selection start to guess whether the move was caused by @@ -110,6 +123,11 @@ public final class RichInputConnection implements PrivateCommandPerformer { InputConnection mIC; int mNestLevel; + /** + * The timestamp of the last slow InputConnection operation + */ + private long mLastSlowInputConnectionTime = 0; + public RichInputConnection(final InputMethodService parent) { mParent = parent; mIC = null; @@ -120,6 +138,20 @@ public final class RichInputConnection implements PrivateCommandPerformer { return mIC != null; } + /** + * Returns whether or not the underlying InputConnection is slow. When true, we want to avoid + * calling InputConnection methods that trigger an IPC round-trip (e.g., getTextAfterCursor). + */ + public boolean hasSlowInputConnection() { + return mLastSlowInputConnectionTime > 0 && + (SystemClock.uptimeMillis() - mLastSlowInputConnectionTime) + <= SLOW_INPUTCONNECTION_PERSIST_MS; + } + + public void onStartInput() { + mLastSlowInputConnectionTime = 0; + } + private void checkConsistencyForDebug() { final ExtractedTextRequest r = new ExtractedTextRequest(); r.hintMaxChars = 0; @@ -395,7 +427,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { if (!isConnected()) { return null; } - long startTime = SystemClock.uptimeMillis(); + final long startTime = SystemClock.uptimeMillis(); final CharSequence result = mIC.getTextBeforeCursor(n, flags); detectLaggyConnection(operation, startTime); return result; @@ -424,6 +456,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { final String operationName = OPERATION_NAMES[operation]; Log.w(TAG, "Slow InputConnection: " + operationName + " took " + duration + " ms."); StatsUtils.onInputConnectionLaggy(operation, duration); + mLastSlowInputConnectionTime = SystemClock.uptimeMillis(); } } @@ -666,7 +699,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { OPERATION_GET_WORD_RANGE_AT_CURSOR, NUM_CHARS_TO_GET_BEFORE_CURSOR, InputConnection.GET_TEXT_WITH_STYLES); - final CharSequence after = getTextBeforeCursorAndDetectLaggyConnection( + final CharSequence after = getTextAfterCursorAndDetectLaggyConnection( OPERATION_GET_WORD_RANGE_AT_CURSOR, NUM_CHARS_TO_GET_AFTER_CURSOR, InputConnection.GET_TEXT_WITH_STYLES); @@ -711,8 +744,9 @@ public final class RichInputConnection implements PrivateCommandPerformer { hasUrlSpans); } - public boolean isCursorTouchingWord(final SpacingAndPunctuations spacingAndPunctuations) { - if (isCursorFollowedByWordCharacter(spacingAndPunctuations)) { + public boolean isCursorTouchingWord(final SpacingAndPunctuations spacingAndPunctuations, + boolean checkTextAfter) { + if (checkTextAfter && isCursorFollowedByWordCharacter(spacingAndPunctuations)) { // If what's after the cursor is a word character, then we're touching a word. return true; } |