From 1488a3a19d4681a41fb45570c15e14d99db1cb66 Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Wed, 24 May 2017 12:25:46 -0700 Subject: SelectionActionModeHelper should use target view's thread Use the looper from the TextView's thread for the helper Bug 62043115 Test: Manual, type on edit field and select text Change-Id: I501430a500016a81963a9f9fa636474b708b9b36 --- core/java/android/os/AsyncTask.java | 40 ++++++++++++++++++---- .../android/widget/SelectionActionModeHelper.java | 4 ++- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index fea64ec5ee1e..141d33bc4145 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -17,14 +17,14 @@ package android.os; import android.annotation.MainThread; +import android.annotation.Nullable; import android.annotation.WorkerThread; - import java.util.ArrayDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; -import java.util.concurrent.Executor; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; import java.util.concurrent.FutureTask; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; @@ -232,6 +232,8 @@ public abstract class AsyncTask { private final AtomicBoolean mCancelled = new AtomicBoolean(); private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); + private final Handler mHandler; + private static class SerialExecutor implements Executor { final ArrayDeque mTasks = new ArrayDeque(); Runnable mActive; @@ -277,15 +279,19 @@ public abstract class AsyncTask { FINISHED, } - private static Handler getHandler() { + private static Handler getMainHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { - sHandler = new InternalHandler(); + sHandler = new InternalHandler(Looper.getMainLooper()); } return sHandler; } } + private Handler getHandler() { + return mHandler; + } + /** @hide */ public static void setDefaultExecutor(Executor exec) { sDefaultExecutor = exec; @@ -295,6 +301,28 @@ public abstract class AsyncTask { * Creates a new asynchronous task. This constructor must be invoked on the UI thread. */ public AsyncTask() { + this((Looper) null); + } + + /** + * Creates a new asynchronous task. This constructor must be invoked on the UI thread. + * + * @hide + */ + public AsyncTask(@Nullable Handler handler) { + this(handler != null ? handler.getLooper() : null); + } + + /** + * Creates a new asynchronous task. This constructor must be invoked on the UI thread. + * + * @hide + */ + public AsyncTask(@Nullable Looper callbackLooper) { + mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() + ? getMainHandler() + : new Handler(callbackLooper); + mWorker = new WorkerRunnable() { public Result call() throws Exception { mTaskInvoked.set(true); @@ -670,8 +698,8 @@ public abstract class AsyncTask { } private static class InternalHandler extends Handler { - public InternalHandler() { - super(Looper.getMainLooper()); + public InternalHandler(Looper looper) { + super(looper); } @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index 6657c3a78a20..142412ac8ccb 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -74,8 +74,9 @@ final class SelectionActionModeHelper { startActionMode(null); } else { resetTextClassificationHelper(true /* resetSelectionTag */); + final TextView tv = mEditor.getTextView(); mTextClassificationAsyncTask = new TextClassificationAsyncTask( - mEditor.getTextView(), + tv, TIMEOUT_DURATION, adjustSelection ? mTextClassificationHelper::suggestSelection @@ -340,6 +341,7 @@ final class SelectionActionModeHelper { @NonNull TextView textView, int timeOut, @NonNull Supplier selectionResultSupplier, @NonNull Consumer selectionResultCallback) { + super(textView != null ? textView.getHandler() : null); mTextView = Preconditions.checkNotNull(textView); mTimeOutDuration = timeOut; mSelectionResultSupplier = Preconditions.checkNotNull(selectionResultSupplier); -- cgit v1.2.3-59-g8ed1b