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

Commit be60f06a authored by Abodunrinwa Toki's avatar Abodunrinwa Toki
Browse files

Increase the duration allowed for a TC result.

Increase the duration allowed for a TextClassifier (TC) result when
it is being initialized for the first time.
Initialization typically takes more time that other calls to the TC.
A timeout during initialization means the user doesn't see the
effect of running the TC the first time. Subsequent calls typically
work fine as they're less likely to timeout.
We increase this value only slightly because we don't want the user
waiting too long for a slow TC's result. Finding the right balance
is an art and most likely depends on the TC being used.

Note that although a TextView's TC can change for each individual
call to the TC, such a situation does not benefit from the bump in
the timeout. Again, we really want to discourage larger timeouts.

Fixes: 66217281
Test: bit FrameworksCoreTests:android.widget.TextViewActivityTest
Test: bit CtsWidgetTestCases:android.widget.cts.TextViewTest
Test: Manual test:
  - Delayed TextClassifier response by about 150ms (allowing only 50ms for initialization)
  - Before cl: Sometimes the result is not shown to the user the
    first time the textclassifier runs
  - After cl: Results consistently show for even for first
    textclassifier call
Merged-In: Iabc8279fa57ef6a9a2db0c7e9c7e3ab8c131bf02
Change-Id: Iabc8279fa57ef6a9a2db0c7e9c7e3ab8c131bf02
parent 6e326268
Loading
Loading
Loading
Loading
+26 −11
Original line number Original line Diff line number Diff line
@@ -51,12 +51,6 @@ final class SelectionActionModeHelper {


    private static final String LOG_TAG = "SelectActionModeHelper";
    private static final String LOG_TAG = "SelectActionModeHelper";


    /**
     * Maximum time (in milliseconds) to wait for a result before timing out.
     */
    // TODO: Consider making this a ViewConfiguration.
    private static final int TIMEOUT_DURATION = 200;

    private final Editor mEditor;
    private final Editor mEditor;
    private final TextView mTextView;
    private final TextView mTextView;
    private final TextClassificationHelper mTextClassificationHelper;
    private final TextClassificationHelper mTextClassificationHelper;
@@ -89,7 +83,7 @@ final class SelectionActionModeHelper {
            resetTextClassificationHelper();
            resetTextClassificationHelper();
            mTextClassificationAsyncTask = new TextClassificationAsyncTask(
            mTextClassificationAsyncTask = new TextClassificationAsyncTask(
                    mTextView,
                    mTextView,
                    TIMEOUT_DURATION,
                    mTextClassificationHelper.getTimeoutDuration(),
                    adjustSelection
                    adjustSelection
                            ? mTextClassificationHelper::suggestSelection
                            ? mTextClassificationHelper::suggestSelection
                            : mTextClassificationHelper::classifyText,
                            : mTextClassificationHelper::classifyText,
@@ -106,7 +100,7 @@ final class SelectionActionModeHelper {
            resetTextClassificationHelper();
            resetTextClassificationHelper();
            mTextClassificationAsyncTask = new TextClassificationAsyncTask(
            mTextClassificationAsyncTask = new TextClassificationAsyncTask(
                    mTextView,
                    mTextView,
                    TIMEOUT_DURATION,
                    mTextClassificationHelper.getTimeoutDuration(),
                    mTextClassificationHelper::classifyText,
                    mTextClassificationHelper::classifyText,
                    this::invalidateActionMode)
                    this::invalidateActionMode)
                    .execute();
                    .execute();
@@ -538,7 +532,7 @@ final class SelectionActionModeHelper {
    private static final class TextClassificationAsyncTask
    private static final class TextClassificationAsyncTask
            extends AsyncTask<Void, Void, SelectionResult> {
            extends AsyncTask<Void, Void, SelectionResult> {


        private final int mTimeOutDuration;
        private final long mTimeOutDuration;
        private final Supplier<SelectionResult> mSelectionResultSupplier;
        private final Supplier<SelectionResult> mSelectionResultSupplier;
        private final Consumer<SelectionResult> mSelectionResultCallback;
        private final Consumer<SelectionResult> mSelectionResultCallback;
        private final TextView mTextView;
        private final TextView mTextView;
@@ -551,7 +545,7 @@ final class SelectionActionModeHelper {
         * @param selectionResultCallback receives the selection results. Runs on the UiThread
         * @param selectionResultCallback receives the selection results. Runs on the UiThread
         */
         */
        TextClassificationAsyncTask(
        TextClassificationAsyncTask(
                @NonNull TextView textView, int timeOut,
                @NonNull TextView textView, long timeOut,
                @NonNull Supplier<SelectionResult> selectionResultSupplier,
                @NonNull Supplier<SelectionResult> selectionResultSupplier,
                @NonNull Consumer<SelectionResult> selectionResultCallback) {
                @NonNull Consumer<SelectionResult> selectionResultCallback) {
            super(textView != null ? textView.getHandler() : null);
            super(textView != null ? textView.getHandler() : null);
@@ -623,6 +617,9 @@ final class SelectionActionModeHelper {
        private LocaleList mLastClassificationLocales;
        private LocaleList mLastClassificationLocales;
        private SelectionResult mLastClassificationResult;
        private SelectionResult mLastClassificationResult;


        /** Whether the TextClassifier has been initialized. */
        private boolean mHot;

        TextClassificationHelper(TextClassifier textClassifier,
        TextClassificationHelper(TextClassifier textClassifier,
                CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
                CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
            reset(textClassifier, text, selectionStart, selectionEnd, locales);
            reset(textClassifier, text, selectionStart, selectionEnd, locales);
@@ -642,11 +639,13 @@ final class SelectionActionModeHelper {


        @WorkerThread
        @WorkerThread
        public SelectionResult classifyText() {
        public SelectionResult classifyText() {
            return performClassification(null);
            mHot = true;
            return performClassification(null /* selection */);
        }
        }


        @WorkerThread
        @WorkerThread
        public SelectionResult suggestSelection() {
        public SelectionResult suggestSelection() {
            mHot = true;
            trimText();
            trimText();
            final TextSelection selection = mTextClassifier.suggestSelection(
            final TextSelection selection = mTextClassifier.suggestSelection(
                    mTrimmedText, mRelativeStart, mRelativeEnd, mLocales);
                    mTrimmedText, mRelativeStart, mRelativeEnd, mLocales);
@@ -655,6 +654,22 @@ final class SelectionActionModeHelper {
            return performClassification(selection);
            return performClassification(selection);
        }
        }


        /**
         * Maximum time (in milliseconds) to wait for a textclassifier result before timing out.
         */
        // TODO: Consider making this a ViewConfiguration.
        public long getTimeoutDuration() {
            if (mHot) {
                return 200;
            } else {
                // Return a slightly larger number than usual when the TextClassifier is first
                // initialized. Initialization would usually take longer than subsequent calls to
                // the TextClassifier. The impact of this on the UI is that we do not show the
                // selection handles or toolbar until after this timeout.
                return 500;
            }
        }

        private SelectionResult performClassification(@Nullable TextSelection selection) {
        private SelectionResult performClassification(@Nullable TextSelection selection) {
            if (!Objects.equals(mText, mLastClassificationText)
            if (!Objects.equals(mText, mLastClassificationText)
                    || mSelectionStart != mLastClassificationSelectionStart
                    || mSelectionStart != mLastClassificationSelectionStart