From 87ab5b0518d6e87c22568a5e5d5834c5c40baf83 Mon Sep 17 00:00:00 2001
From: Keisuke Kuroyanagi <ksk@google.com>
Date: Thu, 7 Aug 2014 18:39:06 +0900
Subject: [PATCH] Use DistracterFilterCheckingIsInDictionary for User History

Bug: 13142176
Bug: 15531638
Change-Id: I7e4e5afa05c5cee6eedef62c053d81edac5fa6af
---
 .../latin/DictionaryFacilitator.java          |  4 +-
 .../latin/ExpandableBinaryDictionary.java     | 58 ++++++++++++++-----
 2 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index d6e6656ab..36a02669d 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -468,7 +468,9 @@ public class DictionaryFacilitator {
         // We don't add words with 0-frequency (assuming they would be profanity etc.).
         final boolean isValid = maxFreq > 0;
         UserHistoryDictionary.addToDictionary(userHistoryDictionary, prevWordsInfo, secondWord,
-                isValid, timeStampInSeconds, mDistracterFilter);
+                isValid, timeStampInSeconds,
+                new DistracterFilterCheckingIsInDictionary(
+                        mDistracterFilter, userHistoryDictionary));
     }
 
     private void removeWord(final String dictName, final String word) {
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 5808b9e4e..c11a220a4 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -38,6 +38,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
+import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -163,9 +164,31 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     }
 
     private void asyncExecuteTaskWithLock(final Lock lock, final Runnable task) {
+        asyncPreCheckAndExecuteTaskWithLock(lock, null /* preCheckTask */, task);
+    }
+
+    private void asyncPreCheckAndExecuteTaskWithWriteLock(
+            final Callable<Boolean> preCheckTask, final Runnable task) {
+        asyncPreCheckAndExecuteTaskWithLock(mLock.writeLock(), preCheckTask, task);
+
+    }
+
+    // Execute task with lock when the result of preCheckTask is true or preCheckTask is null.
+    private void asyncPreCheckAndExecuteTaskWithLock(final Lock lock,
+            final Callable<Boolean> preCheckTask, final Runnable task) {
         ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
             @Override
             public void run() {
+                if (preCheckTask != null) {
+                    try {
+                        if (!preCheckTask.call().booleanValue()) {
+                            return;
+                        }
+                    } catch (final Exception e) {
+                        Log.e(TAG, "The pre check task throws an exception.", e);
+                        return;
+                    }
+                }
                 lock.lock();
                 try {
                     task.run();
@@ -278,22 +301,25 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
             final boolean isBlacklisted, final int timestamp,
             final DistracterFilter distracterFilter) {
         reloadDictionaryIfRequired();
-        asyncExecuteTaskWithWriteLock(new Runnable() {
-            @Override
-            public void run() {
-                if (mBinaryDictionary == null) {
-                    return;
-                }
-                if (distracterFilter.isDistracterToWordsInDictionaries(
-                        PrevWordsInfo.EMPTY_PREV_WORDS_INFO, word, mLocale)) {
-                    // The word is a distracter.
-                    return;
-                }
-                runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                addUnigramLocked(word, frequency, shortcutTarget, shortcutFreq,
-                        isNotAWord, isBlacklisted, timestamp);
-            }
-        });
+        asyncPreCheckAndExecuteTaskWithWriteLock(
+                new Callable<Boolean>() {
+                    @Override
+                    public Boolean call() throws Exception {
+                        return !distracterFilter.isDistracterToWordsInDictionaries(
+                                PrevWordsInfo.EMPTY_PREV_WORDS_INFO, word, mLocale);
+                    }
+                },
+                new Runnable() {
+                    @Override
+                    public void run() {
+                        if (mBinaryDictionary == null) {
+                            return;
+                        }
+                        runGCIfRequiredLocked(true /* mindsBlockByGC */);
+                        addUnigramLocked(word, frequency, shortcutTarget, shortcutFreq,
+                                isNotAWord, isBlacklisted, timestamp);
+                    }
+                });
     }
 
     protected void addUnigramLocked(final String word, final int frequency,