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

Commit 5d6b6f28 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Allow TextInfo to store ParcelableSpans for TextService

This CL adds a new constructor of TextService so that spell
parcelable spans can be preserved in TextInfo.  The primary usage
scenario is to provide locale information for spell checker
service.

BUG: 15869548
Change-Id: Ib58ece68dee4c6187d469049fca8c35a307c7a01
parent 9c5ac7ae
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -35302,6 +35302,7 @@ package android.view.textservice {
  public final class TextInfo implements android.os.Parcelable {
    ctor public TextInfo(java.lang.String);
    ctor public TextInfo(java.lang.String, int, int);
    ctor public TextInfo(java.lang.CharSequence, int, int, int, int);
    ctor public TextInfo(android.os.Parcel);
    method public int describeContents();
    method public int getCookie();
+52 −15
Original line number Diff line number Diff line
@@ -18,43 +18,69 @@ package android.view.textservice;

import android.os.Parcel;
import android.os.Parcelable;
import android.text.ParcelableSpan;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.SpellCheckSpan;

/**
 * This class contains a metadata of the input of TextService
 */
public final class TextInfo implements Parcelable {
    private final String mText;
    private final CharSequence mCharSequence;
    private final int mCookie;
    private final int mSequence;
    private final int mSequenceNumber;

    /**
     * Constructor.
     * @param text the text which will be input to TextService
     */
    public TextInfo(String text) {
        this(text, 0, 0);
        this(text, 0, 0, 0, 0);
    }

    /**
     * Constructor.
     * @param text the text which will be input to TextService
     * @param cookie the cookie for this TextInfo
     * @param sequence the sequence number for this TextInfo
     * @param sequenceNumber the sequence number for this TextInfo
     */
    public TextInfo(String text, int cookie, int sequence) {
        if (TextUtils.isEmpty(text)) {
            throw new IllegalArgumentException(text);
    public TextInfo(String text, int cookie, int sequenceNumber) {
        this(text, 0, 0, 0, 0);
    }
        mText = text;

    /**
     * Constructor.
     * @param charSequence the text which will be input to TextService. Attached spans that
     * implement {@link ParcelableSpan} will also be marshaled alongside with the text.
     * @param start the beginning of the range of text (inclusive).
     * @param end the end of the range of text (exclusive).
     * @param cookie the cookie for this TextInfo
     * @param sequenceNumber the sequence number for this TextInfo
     */
    public TextInfo(CharSequence charSequence, int start, int end, int cookie, int sequenceNumber) {
        if (TextUtils.isEmpty(charSequence)) {
            throw new IllegalArgumentException("charSequence is empty");
        }
        // Create a snapshot of the text including spans in case they are updated outside later.
        final SpannableStringBuilder spannableString =
                new SpannableStringBuilder(charSequence, start, end);
        // SpellCheckSpan is for internal use. We do not want to marshal this for TextService.
        final SpellCheckSpan[] spans = spannableString.getSpans(0, spannableString.length(),
                SpellCheckSpan.class);
        for (int i = 0; i < spans.length; ++i) {
            spannableString.removeSpan(spans[i]);
        }

        mCharSequence = spannableString;
        mCookie = cookie;
        mSequence = sequence;
        mSequenceNumber = sequenceNumber;
    }

    public TextInfo(Parcel source) {
        mText = source.readString();
        mCharSequence = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
        mCookie = source.readInt();
        mSequence = source.readInt();
        mSequenceNumber = source.readInt();
    }

    /**
@@ -65,16 +91,27 @@ public final class TextInfo implements Parcelable {
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mText);
        TextUtils.writeToParcel(mCharSequence, dest, flags);
        dest.writeInt(mCookie);
        dest.writeInt(mSequence);
        dest.writeInt(mSequenceNumber);
    }

    /**
     * @return the text which is an input of a text service
     */
    public String getText() {
        return mText;
        if (mCharSequence == null) {
            return null;
        }
        return mCharSequence.toString();
    }

    /**
     * @return the charSequence which is an input of a text service. This may have some parcelable
     * spans.
     */
    public CharSequence getCharSequence() {
        return mCharSequence;
    }

    /**
@@ -88,7 +125,7 @@ public final class TextInfo implements Parcelable {
     * @return the sequence of TextInfo
     */
    public int getSequence() {
        return mSequence;
        return mSequenceNumber;
    }

    /**
+6 −9
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package android.widget;
import android.content.Context;
import android.text.Editable;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.WordIterator;
@@ -42,7 +41,7 @@ import java.util.Locale;


/**
 * Helper class for TextView. Bridge between the TextView and the Dictionnary service.
 * Helper class for TextView. Bridge between the TextView and the Dictionary service.
 *
 * @hide
 */
@@ -83,7 +82,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
    // The mLength first elements of the above arrays have been initialized
    private int mLength;

    // Parsers on chunck of text, cutting text into words that will be checked
    // Parsers on chunk of text, cutting text into words that will be checked
    private SpellParser[] mSpellParsers = new SpellParser[0];

    private int mSpanSequenceCounter = 0;
@@ -286,14 +285,12 @@ public class SpellChecker implements SpellCheckerSessionListener {
                isEditing = selectionEnd < start || selectionStart > end;
            }
            if (start >= 0 && end > start && isEditing) {
                final String word = (editable instanceof SpannableStringBuilder) ?
                        ((SpannableStringBuilder) editable).substring(start, end) :
                        editable.subSequence(start, end).toString();
                spellCheckSpan.setSpellCheckInProgress(true);
                textInfos[textInfosCount++] = new TextInfo(word, mCookie, mIds[i]);
                final TextInfo textInfo = new TextInfo(editable, start, end, mCookie, mIds[i]);
                textInfos[textInfosCount++] = textInfo;
                if (DBG) {
                    Log.d(TAG, "create TextInfo: (" + i + "/" + mLength + ")" + word
                            + ", cookie = " + mCookie + ", seq = "
                    Log.d(TAG, "create TextInfo: (" + i + "/" + mLength + ") text = "
                            + textInfo.getSequence() + ", cookie = " + mCookie + ", seq = "
                            + mIds[i] + ", sel start = " + selectionStart + ", sel end = "
                            + selectionEnd + ", start = " + start + ", end = " + end);
                }