From f9e2d271ca101a53a6aac772ca770242805793ef Mon Sep 17 00:00:00 2001
From: Dan Zivkovic <zivkovic@google.com>
Date: Mon, 9 Mar 2015 13:22:56 -0700
Subject: [PATCH] Use a single background executor.

Bug 19625976.

Change-Id: Ia03f440a31b059b5af42d162e1145330bf7b5ddf
---
 .../latin/ContactsContentObserver.java        |  2 +-
 .../latin/DictionaryFacilitatorImpl.java      |  2 +-
 .../latin/ExpandableBinaryDictionary.java     |  2 +-
 .../spellcheck/UserDictionaryLookup.java      |  4 +-
 .../latin/utils/ExecutorUtils.java            | 55 +++----------------
 .../latin/utils/ExecutorUtilsTests.java       |  2 +-
 6 files changed, 15 insertions(+), 52 deletions(-)

diff --git a/java/src/com/android/inputmethod/latin/ContactsContentObserver.java b/java/src/com/android/inputmethod/latin/ContactsContentObserver.java
index e45681bd7c..04c1cf3339 100644
--- a/java/src/com/android/inputmethod/latin/ContactsContentObserver.java
+++ b/java/src/com/android/inputmethod/latin/ContactsContentObserver.java
@@ -56,7 +56,7 @@ public class ContactsContentObserver implements Runnable {
         mContentObserver = new ContentObserver(null /* handler */) {
             @Override
             public void onChange(boolean self) {
-                ExecutorUtils.getExecutorForDynamicLanguageModelUpdate()
+                ExecutorUtils.getBackgroundExecutor()
                         .execute(ContactsContentObserver.this);
             }
         };
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
index 7ad2a9f7db..6080900a16 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
@@ -444,7 +444,7 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
             final Locale[] locales, final DictionaryInitializationListener listener) {
         final CountDownLatch latchForWaitingLoadingMainDictionary = new CountDownLatch(1);
         mLatchForWaitingLoadingMainDictionaries = latchForWaitingLoadingMainDictionary;
-        ExecutorUtils.getExecutorForStaticLanguageModelUpdate().execute(new Runnable() {
+        ExecutorUtils.getBackgroundExecutor().execute(new Runnable() {
             @Override
             public void run() {
                 doReloadUninitializedMainDictionaries(
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index b0fb91bec7..138a2ea5c2 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -168,7 +168,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     }
 
     private static void asyncExecuteTaskWithLock(final Lock lock, final Runnable task) {
-        ExecutorUtils.getExecutorForDynamicLanguageModelUpdate().execute(new Runnable() {
+        ExecutorUtils.getBackgroundExecutor().execute(new Runnable() {
             @Override
             public void run() {
                 lock.lock();
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookup.java b/java/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookup.java
index 856f16a531..6ab741ca1a 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookup.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookup.java
@@ -143,7 +143,7 @@ public class UserDictionaryLookup implements Closeable {
             }
 
             // Schedule a new reload after RELOAD_DELAY_MS.
-            mReloadFuture = ExecutorUtils.getExecutorForDynamicLanguageModelUpdate().schedule(
+            mReloadFuture = ExecutorUtils.getBackgroundExecutor().schedule(
                     mLoader, RELOAD_DELAY_MS, TimeUnit.MILLISECONDS);
         }
     }
@@ -186,7 +186,7 @@ public class UserDictionaryLookup implements Closeable {
         // Schedule the initial load to run immediately.  It's possible that the first call to
         // isValidWord occurs before the dictionary has actually loaded, so it should not
         // assume that the dictionary has been loaded.
-        ExecutorUtils.getExecutorForDynamicLanguageModelUpdate().execute(mLoader);
+        ExecutorUtils.getBackgroundExecutor().execute(mLoader);
 
         // Register the observer to be notified on changes to the UserDictionary and all individual
         // items.
diff --git a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java
index c533a6273f..b21538caa0 100644
--- a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java
@@ -21,7 +21,6 @@ import android.util.Log;
 import com.android.inputmethod.annotations.UsedForTesting;
 
 import java.lang.Thread.UncaughtExceptionHandler;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadFactory;
@@ -31,11 +30,10 @@ import java.util.concurrent.ThreadFactory;
  */
 public class ExecutorUtils {
 
-    private static final String STATIC_LANGUAGE_MODEL_UPDATE = "StaticLanguageModelUpdate";
-    private static final String DYNAMIC_LANGUAGE_MODEL_UPDATE = "DynamicLanguageModelUpdate";
+    private static final String TAG = "ExecutorUtils";
 
-    private static final ConcurrentHashMap<String, ScheduledExecutorService> sExecutorMap =
-            new ConcurrentHashMap<>();
+    private static final ScheduledExecutorService sExecutorService =
+            Executors.newSingleThreadScheduledExecutor(new ExecutorFactory());
 
     @UsedForTesting
     private static ScheduledExecutorService sExecutorServiceForTests;
@@ -47,37 +45,13 @@ public class ExecutorUtils {
     }
 
     /**
-     * @return scheduled executor service used to update static language models
+     * @return scheduled executor service used to run background tasks
      */
-    public static ScheduledExecutorService getExecutorForStaticLanguageModelUpdate() {
-        return getExecutor(STATIC_LANGUAGE_MODEL_UPDATE);
-    }
-
-    /**
-     * @return scheduled executor service used to update dynamic language models
-     */
-    public static ScheduledExecutorService getExecutorForDynamicLanguageModelUpdate() {
-        return getExecutor(DYNAMIC_LANGUAGE_MODEL_UPDATE);
-    }
-
-    /**
-     * Gets the executor for the given id.
-     */
-    private static ScheduledExecutorService getExecutor(final String id) {
+    public static ScheduledExecutorService getBackgroundExecutor() {
         if (sExecutorServiceForTests != null) {
             return sExecutorServiceForTests;
         }
-        ScheduledExecutorService executor = sExecutorMap.get(id);
-        if (executor == null) {
-            synchronized (sExecutorMap) {
-                executor = sExecutorMap.get(id);
-                if (executor == null) {
-                    executor = Executors.newSingleThreadScheduledExecutor(new ExecutorFactory(id));
-                    sExecutorMap.put(id, executor);
-                }
-            }
-        }
-        return executor;
+        return sExecutorService;
     }
 
     /**
@@ -85,28 +59,17 @@ public class ExecutorUtils {
      */
     @UsedForTesting
     public static void shutdownAllExecutors() {
-        synchronized (sExecutorMap) {
-            for (final ScheduledExecutorService executor : sExecutorMap.values()) {
-                executor.execute(new ExecutorShutdown(executor));
-            }
-            sExecutorMap.clear();
-        }
+        sExecutorService.execute(new ExecutorShutdown(sExecutorService));
     }
 
     private static class ExecutorFactory implements ThreadFactory {
-        private final String mThreadName;
-
-        public ExecutorFactory(final String threadName) {
-            mThreadName = threadName;
-        }
-
         @Override
         public Thread newThread(final Runnable runnable) {
-            Thread thread = new Thread(runnable, mThreadName);
+            Thread thread = new Thread(runnable, TAG);
             thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
                 @Override
                 public void uncaughtException(Thread thread, Throwable ex) {
-                    Log.w(mThreadName + "-" + runnable.getClass().getSimpleName(), ex);
+                    Log.w(TAG + "-" + runnable.getClass().getSimpleName(), ex);
                 }
             });
             return thread;
diff --git a/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java
index 3b1e43ed8e..d722151cf8 100644
--- a/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java
@@ -35,7 +35,7 @@ public class ExecutorUtilsTests extends AndroidTestCase {
     private static final int DELAY_FOR_WAITING_TASKS_MILLISECONDS = 500;
 
     public void testExecute() {
-        final ExecutorService executor = ExecutorUtils.getExecutorForDynamicLanguageModelUpdate();
+        final ExecutorService executor = ExecutorUtils.getBackgroundExecutor();
         final AtomicInteger v = new AtomicInteger(0);
         for (int i = 0; i < NUM_OF_TASKS; ++i) {
             executor.execute(new Runnable() {
-- 
GitLab