Close dictionary pools when they are not used any more.

Bug: 5156851
Change-Id: Icaba54734eb790b40dc2012aac25df5b2af71dbb
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index c718410..649774d 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.latin.spellcheck;
 
+import android.content.Intent;
 import android.content.res.Resources;
 import android.service.textservice.SpellCheckerService;
 import android.service.textservice.SpellCheckerService.Session;
@@ -48,7 +49,7 @@
     private static final int POOL_SIZE = 2;
 
     private final static String[] emptyArray = new String[0];
-    private final Map<String, DictionaryPool> mDictionaryPools =
+    private Map<String, DictionaryPool> mDictionaryPools =
             Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
 
     @Override
@@ -104,6 +105,16 @@
         }
     }
 
+    @Override
+    public boolean onUnbind(final Intent intent) {
+        final Map<String, DictionaryPool> oldPools = mDictionaryPools;
+        mDictionaryPools = Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
+        for (DictionaryPool pool : oldPools.values()) {
+            pool.close();
+        }
+        return false;
+    }
+
     private DictionaryPool getDictionaryPool(final String locale) {
         DictionaryPool pool = mDictionaryPools.get(locale);
         if (null == pool) {
@@ -167,7 +178,9 @@
                 dictInfo.mDictionary.getWords(composer, suggestionsGatherer,
                         dictInfo.mProximityInfo);
                 isInDict = dictInfo.mDictionary.isValidWord(text);
-                mDictionaryPool.offer(dictInfo);
+                if (!mDictionaryPool.offer(dictInfo)) {
+                    Log.e(TAG, "Can't re-insert a dictionary into its pool");
+                }
             } catch (InterruptedException e) {
                 // I don't think this can happen.
                 return new SuggestionsInfo(0, new String[0]);
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
index dfbfcc7..ee294f6 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
@@ -28,7 +28,8 @@
     private final AndroidSpellCheckerService mService;
     private final int mMaxSize;
     private final Locale mLocale;
-    private int mSize = 0;
+    private int mSize;
+    private volatile boolean mClosed;
 
     public DictionaryPool(final int maxSize, final AndroidSpellCheckerService service,
             final Locale locale) {
@@ -36,6 +37,8 @@
         mMaxSize = maxSize;
         mService = service;
         mLocale = locale;
+        mSize = 0;
+        mClosed = false;
     }
 
     @Override
@@ -52,4 +55,24 @@
             }
         }
     }
+
+    public void close() {
+        synchronized(this) {
+            mClosed = true;
+            for (DictAndProximity dict : this) {
+                dict.mDictionary.close();
+            }
+            clear();
+        }
+    }
+
+    @Override
+    public boolean offer(final DictAndProximity dict) {
+        if (mClosed) {
+            dict.mDictionary.close();
+            return false;
+        } else {
+            return super.offer(dict);
+        }
+    }
 }