OSDN Git Service

Increase the duration allowed for a TC result.
authorAbodunrinwa Toki <toki@google.com>
Wed, 27 Sep 2017 01:38:55 +0000 (02:38 +0100)
committerAbodunrinwa Toki <toki@google.com>
Fri, 29 Sep 2017 20:41:54 +0000 (21:41 +0100)
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

core/java/android/widget/SelectionActionModeHelper.java

index 6c13e0c..513a18c 100644 (file)
@@ -51,12 +51,6 @@ final class SelectionActionModeHelper {
 
     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 TextView mTextView;
     private final TextClassificationHelper mTextClassificationHelper;
@@ -89,7 +83,7 @@ final class SelectionActionModeHelper {
             resetTextClassificationHelper();
             mTextClassificationAsyncTask = new TextClassificationAsyncTask(
                     mTextView,
-                    TIMEOUT_DURATION,
+                    mTextClassificationHelper.getTimeoutDuration(),
                     adjustSelection
                             ? mTextClassificationHelper::suggestSelection
                             : mTextClassificationHelper::classifyText,
@@ -106,7 +100,7 @@ final class SelectionActionModeHelper {
             resetTextClassificationHelper();
             mTextClassificationAsyncTask = new TextClassificationAsyncTask(
                     mTextView,
-                    TIMEOUT_DURATION,
+                    mTextClassificationHelper.getTimeoutDuration(),
                     mTextClassificationHelper::classifyText,
                     this::invalidateActionMode)
                     .execute();
@@ -538,7 +532,7 @@ final class SelectionActionModeHelper {
     private static final class TextClassificationAsyncTask
             extends AsyncTask<Void, Void, SelectionResult> {
 
-        private final int mTimeOutDuration;
+        private final long mTimeOutDuration;
         private final Supplier<SelectionResult> mSelectionResultSupplier;
         private final Consumer<SelectionResult> mSelectionResultCallback;
         private final TextView mTextView;
@@ -551,7 +545,7 @@ final class SelectionActionModeHelper {
          * @param selectionResultCallback receives the selection results. Runs on the UiThread
          */
         TextClassificationAsyncTask(
-                @NonNull TextView textView, int timeOut,
+                @NonNull TextView textView, long timeOut,
                 @NonNull Supplier<SelectionResult> selectionResultSupplier,
                 @NonNull Consumer<SelectionResult> selectionResultCallback) {
             super(textView != null ? textView.getHandler() : null);
@@ -623,6 +617,9 @@ final class SelectionActionModeHelper {
         private LocaleList mLastClassificationLocales;
         private SelectionResult mLastClassificationResult;
 
+        /** Whether the TextClassifier has been initialized. */
+        private boolean mHot;
+
         TextClassificationHelper(TextClassifier textClassifier,
                 CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
             reset(textClassifier, text, selectionStart, selectionEnd, locales);
@@ -642,11 +639,13 @@ final class SelectionActionModeHelper {
 
         @WorkerThread
         public SelectionResult classifyText() {
-            return performClassification(null);
+            mHot = true;
+            return performClassification(null /* selection */);
         }
 
         @WorkerThread
         public SelectionResult suggestSelection() {
+            mHot = true;
             trimText();
             final TextSelection selection = mTextClassifier.suggestSelection(
                     mTrimmedText, mRelativeStart, mRelativeEnd, mLocales);
@@ -655,6 +654,22 @@ final class SelectionActionModeHelper {
             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) {
             if (!Objects.equals(mText, mLastClassificationText)
                     || mSelectionStart != mLastClassificationSelectionStart