aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/RichInputConnection.java
diff options
context:
space:
mode:
authorTom Ouyang <ouyang@google.com>2015-06-22 13:43:32 -0700
committerTom Ouyang <ouyang@google.com>2015-06-23 10:34:44 -0700
commit912016b69f1c0e26ec58ee9d17c8ac7e5711d70d (patch)
tree08ea2fedab96e7958edef6115c5d5d266f716779 /java/src/com/android/inputmethod/latin/RichInputConnection.java
parent73aaf6833780c1915dd4ab7d3f0f55e3af130f99 (diff)
downloadlatinime-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.java44
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;
}