Merge "Add EditorInfo#getInitialSurroundingText API"
This commit is contained in:
committed by
Android (Google) Code Review
commit
11615dea52
@@ -50464,6 +50464,7 @@ package android.view.inputmethod {
|
||||
method public int describeContents();
|
||||
method public void dump(android.util.Printer, String);
|
||||
method @Nullable public CharSequence getInitialSelectedText(int);
|
||||
method @Nullable public android.view.inputmethod.SurroundingText getInitialSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int);
|
||||
method @Nullable public CharSequence getInitialTextAfterCursor(int, int);
|
||||
method @Nullable public CharSequence getInitialTextBeforeCursor(int, int);
|
||||
method public final void makeCompatible(int);
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.view.inputmethod.EditorInfoProto.PRIVATE_IME_OPTIONS;
|
||||
import static android.view.inputmethod.EditorInfoProto.TARGET_INPUT_METHOD_USER_ID;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
@@ -36,7 +37,6 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.UserHandle;
|
||||
import android.text.InputType;
|
||||
import android.text.ParcelableSpan;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Printer;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
@@ -44,6 +44,7 @@ import android.view.View;
|
||||
import android.view.autofill.AutofillId;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -563,8 +564,9 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
@VisibleForTesting
|
||||
static final int MAX_INITIAL_SELECTION_LENGTH = MEMORY_EFFICIENT_TEXT_LENGTH / 2;
|
||||
|
||||
@NonNull
|
||||
private InitialSurroundingText mInitialSurroundingText = new InitialSurroundingText();
|
||||
@Nullable
|
||||
private SurroundingText mInitialSurroundingText = null;
|
||||
|
||||
|
||||
/**
|
||||
* Editors may use this method to provide initial input text to IMEs. As the surrounding text
|
||||
@@ -607,6 +609,12 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
public void setInitialSurroundingSubText(@NonNull CharSequence subText, int subTextStart) {
|
||||
Objects.requireNonNull(subText);
|
||||
|
||||
// For privacy protection reason, we don't carry password inputs to IMEs.
|
||||
if (isPasswordInputType(inputType)) {
|
||||
mInitialSurroundingText = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Swap selection start and end if necessary.
|
||||
final int subTextSelStart = initialSelStart > initialSelEnd
|
||||
? initialSelEnd - subTextStart : initialSelStart - subTextStart;
|
||||
@@ -616,23 +624,17 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
final int subTextLength = subText.length();
|
||||
// Unknown or invalid selection.
|
||||
if (subTextStart < 0 || subTextSelStart < 0 || subTextSelEnd > subTextLength) {
|
||||
mInitialSurroundingText = new InitialSurroundingText();
|
||||
return;
|
||||
}
|
||||
|
||||
// For privacy protection reason, we don't carry password inputs to IMEs.
|
||||
if (isPasswordInputType(inputType)) {
|
||||
mInitialSurroundingText = new InitialSurroundingText();
|
||||
mInitialSurroundingText = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (subTextLength <= MEMORY_EFFICIENT_TEXT_LENGTH) {
|
||||
mInitialSurroundingText = new InitialSurroundingText(subText, subTextSelStart,
|
||||
subTextSelEnd);
|
||||
mInitialSurroundingText = new SurroundingText(subText, subTextSelStart,
|
||||
subTextSelEnd, subTextStart);
|
||||
return;
|
||||
}
|
||||
|
||||
trimLongSurroundingText(subText, subTextSelStart, subTextSelEnd);
|
||||
trimLongSurroundingText(subText, subTextSelStart, subTextSelEnd, subTextStart);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -651,8 +653,10 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
* @param subText The long text that needs to be trimmed.
|
||||
* @param selStart The text offset of the start of the selection.
|
||||
* @param selEnd The text offset of the end of the selection
|
||||
* @param subTextStart The position that the input text got trimmed.
|
||||
*/
|
||||
private void trimLongSurroundingText(CharSequence subText, int selStart, int selEnd) {
|
||||
private void trimLongSurroundingText(CharSequence subText, int selStart, int selEnd,
|
||||
int subTextStart) {
|
||||
final int sourceSelLength = selEnd - selStart;
|
||||
// When the selected text is too long, drop it.
|
||||
final int newSelLength = (sourceSelLength > MAX_INITIAL_SELECTION_LENGTH)
|
||||
@@ -702,10 +706,13 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
// obj.
|
||||
newBeforeCursorHead = 0;
|
||||
final int newSelHead = newBeforeCursorHead + newBeforeCursorLength;
|
||||
mInitialSurroundingText = new InitialSurroundingText(
|
||||
newInitialSurroundingText, newSelHead, newSelHead + newSelLength);
|
||||
final int newOffset = subTextStart + selStart - newSelHead;
|
||||
mInitialSurroundingText = new SurroundingText(
|
||||
newInitialSurroundingText, newSelHead, newSelHead + newSelLength,
|
||||
newOffset);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get <var>length</var> characters of text before the current cursor position. May be
|
||||
* {@code null} when the protocol is not supported.
|
||||
@@ -720,7 +727,17 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
*/
|
||||
@Nullable
|
||||
public CharSequence getInitialTextBeforeCursor(int length, int flags) {
|
||||
return mInitialSurroundingText.getInitialTextBeforeCursor(length, flags);
|
||||
if (mInitialSurroundingText == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int selStart = Math.min(mInitialSurroundingText.getSelectionStart(),
|
||||
mInitialSurroundingText.getSelectionEnd());
|
||||
int n = Math.min(length, selStart);
|
||||
return ((flags & InputConnection.GET_TEXT_WITH_STYLES) != 0)
|
||||
? mInitialSurroundingText.getText().subSequence(selStart - n, selStart)
|
||||
: TextUtils.substring(mInitialSurroundingText.getText(), selStart - n,
|
||||
selStart);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -735,6 +752,10 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
*/
|
||||
@Nullable
|
||||
public CharSequence getInitialSelectedText(int flags) {
|
||||
if (mInitialSurroundingText == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Swap selection start and end if necessary.
|
||||
final int correctedTextSelStart = initialSelStart > initialSelEnd
|
||||
? initialSelEnd : initialSelStart;
|
||||
@@ -742,11 +763,21 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
? initialSelStart : initialSelEnd;
|
||||
|
||||
final int sourceSelLength = correctedTextSelEnd - correctedTextSelStart;
|
||||
if (initialSelStart < 0 || initialSelEnd < 0
|
||||
|| mInitialSurroundingText.getSelectionLength() != sourceSelLength) {
|
||||
int selStart = mInitialSurroundingText.getSelectionStart();
|
||||
int selEnd = mInitialSurroundingText.getSelectionEnd();
|
||||
if (selStart > selEnd) {
|
||||
int tmp = selStart;
|
||||
selStart = selEnd;
|
||||
selEnd = tmp;
|
||||
}
|
||||
final int selLength = selEnd - selStart;
|
||||
if (initialSelStart < 0 || initialSelEnd < 0 || selLength != sourceSelLength) {
|
||||
return null;
|
||||
}
|
||||
return mInitialSurroundingText.getInitialSelectedText(flags);
|
||||
|
||||
return ((flags & InputConnection.GET_TEXT_WITH_STYLES) != 0)
|
||||
? mInitialSurroundingText.getText().subSequence(selStart, selEnd)
|
||||
: TextUtils.substring(mInitialSurroundingText.getText(), selStart, selEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -763,7 +794,79 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
*/
|
||||
@Nullable
|
||||
public CharSequence getInitialTextAfterCursor(int length, int flags) {
|
||||
return mInitialSurroundingText.getInitialTextAfterCursor(length, flags);
|
||||
if (mInitialSurroundingText == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int surroundingTextLength = mInitialSurroundingText.getText().length();
|
||||
int selEnd = Math.max(mInitialSurroundingText.getSelectionStart(),
|
||||
mInitialSurroundingText.getSelectionEnd());
|
||||
int n = Math.min(length, surroundingTextLength - selEnd);
|
||||
return ((flags & InputConnection.GET_TEXT_WITH_STYLES) != 0)
|
||||
? mInitialSurroundingText.getText().subSequence(selEnd, selEnd + n)
|
||||
: TextUtils.substring(mInitialSurroundingText.getText(), selEnd, selEnd + n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the surrounding text around the current cursor, with <var>beforeLength</var> characters
|
||||
* of text before the cursor (start of the selection), <var>afterLength</var> characters of text
|
||||
* after the cursor (end of the selection), and all of the selected text.
|
||||
*
|
||||
* <p>The initial surrounding text for return could be trimmed if oversize. Fundamental trimming
|
||||
* rules are:</p>
|
||||
* <ul>
|
||||
* <li>The text before the cursor is the most important information to IMEs.</li>
|
||||
* <li>The text after the cursor is the second important information to IMEs.</li>
|
||||
* <li>The selected text is the least important information but it shall NEVER be truncated.
|
||||
* When it is too long, just drop it.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>For example, the subText can be viewed as TextBeforeCursor + Selection + TextAfterCursor.
|
||||
* The result could be:</p>
|
||||
* <ol>
|
||||
* <li>(maybeTrimmedAtHead)TextBeforeCursor + Selection
|
||||
* + TextAfterCursor(maybeTrimmedAtTail)</li>
|
||||
* <li>(maybeTrimmedAtHead)TextBeforeCursor + TextAfterCursor(maybeTrimmedAtTail)</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param beforeLength The expected length of the text before the cursor.
|
||||
* @param afterLength The expected length of the text after the cursor.
|
||||
* @param flags Supplies additional options controlling how the text is returned. May be either
|
||||
* {@code 0} or {@link InputConnection#GET_TEXT_WITH_STYLES}.
|
||||
* @return an {@link android.view.inputmethod.SurroundingText} object describing the surrounding
|
||||
* text and state of selection, or {@code null} if the editor or system could not support this
|
||||
* protocol.
|
||||
* @throws IllegalArgumentException if {@code beforeLength} or {@code afterLength} is negative.
|
||||
*/
|
||||
@Nullable
|
||||
public SurroundingText getInitialSurroundingText(
|
||||
@IntRange(from = 0) int beforeLength, @IntRange(from = 0) int afterLength,
|
||||
@InputConnection.GetTextType int flags) {
|
||||
Preconditions.checkArgumentNonnegative(beforeLength);
|
||||
Preconditions.checkArgumentNonnegative(afterLength);
|
||||
|
||||
if (mInitialSurroundingText == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int length = mInitialSurroundingText.getText().length();
|
||||
int selStart = mInitialSurroundingText.getSelectionStart();
|
||||
int selEnd = mInitialSurroundingText.getSelectionEnd();
|
||||
if (selStart > selEnd) {
|
||||
int tmp = selStart;
|
||||
selStart = selEnd;
|
||||
selEnd = tmp;
|
||||
}
|
||||
|
||||
int before = Math.min(beforeLength, selStart);
|
||||
int after = Math.min(selEnd + afterLength, length);
|
||||
int offset = selStart - before;
|
||||
CharSequence newText = ((flags & InputConnection.GET_TEXT_WITH_STYLES) != 0)
|
||||
? mInitialSurroundingText.getText().subSequence(offset, after)
|
||||
: TextUtils.substring(mInitialSurroundingText.getText(), offset, after);
|
||||
int newSelEnd = Math.min(selEnd - offset, length);
|
||||
return new SurroundingText(newText, before, newSelEnd,
|
||||
mInitialSurroundingText.getOffset() + offset);
|
||||
}
|
||||
|
||||
private static boolean isCutOnSurrogate(CharSequence sourceText, int cutPosition,
|
||||
@@ -893,7 +996,10 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
dest.writeInt(fieldId);
|
||||
dest.writeString(fieldName);
|
||||
dest.writeBundle(extras);
|
||||
mInitialSurroundingText.writeToParcel(dest, flags);
|
||||
dest.writeBoolean(mInitialSurroundingText != null);
|
||||
if (mInitialSurroundingText != null) {
|
||||
mInitialSurroundingText.writeToParcel(dest, flags);
|
||||
}
|
||||
if (hintLocales != null) {
|
||||
hintLocales.writeToParcel(dest, flags);
|
||||
} else {
|
||||
@@ -925,9 +1031,11 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
res.fieldId = source.readInt();
|
||||
res.fieldName = source.readString();
|
||||
res.extras = source.readBundle();
|
||||
InitialSurroundingText initialSurroundingText =
|
||||
InitialSurroundingText.CREATOR.createFromParcel(source);
|
||||
res.mInitialSurroundingText = initialSurroundingText;
|
||||
boolean hasInitialSurroundingText = source.readBoolean();
|
||||
if (hasInitialSurroundingText) {
|
||||
res.mInitialSurroundingText =
|
||||
SurroundingText.CREATOR.createFromParcel(source);
|
||||
}
|
||||
LocaleList hintLocales = LocaleList.CREATOR.createFromParcel(source);
|
||||
res.hintLocales = hintLocales.isEmpty() ? null : hintLocales;
|
||||
res.contentMimeTypes = source.readStringArray();
|
||||
@@ -943,120 +1051,4 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static final class InitialSurroundingText implements Parcelable {
|
||||
@Nullable final CharSequence mSurroundingText;
|
||||
final int mSelectionHead;
|
||||
final int mSelectionEnd;
|
||||
|
||||
InitialSurroundingText() {
|
||||
mSurroundingText = null;
|
||||
mSelectionHead = 0;
|
||||
mSelectionEnd = 0;
|
||||
}
|
||||
|
||||
InitialSurroundingText(@Nullable CharSequence surroundingText, int selectionHead,
|
||||
int selectionEnd) {
|
||||
// Copy the original text (without NoCopySpan) in case the original text is updated
|
||||
// later.
|
||||
mSurroundingText = copyWithParcelableSpans(surroundingText);
|
||||
mSelectionHead = selectionHead;
|
||||
mSelectionEnd = selectionEnd;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CharSequence getInitialTextBeforeCursor(int n, int flags) {
|
||||
if (mSurroundingText == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int length = Math.min(n, mSelectionHead);
|
||||
return ((flags & InputConnection.GET_TEXT_WITH_STYLES) != 0)
|
||||
? mSurroundingText.subSequence(mSelectionHead - length, mSelectionHead)
|
||||
: TextUtils.substring(mSurroundingText, mSelectionHead - length,
|
||||
mSelectionHead);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CharSequence getInitialSelectedText(int flags) {
|
||||
if (mSurroundingText == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ((flags & InputConnection.GET_TEXT_WITH_STYLES) != 0)
|
||||
? mSurroundingText.subSequence(mSelectionHead, mSelectionEnd)
|
||||
: TextUtils.substring(mSurroundingText, mSelectionHead, mSelectionEnd);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CharSequence getInitialTextAfterCursor(int n, int flags) {
|
||||
if (mSurroundingText == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int length = Math.min(n, mSurroundingText.length() - mSelectionEnd);
|
||||
return ((flags & InputConnection.GET_TEXT_WITH_STYLES) != 0)
|
||||
? mSurroundingText.subSequence(mSelectionEnd, mSelectionEnd + length)
|
||||
: TextUtils.substring(mSurroundingText, mSelectionEnd, mSelectionEnd + length);
|
||||
}
|
||||
|
||||
private int getSelectionLength() {
|
||||
return mSelectionEnd - mSelectionHead;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
TextUtils.writeToParcel(mSurroundingText, dest, flags);
|
||||
dest.writeInt(mSelectionHead);
|
||||
dest.writeInt(mSelectionEnd);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<InitialSurroundingText>
|
||||
CREATOR = new Parcelable.Creator<InitialSurroundingText>() {
|
||||
@Override
|
||||
public InitialSurroundingText createFromParcel(Parcel source) {
|
||||
final CharSequence initialText =
|
||||
TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
|
||||
final int selectionHead = source.readInt();
|
||||
final int selectionEnd = source.readInt();
|
||||
|
||||
return new InitialSurroundingText(initialText, selectionHead, selectionEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InitialSurroundingText[] newArray(int size) {
|
||||
return new InitialSurroundingText[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a copy of the given {@link CharSequence} object, with completely copy
|
||||
* {@link ParcelableSpan} instances.
|
||||
*
|
||||
* @param source the original {@link CharSequence} to be copied.
|
||||
* @return the copied {@link CharSequence}. {@code null} if {@code source} is {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
private static CharSequence copyWithParcelableSpans(@Nullable CharSequence source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
Parcel parcel = null;
|
||||
try {
|
||||
parcel = Parcel.obtain();
|
||||
TextUtils.writeToParcel(source, parcel, /* parcelableFlags= */ 0);
|
||||
parcel.setDataPosition(0);
|
||||
return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
|
||||
} finally {
|
||||
if (parcel != null) {
|
||||
parcel.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package android.view.inputmethod;
|
||||
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
@@ -74,7 +75,7 @@ public final class SurroundingText implements Parcelable {
|
||||
public SurroundingText(@NonNull final CharSequence text,
|
||||
@IntRange(from = 0) int selectionStart, @IntRange(from = 0) int selectionEnd,
|
||||
@IntRange(from = -1) int offset) {
|
||||
mText = text;
|
||||
mText = copyWithParcelableSpans(text);
|
||||
mSelectionStart = selectionStart;
|
||||
mSelectionEnd = selectionEnd;
|
||||
mOffset = offset;
|
||||
@@ -155,4 +156,29 @@ public final class SurroundingText implements Parcelable {
|
||||
return new SurroundingText[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a copy of the given {@link CharSequence} object, with completely copy
|
||||
* {@link ParcelableSpan} instances.
|
||||
*
|
||||
* @param source the original {@link CharSequence} to be copied.
|
||||
* @return the copied {@link CharSequence}. {@code null} if {@code source} is {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
private static CharSequence copyWithParcelableSpans(@Nullable CharSequence source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
Parcel parcel = null;
|
||||
try {
|
||||
parcel = Parcel.obtain();
|
||||
TextUtils.writeToParcel(source, parcel, /* parcelableFlags= */ 0);
|
||||
parcel.setDataPosition(0);
|
||||
return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
|
||||
} finally {
|
||||
if (parcel != null) {
|
||||
parcel.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,11 +109,15 @@ public class EditorInfoTest {
|
||||
editorInfo.initialSelEnd = editorInfo.initialSelStart + selectionLength;
|
||||
final int expectedTextBeforeCursorLength = 0;
|
||||
final int expectedTextAfterCursorLength = testText.length();
|
||||
final SurroundingText expectedSurroundingText =
|
||||
new SurroundingText(testText, editorInfo.initialSelStart,
|
||||
editorInfo.initialSelEnd, 0);
|
||||
|
||||
|
||||
editorInfo.setInitialSurroundingText(testText);
|
||||
|
||||
assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
|
||||
expectedTextAfterCursorLength);
|
||||
expectedTextAfterCursorLength, expectedSurroundingText);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -125,11 +129,14 @@ public class EditorInfoTest {
|
||||
editorInfo.initialSelEnd = testText.length();
|
||||
final int expectedTextBeforeCursorLength = testText.length();
|
||||
final int expectedTextAfterCursorLength = 0;
|
||||
final SurroundingText expectedSurroundingText =
|
||||
new SurroundingText(testText, editorInfo.initialSelStart,
|
||||
editorInfo.initialSelEnd, 0);
|
||||
|
||||
editorInfo.setInitialSurroundingText(testText);
|
||||
|
||||
assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
|
||||
expectedTextAfterCursorLength);
|
||||
expectedTextAfterCursorLength, expectedSurroundingText);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -141,11 +148,14 @@ public class EditorInfoTest {
|
||||
editorInfo.initialSelEnd = editorInfo.initialSelStart + selectionLength;
|
||||
final int expectedTextBeforeCursorLength = editorInfo.initialSelStart;
|
||||
final int expectedTextAfterCursorLength = testText.length() - editorInfo.initialSelEnd;
|
||||
final SurroundingText expectedSurroundingText =
|
||||
new SurroundingText(testText, editorInfo.initialSelStart,
|
||||
editorInfo.initialSelEnd, 0);
|
||||
|
||||
editorInfo.setInitialSurroundingText(testText);
|
||||
|
||||
assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
|
||||
expectedTextAfterCursorLength);
|
||||
expectedTextAfterCursorLength, expectedSurroundingText);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -158,11 +168,14 @@ public class EditorInfoTest {
|
||||
final int expectedTextBeforeCursorLength = testText.length() / 2;
|
||||
final int expectedTextAfterCursorLength = testText.length() - testText.length() / 2
|
||||
- selectionLength;
|
||||
|
||||
final SurroundingText expectedSurroundingText =
|
||||
new SurroundingText(testText,
|
||||
editorInfo.initialSelEnd,
|
||||
editorInfo.initialSelStart , 0);
|
||||
editorInfo.setInitialSurroundingText(testText);
|
||||
|
||||
assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
|
||||
expectedTextAfterCursorLength);
|
||||
expectedTextAfterCursorLength, expectedSurroundingText);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -174,9 +187,10 @@ public class EditorInfoTest {
|
||||
editorInfo.setInitialSurroundingText(testText);
|
||||
|
||||
assertExpectedTextLength(editorInfo,
|
||||
/* expectBeforeCursorLength= */null,
|
||||
/* expectSelectionLength= */null,
|
||||
/* expectAfterCursorLength= */null);
|
||||
/* expectBeforeCursorLength= */ null,
|
||||
/* expectSelectionLength= */ null,
|
||||
/* expectAfterCursorLength= */ null,
|
||||
/* expectSurroundingText= */ null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -190,11 +204,23 @@ public class EditorInfoTest {
|
||||
(int) (0.8 * (EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH - selectionLength)));
|
||||
final int expectedTextAfterCursorLength = EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH
|
||||
- expectedTextBeforeCursorLength - selectionLength;
|
||||
final int offset = editorInfo.initialSelStart - expectedTextBeforeCursorLength;
|
||||
final CharSequence beforeCursor = testText.subSequence(
|
||||
offset, offset + expectedTextBeforeCursorLength);
|
||||
final CharSequence afterCursor = testText.subSequence(editorInfo.initialSelEnd,
|
||||
editorInfo.initialSelEnd + expectedTextAfterCursorLength);
|
||||
final CharSequence selectedText = testText.subSequence(editorInfo.initialSelStart,
|
||||
editorInfo.initialSelEnd);
|
||||
|
||||
final SurroundingText expectedSurroundingText =
|
||||
new SurroundingText(TextUtils.concat(beforeCursor, selectedText, afterCursor),
|
||||
expectedTextBeforeCursorLength,
|
||||
expectedTextBeforeCursorLength + selectionLength, offset);
|
||||
|
||||
editorInfo.setInitialSurroundingText(testText);
|
||||
|
||||
assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
|
||||
expectedTextAfterCursorLength);
|
||||
expectedTextAfterCursorLength, expectedSurroundingText);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -207,11 +233,22 @@ public class EditorInfoTest {
|
||||
final int expectedTextBeforeCursorLength = Math.min(editorInfo.initialSelStart,
|
||||
(int) (0.8 * EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH));
|
||||
final int expectedTextAfterCursorLength = testText.length() - editorInfo.initialSelEnd;
|
||||
final CharSequence before = testText.subSequence(
|
||||
editorInfo.initialSelStart - expectedTextBeforeCursorLength,
|
||||
expectedTextBeforeCursorLength);
|
||||
final CharSequence after = testText.subSequence(editorInfo.initialSelEnd,
|
||||
editorInfo.initialSelEnd + expectedTextAfterCursorLength);
|
||||
final SurroundingText expectedSurroundingText =
|
||||
new SurroundingText(TextUtils.concat(before, after),
|
||||
expectedTextBeforeCursorLength,
|
||||
expectedTextBeforeCursorLength,
|
||||
editorInfo.initialSelStart - expectedTextBeforeCursorLength);
|
||||
|
||||
editorInfo.setInitialSurroundingText(testText);
|
||||
|
||||
assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength,
|
||||
/* expectSelectionLength= */null, expectedTextAfterCursorLength);
|
||||
/* expectSelectionLength= */null, expectedTextAfterCursorLength,
|
||||
expectedSurroundingText);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -269,6 +306,19 @@ public class EditorInfoTest {
|
||||
InputConnection.GET_TEXT_WITH_STYLES),
|
||||
targetEditorInfo.getInitialTextAfterCursor(LONG_EXP_TEXT_LENGTH,
|
||||
InputConnection.GET_TEXT_WITH_STYLES)));
|
||||
|
||||
final SurroundingText sourceSurroundingText = sourceEditorInfo.getInitialSurroundingText(
|
||||
LONG_EXP_TEXT_LENGTH, LONG_EXP_TEXT_LENGTH, InputConnection.GET_TEXT_WITH_STYLES);
|
||||
final SurroundingText targetSurroundingText = targetEditorInfo.getInitialSurroundingText(
|
||||
LONG_EXP_TEXT_LENGTH, LONG_EXP_TEXT_LENGTH, InputConnection.GET_TEXT_WITH_STYLES);
|
||||
|
||||
assertTrue(TextUtils.equals(sourceSurroundingText.getText(),
|
||||
targetSurroundingText.getText()));
|
||||
assertEquals(sourceSurroundingText.getSelectionStart(),
|
||||
targetSurroundingText.getSelectionStart());
|
||||
assertEquals(sourceSurroundingText.getSelectionEnd(),
|
||||
targetSurroundingText.getSelectionEnd());
|
||||
assertEquals(sourceSurroundingText.getOffset(), targetSurroundingText.getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -338,7 +388,8 @@ public class EditorInfoTest {
|
||||
|
||||
private static void assertExpectedTextLength(EditorInfo editorInfo,
|
||||
@Nullable Integer expectBeforeCursorLength, @Nullable Integer expectSelectionLength,
|
||||
@Nullable Integer expectAfterCursorLength) {
|
||||
@Nullable Integer expectAfterCursorLength,
|
||||
@Nullable SurroundingText expectSurroundingText) {
|
||||
final CharSequence textBeforeCursor =
|
||||
editorInfo.getInitialTextBeforeCursor(LONG_EXP_TEXT_LENGTH,
|
||||
InputConnection.GET_TEXT_WITH_STYLES);
|
||||
@@ -347,6 +398,10 @@ public class EditorInfoTest {
|
||||
final CharSequence textAfterCursor =
|
||||
editorInfo.getInitialTextAfterCursor(LONG_EXP_TEXT_LENGTH,
|
||||
InputConnection.GET_TEXT_WITH_STYLES);
|
||||
final SurroundingText surroundingText = editorInfo.getInitialSurroundingText(
|
||||
LONG_EXP_TEXT_LENGTH,
|
||||
LONG_EXP_TEXT_LENGTH,
|
||||
InputConnection.GET_TEXT_WITH_STYLES);
|
||||
|
||||
if (expectBeforeCursorLength == null) {
|
||||
assertNull(textBeforeCursor);
|
||||
@@ -365,6 +420,18 @@ public class EditorInfoTest {
|
||||
} else {
|
||||
assertEquals(expectAfterCursorLength.intValue(), textAfterCursor.length());
|
||||
}
|
||||
|
||||
if (expectSurroundingText == null) {
|
||||
assertNull(surroundingText);
|
||||
} else {
|
||||
assertTrue(TextUtils.equals(
|
||||
expectSurroundingText.getText(), surroundingText.getText()));
|
||||
assertEquals(expectSurroundingText.getSelectionStart(),
|
||||
surroundingText.getSelectionStart());
|
||||
assertEquals(expectSurroundingText.getSelectionEnd(),
|
||||
surroundingText.getSelectionEnd());
|
||||
assertEquals(expectSurroundingText.getOffset(), surroundingText.getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
private static CharSequence createTestText(int surroundingLength) {
|
||||
|
||||
Reference in New Issue
Block a user