From fdd2db576dc69aa69ae99ddb2178a955e71b61f0 Mon Sep 17 00:00:00 2001
From: Keisuke Kuroyanagi <ksk@google.com>
Date: Thu, 3 Apr 2014 18:08:23 +0900
Subject: [PATCH] Always close binary dicts for personalized dicts.

Bug: 10923130
Bug: 13664080
Change-Id: Ib247c775194a03462387994cd832b1650bfd1915
---
 .../inputmethod/latin/BinaryDictionary.java   | 14 +++++++++--
 .../latin/ContactsBinaryDictionary.java       |  4 ---
 .../latin/ExpandableBinaryDictionary.java     | 25 ++++++++++++++-----
 ...ecayingExpandableBinaryDictionaryBase.java |  2 +-
 4 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 43a44221d2..30c2dfedbb 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -89,6 +89,8 @@ public final class BinaryDictionary extends Dictionary {
     private final long mDictSize;
     private final String mDictFilePath;
     private final boolean mIsUpdatable;
+    private boolean mHasUpdated;
+
     private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
     private final int[] mOutputSuggestionCount = new int[1];
     private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS];
@@ -138,6 +140,7 @@ public final class BinaryDictionary extends Dictionary {
         mDictSize = length;
         mDictFilePath = filename;
         mIsUpdatable = isUpdatable;
+        mHasUpdated = false;
         mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
         loadDictionary(filename, offset, length, isUpdatable);
     }
@@ -185,6 +188,7 @@ public final class BinaryDictionary extends Dictionary {
     // TODO: Move native dict into session
     private final void loadDictionary(final String path, final long startOffset,
             final long length, final boolean isUpdatable) {
+        mHasUpdated = false;
         mNativeDict = openNative(path, startOffset, length, isUpdatable);
     }
 
@@ -401,6 +405,7 @@ public final class BinaryDictionary extends Dictionary {
                 StringUtils.toCodePointArray(shortcutTarget) : null;
         addUnigramWordNative(mNativeDict, codePoints, probability, shortcutTargetCodePoints,
                 shortcutProbability, isNotAWord, isBlacklisted, timestamp);
+        mHasUpdated = true;
     }
 
     // Add a bigram entry to binary dictionary with timestamp in native code.
@@ -412,6 +417,7 @@ public final class BinaryDictionary extends Dictionary {
         final int[] codePoints0 = StringUtils.toCodePointArray(word0);
         final int[] codePoints1 = StringUtils.toCodePointArray(word1);
         addBigramWordsNative(mNativeDict, codePoints0, codePoints1, probability, timestamp);
+        mHasUpdated = true;
     }
 
     // Remove a bigram entry form binary dictionary in native code.
@@ -422,6 +428,7 @@ public final class BinaryDictionary extends Dictionary {
         final int[] codePoints0 = StringUtils.toCodePointArray(word0);
         final int[] codePoints1 = StringUtils.toCodePointArray(word1);
         removeBigramWordsNative(mNativeDict, codePoints0, codePoints1);
+        mHasUpdated = true;
     }
 
     public void addMultipleDictionaryEntries(final LanguageModelParam[] languageModelParams) {
@@ -433,6 +440,7 @@ public final class BinaryDictionary extends Dictionary {
             }
             processedParamCount = addMultipleDictionaryEntriesNative(mNativeDict,
                     languageModelParams, processedParamCount);
+            mHasUpdated = true;
             if (processedParamCount <= 0) {
                 return;
             }
@@ -451,8 +459,10 @@ public final class BinaryDictionary extends Dictionary {
 
     public void flush() {
         if (!isValidDictionary()) return;
-        flushNative(mNativeDict, mDictFilePath);
-        reopen();
+        if (mHasUpdated) {
+            flushNative(mNativeDict, mDictFilePath);
+            reopen();
+        }
     }
 
     public void flushWithGC() {
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 4e17f83895..d5873d70fc 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -100,10 +100,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
                 });
     }
 
-    public void reopen(final Context context) {
-        registerObserver(context);
-    }
-
     @Override
     public synchronized void close() {
         if (mObserver != null) {
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index aea4811a97..64e9d2b51f 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -262,6 +262,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
         ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
             @Override
             public void run() {
+                if (mBinaryDictionary == null) {
+                    return;
+                }
                 runGCAfterAllPrioritizedTasksIfRequiredLocked(mindsBlockByGC);
             }
         });
@@ -274,9 +277,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     }
 
     private void runGCAfterAllPrioritizedTasksIfRequiredLocked(final boolean mindsBlockByGC) {
-        if (mBinaryDictionary == null) {
-            return;
-        }
         // needsToRunGC() have to be called with lock.
         if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) {
             if (setProcessingLargeTaskIfNot()) {
@@ -301,9 +301,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     protected void addWordDynamically(final String word, final int frequency,
             final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord,
             final boolean isBlacklisted, final int timestamp) {
+        reloadDictionaryIfRequired();
         ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
             @Override
             public void run() {
+                if (mBinaryDictionary == null) {
+                    return;
+                }
                 runGCAfterAllPrioritizedTasksIfRequiredLocked(true /* mindsBlockByGC */);
                 addWordDynamicallyLocked(word, frequency, shortcutTarget, shortcutFreq,
                         isNotAWord, isBlacklisted, timestamp);
@@ -323,9 +327,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
      */
     protected void addBigramDynamically(final String word0, final String word1,
             final int frequency, final int timestamp) {
+        reloadDictionaryIfRequired();
         ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
             @Override
             public void run() {
+                if (mBinaryDictionary == null) {
+                    return;
+                }
                 runGCAfterAllPrioritizedTasksIfRequiredLocked(true /* mindsBlockByGC */);
                 addBigramDynamicallyLocked(word0, word1, frequency, timestamp);
             }
@@ -341,9 +349,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
      * Dynamically remove a word bigram in the dictionary.
      */
     protected void removeBigramDynamically(final String word0, final String word1) {
+        reloadDictionaryIfRequired();
         ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
             @Override
             public void run() {
+                if (mBinaryDictionary == null) {
+                    return;
+                }
                 runGCAfterAllPrioritizedTasksIfRequiredLocked(true /* mindsBlockByGC */);
                 mBinaryDictionary.removeBigramWords(word0, word1);
             }
@@ -360,14 +372,15 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     protected void addMultipleDictionaryEntriesDynamically(
             final ArrayList<LanguageModelParam> languageModelParams,
             final AddMultipleDictionaryEntriesCallback callback) {
+        reloadDictionaryIfRequired();
         ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
             @Override
             public void run() {
+                if (mBinaryDictionary == null) {
+                    return;
+                }
                 final boolean locked = setProcessingLargeTaskIfNot();
                 try {
-                    if (mBinaryDictionary == null) {
-                        return;
-                    }
                     mBinaryDictionary.addMultipleDictionaryEntries(
                             languageModelParams.toArray(
                                     new LanguageModelParam[languageModelParams.size()]));
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 6f84e1f108..712e314a82 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -66,7 +66,7 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
         }
         // Flush pending writes.
         flush();
-        // TODO: Quit depending on finalize() and really close the dictionary file.
+        super.close();
     }
 
     public void flush() {
-- 
GitLab