Use the contacts dictionary in the spell checker.

Bug: 5447495
Change-Id: I7292eb291a1630265884cc8e505a2e83a74f0c72
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsDictionary.java
new file mode 100644
index 0000000..444c7f5
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsDictionary.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+
+import com.android.inputmethod.keyboard.ProximityInfo;
+
+public class SynchronouslyLoadedContactsDictionary extends ContactsDictionary {
+    private boolean mClosed;
+
+    public SynchronouslyLoadedContactsDictionary(final Context context) {
+        super(context, Suggest.DIC_CONTACTS);
+        mClosed = false;
+    }
+
+    @Override
+    public synchronized void getWords(final WordComposer codes, final WordCallback callback,
+            final ProximityInfo proximityInfo) {
+        blockingReloadDictionaryIfRequired();
+        getWordsInner(codes, callback, proximityInfo);
+    }
+
+    @Override
+    public synchronized boolean isValidWord(CharSequence word) {
+        blockingReloadDictionaryIfRequired();
+        return getWordFrequency(word) > -1;
+    }
+
+    // Protect against multiple closing
+    @Override
+    public synchronized void close() {
+        // Actually with the current implementation of ContactsDictionary it's safe to close
+        // several times, so the following protection is really only for foolproofing
+        if (mClosed) return;
+        mClosed = true;
+        super.close();
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index f9e6a5e..8f478f3 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -35,6 +35,7 @@
 import com.android.inputmethod.latin.Flag;
 import com.android.inputmethod.latin.LocaleUtils;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.SynchronouslyLoadedContactsDictionary;
 import com.android.inputmethod.latin.SynchronouslyLoadedUserDictionary;
 import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.WhitelistDictionary;
@@ -82,6 +83,7 @@
             Collections.synchronizedMap(new TreeMap<String, Dictionary>());
     private Map<String, Dictionary> mWhitelistDictionaries =
             Collections.synchronizedMap(new TreeMap<String, Dictionary>());
+    private SynchronouslyLoadedContactsDictionary mContactsDictionary;
 
     // The threshold for a candidate to be offered as a suggestion.
     private double mSuggestionThreshold;
@@ -267,6 +269,14 @@
         for (Dictionary dict : oldWhitelistDictionaries.values()) {
             dict.close();
         }
+        if (null != mContactsDictionary) {
+            // The synchronously loaded contacts dictionary should have been in one
+            // or several pools, but it is shielded against multiple closing and it's
+            // safe to call it several times.
+            final SynchronouslyLoadedContactsDictionary dictToClose = mContactsDictionary;
+            mContactsDictionary = null;
+            dictToClose.close();
+        }
         return false;
     }
 
@@ -300,6 +310,11 @@
             mWhitelistDictionaries.put(localeStr, whitelistDictionary);
         }
         dictionaryCollection.addDictionary(whitelistDictionary);
+        if (null == mContactsDictionary) {
+            mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
+        }
+        // TODO: add a setting to use or not contacts when checking spelling
+        dictionaryCollection.addDictionary(mContactsDictionary);
         return new DictAndProximity(dictionaryCollection, proximityInfo);
     }