Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c5404b48 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Refine the surrounding text copy logic"

parents 934de361 93cdaafc
Loading
Loading
Loading
Loading
+40 −7
Original line number Diff line number Diff line
@@ -22,13 +22,14 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.text.Editable;
import android.text.InputType;
import android.text.ParcelableSpan;
import android.text.TextUtils;
import android.util.Printer;
import android.view.View;
@@ -543,6 +544,9 @@ public class EditorInfo implements InputType, Parcelable {
     * {@code #getInitialSelectedText}, and {@code #getInitialTextBeforeCursor}. System is allowed
     * to trim {@code sourceText} for various reasons while keeping the most valuable data to IMEs.
     *
     * Starting from {@link VERSION_CODES#S}, spans that do not implement {@link Parcelable} will
     * be automatically dropped.
     *
     * <p><strong>Editor authors: </strong>Providing the initial input text helps reducing IPC calls
     * for IMEs to provide many modern features right after the connection setup. We recommend
     * calling this method in your implementation.
@@ -562,14 +566,16 @@ public class EditorInfo implements InputType, Parcelable {
     * try to include the selected text within {@code subText} to give the system best flexibility
     * to choose where and how to trim {@code subText} when necessary.
     *
     * Starting from {@link VERSION_CODES#S}, spans that do not implement {@link Parcelable} will
     * be automatically dropped.
     *
     * @param subText The input text. When it was trimmed, {@code subTextStart} must be provided
     *                correctly.
     * @param subTextStart  The position that the input text got trimmed. For example, when the
     *                      editor wants to trim out the first 10 chars, subTextStart should be 10.
     */
    public void setInitialSurroundingSubText(@NonNull CharSequence subText, int subTextStart) {
        CharSequence newSubText = Editable.Factory.getInstance().newEditable(subText);
        Objects.requireNonNull(newSubText);
        Objects.requireNonNull(subText);

        // Swap selection start and end if necessary.
        final int subTextSelStart = initialSelStart > initialSelEnd
@@ -577,7 +583,7 @@ public class EditorInfo implements InputType, Parcelable {
        final int subTextSelEnd = initialSelStart > initialSelEnd
                ? initialSelStart - subTextStart : initialSelEnd - subTextStart;

        final int subTextLength = newSubText.length();
        final int subTextLength = subText.length();
        // Unknown or invalid selection.
        if (subTextStart < 0 || subTextSelStart < 0 || subTextSelEnd > subTextLength) {
            mInitialSurroundingText = new InitialSurroundingText();
@@ -591,12 +597,12 @@ public class EditorInfo implements InputType, Parcelable {
        }

        if (subTextLength <= MEMORY_EFFICIENT_TEXT_LENGTH) {
            mInitialSurroundingText = new InitialSurroundingText(newSubText, subTextSelStart,
            mInitialSurroundingText = new InitialSurroundingText(subText, subTextSelStart,
                    subTextSelEnd);
            return;
        }

        trimLongSurroundingText(newSubText, subTextSelStart, subTextSelEnd);
        trimLongSurroundingText(subText, subTextSelStart, subTextSelEnd);
    }

    /**
@@ -901,7 +907,9 @@ public class EditorInfo implements InputType, Parcelable {

        InitialSurroundingText(@Nullable CharSequence surroundingText, int selectionHead,
                int selectionEnd) {
            mSurroundingText = surroundingText;
            // Copy the original text (without NoCopySpan) in case the original text is updated
            // later.
            mSurroundingText = copyWithParcelableSpans(surroundingText);
            mSelectionHead = selectionHead;
            mSelectionEnd = selectionEnd;
        }
@@ -975,5 +983,30 @@ public class EditorInfo implements InputType, Parcelable {
                        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();
                }
            }
        }
    }
}
+3 −6
Original line number Diff line number Diff line
@@ -274,13 +274,10 @@ public class EditorInfoTest {
        editorInfo.inputType = EditorInfo.TYPE_CLASS_TEXT;

        editorInfo.setInitialSurroundingText(sb);
        sb.setLength(0);
        editorInfo.writeToParcel(parcel, 0);
        sb.setLength(/* newLength= */ 0);
        editorInfo.writeToParcel(parcel, /* flags= */ 0);

        try {
            editorInfo.getInitialTextBeforeCursor(60, 1);
            fail("Test shouldn't have exception");
        } catch (AssertionError e) { }
        editorInfo.getInitialTextBeforeCursor(/* length= */ 60, /* flags= */ 1);
    }

    private static void assertExpectedTextLength(EditorInfo editorInfo,