Extend laggy connection timeout for initial load.

The initial reloadTextCache() operation needs to read 1k characters, and it
could be slow on low-end devices. Also, the initial load is not blocking key
strokes, so it can take a little longer.

Bug 22062102.

Change-Id: I134424e8910c0d6131c311a862bdc87eccd3af44
main
Dan Zivkovic 2015-06-24 11:36:04 -07:00
parent ecea6a6113
commit 563d7935a9
1 changed files with 27 additions and 14 deletions

View File

@ -69,10 +69,16 @@ public final class RichInputConnection implements PrivateCommandPerformer {
private static final int INVALID_CURSOR_POSITION = -1; private static final int INVALID_CURSOR_POSITION = -1;
/** /**
* The amount of time an InputConnection call needs to take for the keyboard to enter * The amount of time a {@link #reloadTextCache} call needs to take for the keyboard to enter
* the SlowInputConnection state. * the {@link #hasSlowInputConnection} state.
*/ */
private static final long SLOW_INPUTCONNECTION_MS = 200; private static final long SLOW_INPUT_CONNECTION_ON_FULL_RELOAD_MS = 1000;
/**
* The amount of time a {@link #getTextBeforeCursor} or {@link #getTextAfterCursor} call needs
* to take for the keyboard to enter the {@link #hasSlowInputConnection} state.
*/
private static final long SLOW_INPUT_CONNECTION_ON_PARTIAL_RELOAD_MS = 200;
private static final int OPERATION_GET_TEXT_BEFORE_CURSOR = 0; 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_TEXT_AFTER_CURSOR = 1;
private static final int OPERATION_GET_WORD_RANGE_AT_CURSOR = 2; private static final int OPERATION_GET_WORD_RANGE_AT_CURSOR = 2;
@ -84,7 +90,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
"RELOAD_TEXT_CACHE"}; "RELOAD_TEXT_CACHE"};
/** /**
* The amount of time the keyboard will persist in the 'hasSlowInputConnection' state * The amount of time the keyboard will persist in the {@link #hasSlowInputConnection} state
* after observing a slow InputConnection event. * after observing a slow InputConnection event.
*/ */
private static final long SLOW_INPUTCONNECTION_PERSIST_MS = TimeUnit.MINUTES.toMillis(10); private static final long SLOW_INPUTCONNECTION_PERSIST_MS = TimeUnit.MINUTES.toMillis(10);
@ -120,8 +126,8 @@ public final class RichInputConnection implements PrivateCommandPerformer {
private SpannableStringBuilder mTempObjectForCommitText = new SpannableStringBuilder(); private SpannableStringBuilder mTempObjectForCommitText = new SpannableStringBuilder();
private final InputMethodService mParent; private final InputMethodService mParent;
InputConnection mIC; private InputConnection mIC;
int mNestLevel; private int mNestLevel;
/** /**
* The timestamp of the last slow InputConnection operation * The timestamp of the last slow InputConnection operation
@ -252,6 +258,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
// we want to refresh it. // we want to refresh it.
final CharSequence textBeforeCursor = getTextBeforeCursorAndDetectLaggyConnection( final CharSequence textBeforeCursor = getTextBeforeCursorAndDetectLaggyConnection(
OPERATION_RELOAD_TEXT_CACHE, OPERATION_RELOAD_TEXT_CACHE,
SLOW_INPUT_CONNECTION_ON_FULL_RELOAD_MS,
Constants.EDITOR_CONTENTS_CACHE_SIZE, Constants.EDITOR_CONTENTS_CACHE_SIZE,
0 /* flags */); 0 /* flags */);
if (null == textBeforeCursor) { if (null == textBeforeCursor) {
@ -418,41 +425,45 @@ public final class RichInputConnection implements PrivateCommandPerformer {
return s; return s;
} }
return getTextBeforeCursorAndDetectLaggyConnection( return getTextBeforeCursorAndDetectLaggyConnection(
OPERATION_GET_TEXT_BEFORE_CURSOR, n, flags); OPERATION_GET_TEXT_BEFORE_CURSOR,
SLOW_INPUT_CONNECTION_ON_PARTIAL_RELOAD_MS,
n, flags);
} }
private CharSequence getTextBeforeCursorAndDetectLaggyConnection( private CharSequence getTextBeforeCursorAndDetectLaggyConnection(
final int operation, final int n, final int flags) { final int operation, final long timeout, final int n, final int flags) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
if (!isConnected()) { if (!isConnected()) {
return null; return null;
} }
final long startTime = SystemClock.uptimeMillis(); final long startTime = SystemClock.uptimeMillis();
final CharSequence result = mIC.getTextBeforeCursor(n, flags); final CharSequence result = mIC.getTextBeforeCursor(n, flags);
detectLaggyConnection(operation, startTime); detectLaggyConnection(operation, timeout, startTime);
return result; return result;
} }
public CharSequence getTextAfterCursor(final int n, final int flags) { public CharSequence getTextAfterCursor(final int n, final int flags) {
return getTextAfterCursorAndDetectLaggyConnection( return getTextAfterCursorAndDetectLaggyConnection(
OPERATION_GET_TEXT_AFTER_CURSOR, n, flags); OPERATION_GET_TEXT_AFTER_CURSOR,
SLOW_INPUT_CONNECTION_ON_PARTIAL_RELOAD_MS,
n, flags);
} }
private CharSequence getTextAfterCursorAndDetectLaggyConnection( private CharSequence getTextAfterCursorAndDetectLaggyConnection(
final int operation, final int n, final int flags) { final int operation, final long timeout, final int n, final int flags) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
if (!isConnected()) { if (!isConnected()) {
return null; return null;
} }
final long startTime = SystemClock.uptimeMillis(); final long startTime = SystemClock.uptimeMillis();
final CharSequence result = mIC.getTextAfterCursor(n, flags); final CharSequence result = mIC.getTextAfterCursor(n, flags);
detectLaggyConnection(operation, startTime); detectLaggyConnection(operation, timeout, startTime);
return result; return result;
} }
private void detectLaggyConnection(final int operation, final long startTime) { private void detectLaggyConnection(final int operation, final long timeout, final long startTime) {
final long duration = SystemClock.uptimeMillis() - startTime; final long duration = SystemClock.uptimeMillis() - startTime;
if (duration >= SLOW_INPUTCONNECTION_MS) { if (duration >= timeout) {
final String operationName = OPERATION_NAMES[operation]; final String operationName = OPERATION_NAMES[operation];
Log.w(TAG, "Slow InputConnection: " + operationName + " took " + duration + " ms."); Log.w(TAG, "Slow InputConnection: " + operationName + " took " + duration + " ms.");
StatsUtils.onInputConnectionLaggy(operation, duration); StatsUtils.onInputConnectionLaggy(operation, duration);
@ -697,10 +708,12 @@ public final class RichInputConnection implements PrivateCommandPerformer {
} }
final CharSequence before = getTextBeforeCursorAndDetectLaggyConnection( final CharSequence before = getTextBeforeCursorAndDetectLaggyConnection(
OPERATION_GET_WORD_RANGE_AT_CURSOR, OPERATION_GET_WORD_RANGE_AT_CURSOR,
SLOW_INPUT_CONNECTION_ON_PARTIAL_RELOAD_MS,
NUM_CHARS_TO_GET_BEFORE_CURSOR, NUM_CHARS_TO_GET_BEFORE_CURSOR,
InputConnection.GET_TEXT_WITH_STYLES); InputConnection.GET_TEXT_WITH_STYLES);
final CharSequence after = getTextAfterCursorAndDetectLaggyConnection( final CharSequence after = getTextAfterCursorAndDetectLaggyConnection(
OPERATION_GET_WORD_RANGE_AT_CURSOR, OPERATION_GET_WORD_RANGE_AT_CURSOR,
SLOW_INPUT_CONNECTION_ON_PARTIAL_RELOAD_MS,
NUM_CHARS_TO_GET_AFTER_CURSOR, NUM_CHARS_TO_GET_AFTER_CURSOR,
InputConnection.GET_TEXT_WITH_STYLES); InputConnection.GET_TEXT_WITH_STYLES);
if (before == null || after == null) { if (before == null || after == null) {