Merge "Exception refactoring"
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 9b89b9a..3af7527 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -158,6 +158,41 @@
                 context.getApplicationInfo().sourceDir, afd.getStartOffset(), afd.getLength());
     }
 
+    static private class DictPackSettings {
+        final SharedPreferences mDictPreferences;
+        public DictPackSettings(final Context context) {
+            Context dictPackContext = null;
+            try {
+                final String dictPackName =
+                        context.getString(R.string.dictionary_pack_package_name);
+                dictPackContext = context.createPackageContext(dictPackName, 0);
+            } catch (NameNotFoundException e) {
+                // The dictionary pack is not installed...
+                // TODO: fallback on the built-in dict, see the TODO above
+                Log.e(TAG, "Could not find a dictionary pack");
+            }
+            mDictPreferences = null == dictPackContext ? null
+                    : dictPackContext.getSharedPreferences(COMMON_PREFERENCES_NAME,
+                            Context.MODE_WORLD_READABLE | Context.MODE_MULTI_PROCESS);
+        }
+        public boolean isWordListActive(final String dictId) {
+            if (null == mDictPreferences) {
+                // If we don't have preferences it basically means we can't find the dictionary
+                // pack - either it's not installed, or it's disabled, or there is some strange
+                // bug. Either way, a word list with no settings should be on by default: default
+                // dictionaries in LatinIME are on if there is no settings at all, and if for some
+                // reason some dictionaries have been installed BUT the dictionary pack can't be
+                // found anymore it's safer to actually supply installed dictionaries.
+                return true;
+            } else {
+                // The default is true here for the same reasons as above. We got the dictionary
+                // pack but if we don't have any settings for it it means the user has never been
+                // to the settings yet. So by default, the main dictionaries should be on.
+                return mDictPreferences.getBoolean(dictId, true);
+            }
+        }
+    }
+
     /**
      * Returns the list of cached files for a specific locale.
      *
@@ -173,24 +208,12 @@
         // not present or disabled, then return an empty list.
         if (null == cacheFiles) return null;
 
-        final SharedPreferences dictPackSettings;
-        try {
-            final String dictPackName = context.getString(R.string.dictionary_pack_package_name);
-            final Context dictPackContext = context.createPackageContext(dictPackName, 0);
-            dictPackSettings = dictPackContext.getSharedPreferences(COMMON_PREFERENCES_NAME,
-                    Context.MODE_WORLD_READABLE | Context.MODE_MULTI_PROCESS);
-        } catch (NameNotFoundException e) {
-            // The dictionary pack is not installed...
-            // TODO: fallback on the built-in dict, see the TODO above
-            Log.e(TAG, "Could not find a dictionary pack");
-            return null;
-        }
+        final DictPackSettings dictPackSettings = new DictPackSettings(context);
 
         final ArrayList<AssetFileAddress> fileList = new ArrayList<AssetFileAddress>();
         for (File f : cacheFiles) {
             final String wordListId = getWordListIdFromFileName(f.getName());
-            final boolean isActive = dictPackSettings.getBoolean(wordListId, true);
-            if (!isActive) continue;
+            if (!dictPackSettings.isWordListActive(wordListId)) continue;
             if (f.canRead()) {
                 fileList.add(AssetFileAddress.makeFromFileName(f.getPath()));
             } else {
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index a2d66f3..937457e 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -426,7 +426,7 @@
         if (typedWord != null) {
             mSuggestions.add(0, typedWordString);
         }
-        removeDupes();
+        removeDupes(mSuggestions);
 
         if (DBG) {
             double normalizedScore = mAutoCorrection.getNormalizedScore();
@@ -453,8 +453,7 @@
         return new SuggestedWords.Builder().addWords(mSuggestions, null);
     }
 
-    private void removeDupes() {
-        final ArrayList<CharSequence> suggestions = mSuggestions;
+    private static void removeDupes(final ArrayList<CharSequence> suggestions) {
         if (suggestions.size() < 2) return;
         int i = 1;
         // Don't cache suggestions.size(), since we may be removing items
@@ -464,7 +463,7 @@
             for (int j = 0; j < i; j++) {
                 CharSequence previous = suggestions.get(j);
                 if (TextUtils.equals(cur, previous)) {
-                    removeFromSuggestions(i);
+                    removeFromSuggestions(suggestions, i);
                     i--;
                     break;
                 }
@@ -473,10 +472,12 @@
         }
     }
 
-    private void removeFromSuggestions(int index) {
-        CharSequence garbage = mSuggestions.remove(index);
+    private static void removeFromSuggestions(final ArrayList<CharSequence> suggestions,
+            final int index) {
+        final CharSequence garbage = suggestions.remove(index);
         if (garbage != null && garbage instanceof StringBuilder) {
-            mStringPool.add(garbage);
+            // TODO: rebase this over the static string builder pool
+            //            mStringPool.add(garbage);
         }
     }