From bd1bc4067ff87ce1a21d12a48b1695fe58c8dd4d Mon Sep 17 00:00:00 2001 From: Dan Zivkovic Date: Mon, 9 Mar 2015 14:48:51 -0700 Subject: [PATCH] ExecutorUtils lets use schedule a runnable chain. Bug 19625976. Change-Id: Iebbef7fed57a381498301dcf26fefa27d06802f7 --- .../latin/ContactsContentObserver.java | 4 +- .../latin/utils/ExecutorUtils.java | 74 +++++++++++-------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/ContactsContentObserver.java b/java/src/com/android/inputmethod/latin/ContactsContentObserver.java index 04c1cf333..4a8d1133b 100644 --- a/java/src/com/android/inputmethod/latin/ContactsContentObserver.java +++ b/java/src/com/android/inputmethod/latin/ContactsContentObserver.java @@ -56,8 +56,8 @@ public class ContactsContentObserver implements Runnable { mContentObserver = new ContentObserver(null /* handler */) { @Override public void onChange(boolean self) { - ExecutorUtils.getBackgroundExecutor() - .execute(ContactsContentObserver.this); + // TODO(zivkovic): Schedule a separate task to reset the decoder. + ExecutorUtils.getBackgroundExecutor().execute(ContactsContentObserver.this); } }; final ContentResolver contentResolver = mContext.getContentResolver(); diff --git a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java index b21538caa..b04a820aa 100644 --- a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java @@ -23,7 +23,9 @@ import com.android.inputmethod.annotations.UsedForTesting; import java.lang.Thread.UncaughtExceptionHandler; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; /** * Utilities to manage executors. @@ -35,33 +37,6 @@ public class ExecutorUtils { private static final ScheduledExecutorService sExecutorService = Executors.newSingleThreadScheduledExecutor(new ExecutorFactory()); - @UsedForTesting - private static ScheduledExecutorService sExecutorServiceForTests; - - @UsedForTesting - public static void setExecutorServiceForTests( - final ScheduledExecutorService executorServiceForTests) { - sExecutorServiceForTests = executorServiceForTests; - } - - /** - * @return scheduled executor service used to run background tasks - */ - public static ScheduledExecutorService getBackgroundExecutor() { - if (sExecutorServiceForTests != null) { - return sExecutorServiceForTests; - } - return sExecutorService; - } - - /** - * Shutdowns all executors and removes all executors from the executor map for testing. - */ - @UsedForTesting - public static void shutdownAllExecutors() { - sExecutorService.execute(new ExecutorShutdown(sExecutorService)); - } - private static class ExecutorFactory implements ThreadFactory { @Override public Thread newThread(final Runnable runnable) { @@ -76,16 +51,51 @@ public class ExecutorUtils { } } - private static class ExecutorShutdown implements Runnable { - private final ScheduledExecutorService mExecutor; + @UsedForTesting + private static ScheduledExecutorService sExecutorServiceForTests; - public ExecutorShutdown(final ScheduledExecutorService executor) { - mExecutor = executor; + @UsedForTesting + public static void setExecutorServiceForTests( + final ScheduledExecutorService executorServiceForTests) { + sExecutorServiceForTests = executorServiceForTests; + } + + // + // Public methods used to schedule a runnable for execution. + // + + /** + * @return scheduled executor service used to run background tasks + */ + public static ScheduledExecutorService getBackgroundExecutor() { + if (sExecutorServiceForTests != null) { + return sExecutorServiceForTests; + } + return sExecutorService; + } + + public static Runnable chain(final Runnable... runnables) { + return new RunnableChain(runnables); + } + + private static class RunnableChain implements Runnable { + private final Runnable[] mRunnables; + + private RunnableChain(final Runnable... runnables) { + if (runnables == null || runnables.length == 0) { + throw new IllegalArgumentException("Attempting to construct an empty chain"); + } + mRunnables = runnables; } @Override public void run() { - mExecutor.shutdown(); + for (Runnable runnable : mRunnables) { + if (Thread.interrupted()) { + return; + } + runnable.run(); + } } } }