From 36c7a62dffb7f5b6728fa0850c1f63aee0f14d80 Mon Sep 17 00:00:00 2001
From: Keisuke Kuroyanagi <ksk@google.com>
Date: Tue, 4 Feb 2014 21:29:09 +0900
Subject: [PATCH] Add dictionary dump buttons in debug settings.

Bug: 11736680
Bug: 12810574
Change-Id: I1f797b5ac6acf94b40d9698d4535e8f5da2bfb17
---
 java/res/values/strings.xml                   |  8 +++
 java/res/xml/prefs_for_debug.xml              | 17 ++++++
 .../DictionaryDumpBroadcastReceiver.java      | 50 ++++++++++++++++++
 .../DictionaryFacilitatorForSuggest.java      | 21 ++++++++
 .../android/inputmethod/latin/LatinIME.java   | 14 +++++
 .../latin/settings/DebugSettings.java         | 52 ++++++++++++++++++-
 6 files changed, 161 insertions(+), 1 deletion(-)
 create mode 100644 java/src/com/android/inputmethod/latin/DictionaryDumpBroadcastReceiver.java

diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index ef24448269..70f4c18297 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -498,6 +498,14 @@ mobile devices. [CHAR LIMIT=25] -->
     <string name="read_external_dictionary_confirm_install_message">Really install this file for <xliff:g id="locale_name">%s</xliff:g>?</string>
     <!-- Title for an error dialog that contains the details of the error in the body [CHAR LIMIT=80] -->
     <string name="error">There was an error</string>
+    <!-- Title of the settings for dumpping contacts dictionary file [CHAR LIMIT=35] -->
+    <string name="prefs_dump_contacts_dict">Dump contacts dictionary</string>
+    <!-- Title of the settings for dumpping personal dictionary file [CHAR LIMIT=35] -->
+    <string name="prefs_dump_user_dict">Dump personal dictionary</string>
+    <!-- Title of the settings for dumpping user history dictionary file [CHAR LIMIT=35] -->
+    <string name="prefs_dump_user_history_dict">Dump user history dictionary</string>
+    <!-- Title of the settings for dumpping personalization dictionary file [CHAR LIMIT=35] -->
+    <string name="prefs_dump_personalization_dict">Dump personalization dictionary</string>
 
     <!-- Title of the button to revert to the default value of the device in the settings dialog [CHAR LIMIT=15] -->
     <string name="button_default">Default</string>
diff --git a/java/res/xml/prefs_for_debug.xml b/java/res/xml/prefs_for_debug.xml
index 8d9508e38e..899e2b88e8 100644
--- a/java/res/xml/prefs_for_debug.xml
+++ b/java/res/xml/prefs_for_debug.xml
@@ -61,4 +61,21 @@
     <PreferenceScreen
         android:key="read_external_dictionary"
         android:title="@string/prefs_read_external_dictionary" />
+
+    <PreferenceScreen
+        android:key="dump_contacts_dict"
+        android:title="@string/prefs_dump_contacts_dict" />
+
+    <PreferenceScreen
+        android:key="dump_user_dict"
+        android:title="@string/prefs_dump_user_dict" />
+
+    <PreferenceScreen
+        android:key="dump_user_history_dict"
+        android:title="@string/prefs_dump_user_history_dict" />
+
+    <PreferenceScreen
+        android:key="dump_personalization_dict"
+        android:title="@string/prefs_dump_personalization_dict" />
+
 </PreferenceScreen>
diff --git a/java/src/com/android/inputmethod/latin/DictionaryDumpBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/DictionaryDumpBroadcastReceiver.java
new file mode 100644
index 0000000000..ee2fdc6c7e
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/DictionaryDumpBroadcastReceiver.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 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.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class DictionaryDumpBroadcastReceiver extends BroadcastReceiver {
+  private static final String TAG = DictionaryDumpBroadcastReceiver.class.getSimpleName();
+
+    private static final String DOMAIN = "com.android.inputmethod.latin";
+    public static final String DICTIONARY_DUMP_INTENT_ACTION = DOMAIN + ".DICT_DUMP";
+    public static final String DICTIONARY_NAME_KEY = "dictName";
+
+    final LatinIME mLatinIme;
+
+    public DictionaryDumpBroadcastReceiver(final LatinIME latinIme) {
+        mLatinIme = latinIme;
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final String action = intent.getAction();
+        if (action.equals(DICTIONARY_DUMP_INTENT_ACTION)) {
+            final String dictName = intent.getStringExtra(DICTIONARY_NAME_KEY);
+            if (dictName == null) {
+                Log.e(TAG, "Received dictionary dump intent action " +
+                      "but the dictionary name is not set.");
+                return;
+            }
+            mLatinIme.dumpDictionaryForDebug(dictName);
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index 8b02984e00..e68c6b771e 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -534,4 +534,25 @@ public class DictionaryFacilitatorForSuggest {
         mPersonalizationDictionary.addMultipleDictionaryEntriesToDictionary(languageModelParams,
                 callback);
     }
+
+    public void dumpDictionaryForDebug(final String dictName) {
+        final ExpandableBinaryDictionary dictToDump;
+        if (dictName.equals(Dictionary.TYPE_CONTACTS)) {
+            dictToDump = mContactsDictionary;
+        } else if (dictName.equals(Dictionary.TYPE_USER)) {
+            dictToDump = mUserDictionary;
+        } else if (dictName.equals(Dictionary.TYPE_USER_HISTORY)) {
+            dictToDump = mUserHistoryDictionary;
+        } else if (dictName.equals(Dictionary.TYPE_PERSONALIZATION)) {
+            dictToDump = mPersonalizationDictionary;
+        } else {
+            dictToDump = null;
+        }
+        if (dictToDump == null) {
+            Log.e(TAG, "Cannot dump " + dictName + ". "
+                    + "The dictionary is not being used for suggestion or cannot be dumped.");
+            return;
+        }
+        dictToDump.dumpAllWordsForDebug();
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 6517ef29da..2e163c4be3 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -133,6 +133,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
     private BroadcastReceiver mDictionaryPackInstallReceiver =
             new DictionaryPackInstallBroadcastReceiver(this);
 
+    private BroadcastReceiver mDictionaryDumpBroadcastReceiver =
+            new DictionaryDumpBroadcastReceiver(this);
+
     private AlertDialog mOptionsDialog;
 
     private final boolean mIsHardwareAcceleratedDrawingEnabled;
@@ -487,6 +490,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         newDictFilter.addAction(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION);
         registerReceiver(mDictionaryPackInstallReceiver, newDictFilter);
 
+        final IntentFilter dictDumpFilter = new IntentFilter();
+        dictDumpFilter.addAction(DictionaryDumpBroadcastReceiver.DICTIONARY_DUMP_INTENT_ACTION);
+        registerReceiver(mDictionaryDumpBroadcastReceiver, dictDumpFilter);
+
         DictionaryDecayBroadcastReciever.setUpIntervalAlarmForDictionaryDecaying(this);
     }
 
@@ -1758,6 +1765,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         resetSuggest(new Suggest(locale, dictionaryFacilitator));
     }
 
+    public void dumpDictionaryForDebug(final String dictName) {
+        if (mInputLogic.mSuggest == null) {
+            initSuggest();
+        }
+        mInputLogic.mSuggest.mDictionaryFacilitator.dumpDictionaryForDebug(dictName);
+    }
+
     public void debugDumpStateAndCrashWithException(final String context) {
         final SettingsValues settingsValues = mSettings.getCurrent();
         final StringBuilder s = new StringBuilder(settingsValues.toString());
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
index 29bbed8bd5..fa5ae92e7c 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
@@ -16,15 +16,18 @@
 
 package com.android.inputmethod.latin.settings;
 
+import android.content.Intent;
 import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.os.Process;
 import android.preference.CheckBoxPreference;
 import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceScreen;
 
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
+import com.android.inputmethod.latin.Dictionary;
+import com.android.inputmethod.latin.DictionaryDumpBroadcastReceiver;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.debug.ExternalDictionaryGetterForDebug;
@@ -40,6 +43,11 @@ public final class DebugSettings extends PreferenceFragment
     public static final String PREF_USE_ONLY_PERSONALIZATION_DICTIONARY_FOR_DEBUG =
             "use_only_personalization_dictionary_for_debug";
     private static final String PREF_READ_EXTERNAL_DICTIONARY = "read_external_dictionary";
+    private static final String PREF_DUMP_CONTACTS_DICT = "dump_contacts_dict";
+    private static final String PREF_DUMP_USER_DICT = "dump_user_dict";
+    private static final String PREF_DUMP_USER_HISTORY_DICT = "dump_user_history_dict";
+    private static final String PREF_DUMP_PERSONALIZATION_DICT = "dump_personalization_dict";
+
     private static final boolean SHOW_STATISTICS_LOGGING = false;
 
     private boolean mServiceNeedsRestart = false;
@@ -83,11 +91,53 @@ public final class DebugSettings extends PreferenceFragment
                     });
         }
 
+        final OnPreferenceClickListener dictDumpPrefClickListener =
+                new DictDumpPrefClickListener(this);
+        findPreference(PREF_DUMP_CONTACTS_DICT).setOnPreferenceClickListener(
+                dictDumpPrefClickListener);
+        findPreference(PREF_DUMP_USER_DICT).setOnPreferenceClickListener(
+                dictDumpPrefClickListener);
+        findPreference(PREF_DUMP_USER_HISTORY_DICT).setOnPreferenceClickListener(
+                dictDumpPrefClickListener);
+        findPreference(PREF_DUMP_PERSONALIZATION_DICT).setOnPreferenceClickListener(
+                dictDumpPrefClickListener);
+
         mServiceNeedsRestart = false;
         mDebugMode = (CheckBoxPreference) findPreference(PREF_DEBUG_MODE);
         updateDebugMode();
     }
 
+    private static class DictDumpPrefClickListener implements OnPreferenceClickListener {
+        final PreferenceFragment mPreferenceFragment;
+
+        public DictDumpPrefClickListener(final PreferenceFragment preferenceFragment) {
+            mPreferenceFragment = preferenceFragment;
+        }
+
+        @Override
+        public boolean onPreferenceClick(final Preference arg0) {
+            final String dictName;
+            if (arg0.getKey().equals(PREF_DUMP_CONTACTS_DICT)) {
+                dictName = Dictionary.TYPE_CONTACTS;
+            } else if (arg0.getKey().equals(PREF_DUMP_USER_DICT)) {
+                dictName = Dictionary.TYPE_USER;
+            } else if (arg0.getKey().equals(PREF_DUMP_USER_HISTORY_DICT)) {
+                dictName = Dictionary.TYPE_USER_HISTORY;
+            } else if (arg0.getKey().equals(PREF_DUMP_PERSONALIZATION_DICT)) {
+                dictName = Dictionary.TYPE_PERSONALIZATION;
+            } else {
+                dictName = null;
+            }
+            if (dictName != null) {
+                final Intent intent =
+                        new Intent(DictionaryDumpBroadcastReceiver.DICTIONARY_DUMP_INTENT_ACTION);
+                intent.putExtra(DictionaryDumpBroadcastReceiver.DICTIONARY_NAME_KEY, dictName);
+                mPreferenceFragment.getActivity().sendBroadcast(intent);
+            }
+            return true;
+        }
+    }
+
     @Override
     public void onStop() {
         super.onStop();
-- 
GitLab