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

Commit 0ebe70cb authored by Wilson Wu's avatar Wilson Wu
Browse files

Prevent exception when surrounding text retrieval

We use same reference from TextView to set the initial
surrounding text. The actual surrounding text may be
modified before retrieval since the mSurroundingText
is mutable. Use a copy of subText should avoid this
concurrent issue.

Bug: 160390184
Test: atest FrameworksCoreTests:EditorInfoTest
Change-Id: I6082a4cae2fcdc4c529dc14e2e5e7a45ab1aae4d
parent 76cfda57
Loading
Loading
Loading
Loading
+6 −4
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.os.UserHandle;
import android.os.UserHandle;
import android.text.Editable;
import android.text.InputType;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.Printer;
import android.util.Printer;
@@ -567,7 +568,8 @@ public class EditorInfo implements InputType, Parcelable {
     *                      editor wants to trim out the first 10 chars, subTextStart should be 10.
     *                      editor wants to trim out the first 10 chars, subTextStart should be 10.
     */
     */
    public void setInitialSurroundingSubText(@NonNull CharSequence subText, int subTextStart) {
    public void setInitialSurroundingSubText(@NonNull CharSequence subText, int subTextStart) {
        Objects.requireNonNull(subText);
        CharSequence newSubText = Editable.Factory.getInstance().newEditable(subText);
        Objects.requireNonNull(newSubText);


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


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


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


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


    /**
    /**
+19 −0
Original line number Original line Diff line number Diff line
@@ -264,6 +264,25 @@ public class EditorInfoTest {
                        InputConnection.GET_TEXT_WITH_STYLES)));
                        InputConnection.GET_TEXT_WITH_STYLES)));
    }
    }


    @Test
    public void surroundingTextRetrieval_writeToParcel_noException() {
        StringBuilder sb = new StringBuilder("abcdefg");
        Parcel parcel = Parcel.obtain();
        EditorInfo editorInfo = new EditorInfo();
        editorInfo.initialSelStart = 2;
        editorInfo.initialSelEnd = 5;
        editorInfo.inputType = EditorInfo.TYPE_CLASS_TEXT;

        editorInfo.setInitialSurroundingText(sb);
        sb.setLength(0);
        editorInfo.writeToParcel(parcel, 0);

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

    private static void assertExpectedTextLength(EditorInfo editorInfo,
    private static void assertExpectedTextLength(EditorInfo editorInfo,
            @Nullable Integer expectBeforeCursorLength, @Nullable Integer expectSelectionLength,
            @Nullable Integer expectBeforeCursorLength, @Nullable Integer expectSelectionLength,
            @Nullable Integer expectAfterCursorLength) {
            @Nullable Integer expectAfterCursorLength) {