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

Commit 2e853aa1 authored by Tony Mak's avatar Tony Mak
Browse files

Introduce TextSelection.Builder.setIncludeTextClassification and...

Introduce TextSelection.Builder.setIncludeTextClassification and TextSelection.getTextClassification()

This small API change enables us to optimize the latnecy of smart
selection.

To enable smart selection, TextView/WebView always call
textClassifier.suggestSelection and textClassifier.classifyText back to
back. There are a lot of overlaps between suggestSelection and
classifyText, e.g. both API calls classify the entity type of the text.
This optimization is important to make smart selection working
responsively, especially that we enforce a 200ms timeout in TextView.

This small API change allows the TextClassifier to implement smart
selection with just one single API call.

This change is backward-compatible.
If the text classifier is not updated to return the text classification
result in suggestSelection yet, clients can learn that by checking if
textSelection.getTextClassification() returns null. If so, the client
can then fallback to call ClassifyText().

You may find the textview integration in ag/13092679

Design doc: go/android-s-suggestselection

Bug: 173512834

Test: atest TextSelectionTest
Change-Id: If4cc827aa19d6d14c885cf10cd5ba16aa3041cf6
parent 68a3422b
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -56539,6 +56539,7 @@ package android.view.textclassifier {
    method @Nullable public String getId();
    method public int getSelectionEndIndex();
    method public int getSelectionStartIndex();
    method @Nullable public android.view.textclassifier.TextClassification getTextClassification();
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextSelection> CREATOR;
  }
@@ -56549,6 +56550,7 @@ package android.view.textclassifier {
    method @NonNull public android.view.textclassifier.TextSelection.Builder setEntityType(@NonNull String, @FloatRange(from=0.0, to=1.0) float);
    method @NonNull public android.view.textclassifier.TextSelection.Builder setExtras(@Nullable android.os.Bundle);
    method @NonNull public android.view.textclassifier.TextSelection.Builder setId(@Nullable String);
    method @NonNull public android.view.textclassifier.TextSelection.Builder setTextClassification(@Nullable android.view.textclassifier.TextClassification);
  }
  public static final class TextSelection.Request implements android.os.Parcelable {
@@ -56559,6 +56561,7 @@ package android.view.textclassifier {
    method @NonNull public android.os.Bundle getExtras();
    method @IntRange(from=0) public int getStartIndex();
    method @NonNull public CharSequence getText();
    method public boolean shouldIncludeTextClassification();
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextSelection.Request> CREATOR;
  }
@@ -56568,6 +56571,7 @@ package android.view.textclassifier {
    method @NonNull public android.view.textclassifier.TextSelection.Request build();
    method @NonNull public android.view.textclassifier.TextSelection.Request.Builder setDefaultLocales(@Nullable android.os.LocaleList);
    method @NonNull public android.view.textclassifier.TextSelection.Request.Builder setExtras(@Nullable android.os.Bundle);
    method @NonNull public android.view.textclassifier.TextSelection.Request.Builder setIncludeTextClassification(boolean);
  }
}
+68 −3
Original line number Diff line number Diff line
@@ -45,15 +45,19 @@ public final class TextSelection implements Parcelable {
    private final int mEndIndex;
    private final EntityConfidence mEntityConfidence;
    @Nullable private final String mId;
    @Nullable
    private final TextClassification mTextClassification;
    private final Bundle mExtras;

    private TextSelection(
            int startIndex, int endIndex, Map<String, Float> entityConfidence, String id,
            @Nullable TextClassification textClassification,
            Bundle extras) {
        mStartIndex = startIndex;
        mEndIndex = endIndex;
        mEntityConfidence = new EntityConfidence(entityConfidence);
        mId = id;
        mTextClassification = textClassification;
        mExtras = extras;
    }

@@ -110,6 +114,19 @@ public final class TextSelection implements Parcelable {
        return mId;
    }

    /**
     * Returns the text classification result of the suggested selection span. Enables the text
     * classification by calling
     * {@link TextSelection.Request.Builder#setIncludeTextClassification(boolean)}. If the text
     * classifier does not support it, a {@code null} is returned.
     *
     * @see TextSelection.Request.Builder#setIncludeTextClassification(boolean)
     */
    @Nullable
    public TextClassification getTextClassification() {
        return mTextClassification;
    }

    /**
     * Returns the extended data.
     *
@@ -138,6 +155,8 @@ public final class TextSelection implements Parcelable {
        private final Map<String, Float> mEntityConfidence = new ArrayMap<>();
        @Nullable private String mId;
        @Nullable
        private TextClassification mTextClassification;
        @Nullable
        private Bundle mExtras;

        /**
@@ -178,6 +197,21 @@ public final class TextSelection implements Parcelable {
            return this;
        }

        /**
         * Sets the text classification result of the suggested selection. If
         * {@link Request#shouldIncludeTextClassification()} is {@code true}, set this value.
         * Otherwise this value may be set to null. The intention of this method is to avoid
         * doing expensive work if the client is not interested in such result.
         *
         * @return this builder
         * @see Request#shouldIncludeTextClassification()
         */
        @NonNull
        public Builder setTextClassification(@Nullable TextClassification textClassification) {
            mTextClassification = textClassification;
            return this;
        }

        /**
         * Sets the extended data.
         *
@@ -196,7 +230,7 @@ public final class TextSelection implements Parcelable {
        public TextSelection build() {
            return new TextSelection(
                    mStartIndex, mEndIndex, mEntityConfidence, mId,
                    mExtras == null ? Bundle.EMPTY : mExtras);
                    mTextClassification, mExtras == null ? Bundle.EMPTY : mExtras);
        }
    }

@@ -210,6 +244,7 @@ public final class TextSelection implements Parcelable {
        private final int mEndIndex;
        @Nullable private final LocaleList mDefaultLocales;
        private final boolean mDarkLaunchAllowed;
        private final boolean mIncludeTextClassification;
        private final Bundle mExtras;
        @Nullable private SystemTextClassifierMetadata mSystemTcMetadata;

@@ -219,12 +254,14 @@ public final class TextSelection implements Parcelable {
                int endIndex,
                LocaleList defaultLocales,
                boolean darkLaunchAllowed,
                boolean includeTextClassification,
                Bundle extras) {
            mText = text;
            mStartIndex = startIndex;
            mEndIndex = endIndex;
            mDefaultLocales = defaultLocales;
            mDarkLaunchAllowed = darkLaunchAllowed;
            mIncludeTextClassification = includeTextClassification;
            mExtras = extras;
        }

@@ -302,6 +339,14 @@ public final class TextSelection implements Parcelable {
            return mSystemTcMetadata;
        }

        /**
         * Returns true if the client wants the text classifier to classify the text as well and
         * include a {@link TextClassification} object in the result.
         */
        public boolean shouldIncludeTextClassification() {
            return mIncludeTextClassification;
        }

        /**
         * Returns the extended data.
         *
@@ -320,9 +365,9 @@ public final class TextSelection implements Parcelable {
            private final CharSequence mText;
            private final int mStartIndex;
            private final int mEndIndex;

            @Nullable private LocaleList mDefaultLocales;
            private boolean mDarkLaunchAllowed;
            private boolean mIncludeTextClassification;
            private Bundle mExtras;

            /**
@@ -371,6 +416,21 @@ public final class TextSelection implements Parcelable {
                return this;
            }

            /**
             * @param includeTextClassification If true, suggests the TextClassifier to classify the
             *     text in the suggested selection span and include a TextClassification object in
             *     the result. The TextClassifier may not support this and in which case,
             *     {@link TextSelection#getTextClassification()} returns {@code null}.
             *
             * @return this builder.
             * @see TextSelection#getTextClassification()
             */
            @NonNull
            public Builder setIncludeTextClassification(boolean includeTextClassification) {
                mIncludeTextClassification = includeTextClassification;
                return this;
            }

            /**
             * Sets the extended data.
             *
@@ -389,6 +449,7 @@ public final class TextSelection implements Parcelable {
            public Request build() {
                return new Request(new SpannedString(mText), mStartIndex, mEndIndex,
                        mDefaultLocales, mDarkLaunchAllowed,
                        mIncludeTextClassification,
                        mExtras == null ? Bundle.EMPTY : mExtras);
            }
        }
@@ -406,6 +467,7 @@ public final class TextSelection implements Parcelable {
            dest.writeParcelable(mDefaultLocales, flags);
            dest.writeBundle(mExtras);
            dest.writeParcelable(mSystemTcMetadata, flags);
            dest.writeBoolean(mIncludeTextClassification);
        }

        private static Request readFromParcel(Parcel in) {
@@ -415,9 +477,10 @@ public final class TextSelection implements Parcelable {
            final LocaleList defaultLocales = in.readParcelable(null);
            final Bundle extras = in.readBundle();
            final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null);
            final boolean includeTextClassification = in.readBoolean();

            final Request request = new Request(text, startIndex, endIndex, defaultLocales,
                    /* darkLaunchAllowed= */ false, extras);
                    /* darkLaunchAllowed= */ false, includeTextClassification, extras);
            request.setSystemTextClassifierMetadata(systemTcMetadata);
            return request;
        }
@@ -448,6 +511,7 @@ public final class TextSelection implements Parcelable {
        mEntityConfidence.writeToParcel(dest, flags);
        dest.writeString(mId);
        dest.writeBundle(mExtras);
        dest.writeParcelable(mTextClassification, flags);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<TextSelection> CREATOR =
@@ -469,5 +533,6 @@ public final class TextSelection implements Parcelable {
        mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
        mId = in.readString();
        mExtras = in.readBundle();
        mTextClassification = in.readParcelable(TextClassification.class.getClassLoader());
    }
}