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

Commit 3895a035 authored by Chang Li's avatar Chang Li
Browse files

Conditionally swallows Exceptions from TextClassificationAsyncTask.

After ag/12036126, the AsyncTask may throw RuntimeException if we
destroy the TCSession before it is done. However, this kind of Exception
should be swallowed silently because we do not need the result anymore.

In b/172627102, the test fails because we perform a cut action to the
text immediately after we trigger a selection. The cut action will
destroy and TCSession and thus cause a session-already-destroyed
Exception in the AsyncTask. With this, we will check whether the Text
Classifier has already been destroyed and therefore can fix it.

Bug: 172627102
Fix: 172627102
Test: atest AccessibilityTextTraversalTest.java

Change-Id: Ia2ca04a06e97858cd897e5d35f707f5edeee56cf
parent 4bc7c491
Loading
Loading
Loading
Loading
+28 −5
Original line number Diff line number Diff line
@@ -156,7 +156,8 @@ public final class SelectionActionModeHelper {
                    mSmartSelectSprite != null
                            ? this::startSelectionActionModeWithSmartSelectAnimation
                            : this::startSelectionActionMode,
                    mTextClassificationHelper::getOriginalSelection)
                    mTextClassificationHelper::getOriginalSelection,
                    mTextClassificationHelper::isTextClassifierDestroyed)
                    .execute();
        }
    }
@@ -178,7 +179,8 @@ public final class SelectionActionModeHelper {
                    mTextClassificationHelper.getTimeoutDuration(),
                    mTextClassificationHelper::classifyText,
                    this::startLinkActionMode,
                    mTextClassificationHelper::getOriginalSelection)
                    mTextClassificationHelper::getOriginalSelection,
                    mTextClassificationHelper::isTextClassifierDestroyed)
                    .execute();
        }
    }
@@ -194,7 +196,8 @@ public final class SelectionActionModeHelper {
                    mTextClassificationHelper.getTimeoutDuration(),
                    mTextClassificationHelper::classifyText,
                    this::invalidateActionMode,
                    mTextClassificationHelper::getOriginalSelection)
                    mTextClassificationHelper::getOriginalSelection,
                    mTextClassificationHelper::isTextClassifierDestroyed)
                    .execute();
        }
    }
@@ -992,6 +995,7 @@ public final class SelectionActionModeHelper {
        private final Supplier<SelectionResult> mSelectionResultSupplier;
        private final Consumer<SelectionResult> mSelectionResultCallback;
        private final Supplier<SelectionResult> mTimeOutResultSupplier;
        private final Supplier<Boolean> mIsTextClassifierDestroyedSupplier;
        private final TextView mTextView;
        private final String mOriginalText;

@@ -1006,13 +1010,16 @@ public final class SelectionActionModeHelper {
                @NonNull TextView textView, int timeOut,
                @NonNull Supplier<SelectionResult> selectionResultSupplier,
                @NonNull Consumer<SelectionResult> selectionResultCallback,
                @NonNull Supplier<SelectionResult> timeOutResultSupplier) {
                @NonNull Supplier<SelectionResult> timeOutResultSupplier,
                @NonNull Supplier<Boolean> isTextClassifierDestroyedSupplier) {
            super(textView != null ? textView.getHandler() : null);
            mTextView = Objects.requireNonNull(textView);
            mTimeOutDuration = timeOut;
            mSelectionResultSupplier = Objects.requireNonNull(selectionResultSupplier);
            mSelectionResultCallback = Objects.requireNonNull(selectionResultCallback);
            mTimeOutResultSupplier = Objects.requireNonNull(timeOutResultSupplier);
            mIsTextClassifierDestroyedSupplier =
                    Objects.requireNonNull(isTextClassifierDestroyedSupplier);
            // Make a copy of the original text.
            mOriginalText = getText(mTextView).toString();
        }
@@ -1022,7 +1029,19 @@ public final class SelectionActionModeHelper {
        protected SelectionResult doInBackground(Void... params) {
            final Runnable onTimeOut = this::onTimeOut;
            mTextView.postDelayed(onTimeOut, mTimeOutDuration);
            final SelectionResult result = mSelectionResultSupplier.get();
            SelectionResult result = null;
            try {
                result = mSelectionResultSupplier.get();
            } catch (IllegalStateException e) {
                // Swallows the exception if the text classifier session is destroyed
                if (mIsTextClassifierDestroyedSupplier.get()) {
                    Log.w(LOG_TAG,
                          "TextClassificationAsyncTask failed because TextClassifier destroyed",
                          e);
                } else {
                    throw e;
                }
            }
            mTextView.removeCallbacks(onTimeOut);
            return result;
        }
@@ -1154,6 +1173,10 @@ public final class SelectionActionModeHelper {
            }
        }

        public boolean isTextClassifierDestroyed() {
          return mTextClassifier.get().isDestroyed();
        }

        private boolean isDarkLaunchEnabled() {
            return TextClassificationManager.getSettings(mContext).isModelDarkLaunchEnabled();
        }