Merge "Remove researcher logger"
diff --git a/java/res/layout/research_feedback_activity.xml b/java/res/layout/research_feedback_activity.xml
deleted file mode 100644
index a6b8b8a..0000000
--- a/java/res/layout/research_feedback_activity.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<com.android.inputmethod.research.FeedbackLayout
-     xmlns:android="http://schemas.android.com/apk/res/android"
-     android:layout_width="match_parent"
-     android:layout_height="wrap_content"
-     android:orientation="vertical"
-     android:id="@+id/research_feedback_layout"
->
-
-    <fragment
-          android:id="@+id/research_feedback_fragment"
-          android:name="com.android.inputmethod.research.FeedbackFragment"
-          android:layout_width="match_parent"
-          android:layout_height="wrap_content"
-    />
-</com.android.inputmethod.research.FeedbackLayout>
diff --git a/java/res/layout/research_feedback_fragment_layout.xml b/java/res/layout/research_feedback_fragment_layout.xml
deleted file mode 100644
index fb5c278..0000000
--- a/java/res/layout/research_feedback_fragment_layout.xml
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<!-- Adapted from frameworks/base/core/res/res/layout/alert_dialog_holo.xml.  We
-   want a dialog, but it must be its own activity so we can launch the soft
-   keyboard on it.  A regular dialog will not work since it would be launched from
-   the IME. -->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android">
-    <LinearLayout
-         android:layout_width="match_parent"
-         android:layout_height="wrap_content"
-         android:layout_marginStart="8dip"
-         android:layout_marginEnd="8dip"
-         android:orientation="vertical">
-        <LinearLayout
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-             android:orientation="vertical">
-            <View android:layout_width="match_parent"
-                android:layout_height="2dip"
-                android:visibility="gone"
-                android:background="@android:color/holo_blue_light" />
-            <TextView
-                style="?android:attr/windowTitleStyle"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:minHeight="64dip"
-                android:layout_marginLeft="16dip"
-                android:layout_marginRight="16dip"
-                android:gravity="center_vertical|left"
-                android:text="@string/research_feedback_dialog_title" />
-            <View
-                android:layout_width="match_parent"
-                android:layout_height="2dip"
-                android:background="@android:color/holo_blue_light" />
-        </LinearLayout>
-
-        <EditText
-            android:id="@+id/research_feedback_contents"
-            android:layout_height="wrap_content"
-            android:layout_width="match_parent"
-            android:layout_gravity="fill_horizontal|center_vertical"
-            android:layout_marginLeft="8dip"
-            android:layout_marginRight="8dip"
-            android:layout_marginBottom="8dip"
-            android:layout_marginTop="8dip"
-            android:minLines="2"
-            android:scrollbars="vertical"
-            android:hint="@string/research_feedback_hint"
-            android:inputType="textMultiLine|textCapSentences">
-            <requestFocus />
-        </EditText>
-        <CheckBox
-            android:id="@+id/research_feedback_include_account_name"
-            android:layout_height="wrap_content"
-            android:layout_width="match_parent"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
-            android:layout_marginBottom="8dip"
-            android:checked="false"
-            android:text="@string/research_feedback_include_account_name_label" />
-        <CheckBox
-            android:id="@+id/research_feedback_include_recording_checkbox"
-            android:layout_height="wrap_content"
-            android:layout_width="match_parent"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
-            android:layout_marginBottom="8dip"
-            android:checked="false"
-            android:text="@string/research_feedback_include_recording_label" />
-        <LinearLayout
-            style="?android:attr/buttonBarStyle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:layoutDirection="locale"
-            android:measureWithLargestChild="true">
-            <Button
-                android:id="@+id/research_feedback_cancel_button"
-                android:layout_width="wrap_content"
-                android:layout_gravity="left"
-                android:layout_weight="1"
-                android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle"
-                android:textSize="14sp"
-                android:text="@string/research_feedback_cancel"
-                android:layout_height="wrap_content" />
-            <Button
-                android:id="@+id/research_feedback_send_button"
-                android:layout_width="wrap_content"
-                android:layout_gravity="right"
-                android:layout_weight="1"
-                android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle"
-                android:textSize="14sp"
-                android:text="@string/research_feedback_send"
-                android:layout_height="wrap_content" />
-        </LinearLayout>
-    </LinearLayout>
-</ScrollView>
diff --git a/java/res/layout/research_feedback_layout.xml b/java/res/layout/research_feedback_layout.xml
deleted file mode 100644
index bacd191..0000000
--- a/java/res/layout/research_feedback_layout.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<LinearLayout
-     xmlns:android="http://schemas.android.com/apk/res/android"
-     android:layout_width="fill_parent"
-     android:layout_height="fill_parent"
-     android:orientation="vertical"
->
-
-    <EditText
-        android:id="@+id/research_feedback_contents"
-        android:layout_height="wrap_content"
-        android:layout_width="match_parent"
-        android:layout_gravity="fill_horizontal|center_vertical"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip"
-        android:layout_marginBottom="8dip"
-        android:layout_marginTop="8dip"
-        android:lines="2"
-        android:hint="@string/research_feedback_hint"
-        android:inputType="textMultiLine"
-        android:imeOptions="flagNoFullscreen"
-        android:focusable="true"
-    >
-        <requestFocus />
-    </EditText>
-
-    <CheckBox
-        android:id="@+id/research_feedback_include_history"
-        android:layout_height="wrap_content"
-        android:layout_width="match_parent"
-        android:layout_marginBottom="8dip"
-        android:checked="true"
-        android:text="@string/research_feedback_include_history_label"
-    />
-</LinearLayout>
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index ce7cb18..6230cbe 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropsies"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Navorsing-loglêerbevele"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Soek kontakname op"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Speltoetser gebruik inskrywings uit jou kontaklys"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreer met sleuteldruk"</string>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index 32eed41..138989e 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"ግቤት አማራጮች"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"የጥናት የምዝግብ ማስታወሻ ትዕዛዞች"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"የእውቅያ ስሞችን ተመልከት"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"ፊደል አራሚ ከእውቅያ ዝርዝርህ የገቡትን ይጠቀማል"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"በቁልፍመጫንጊዜ አንዝር"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index 13aef2a..7df155a 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"خيارات الإرسال"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"أوامر سجلات البحث"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"بحث في أسماء جهات الاتصال"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"يستخدم المدقق الإملائي إدخالات من قائمة جهات الاتصال"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"اهتزاز عند ضغط مفتاح"</string>
diff --git a/java/res/values-az-rAZ/strings.xml b/java/res/values-az-rAZ/strings.xml
index 5a40e9f..a929f8b 100644
--- a/java/res/values-az-rAZ/strings.xml
+++ b/java/res/values-az-rAZ/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Daxiletmə seçimləri"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Araşdırma Jurnalı Əmrləri"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontakt adlarına baxın"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Orfoqrafik yoxlanış kontakt siyahınızdakı qeydlərdən istifadə edir"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrasiyalı klikləmə"</string>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 562e71b..4c94962 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Опции за въвеждане"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Команди за рег. файл за проучвания"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Търсене на имена"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"За проверка на правописа се ползват записи от списъка с контакти"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Да вибрира при натискане на клавиш"</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index e946ba7..d438bb1 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opcions d\'entrada"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Recerca d\'ordres de reg."</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca noms de contactes"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortogràfic utilitza entrades de la llista de contactes"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibra en prémer tecles"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index c093d8c..c90c450 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávání textu a dat"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Příkazy vývoj. protokolu"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhledat kontakty"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kontrola pravopisu používá záznamy z vašeho seznamu kontaktů."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Při stisku klávesy vibrovat"</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 65025b7..e761157 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Indstillinger for input"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Forskningslogkommandoer"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Anvend kontaktnavne"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Stavekontrollen bruger ord fra dine kontaktpersondata"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibration ved tastetryk"</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index f2074b7..b5b0fee 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Eingabeoptionen"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Forschungsprotokollbefehle"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktnamen prüfen"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Rechtschreibprüfung kann Einträge aus meiner Kontaktliste verwenden"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Bei Tastendruck vibrieren"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 7f0e3f3..150c806 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Επιλογές εισόδου"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Έρευνα εντολών καταγραφής"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Αναζήτηση ονομάτων επαφών"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Ο ορθογρ. έλεγχος χρησιμοπ. καταχωρίσεις από τη λίστα επαφών σας"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Δόνηση κατά το πάτημα πλήκτρων"</string>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index 89e9789..2be2a56 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Input options"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Research Log Commands"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Look up contact names"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Spell checker uses entries from your contact list"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrate on keypress"</string>
diff --git a/java/res/values-en-rIN/strings.xml b/java/res/values-en-rIN/strings.xml
index 89e9789..2be2a56 100644
--- a/java/res/values-en-rIN/strings.xml
+++ b/java/res/values-en-rIN/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Input options"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Research Log Commands"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Look up contact names"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Spell checker uses entries from your contact list"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrate on keypress"</string>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index d440c0c..cf88e19 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones de entrada"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos registro invest."</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nombres contactos"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortográfico usa entradas de tu lista de contactos."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar teclas"</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 3476ac5..66a551d 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones entrada texto"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos registro investigación"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Nombres de contactos"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Añadir nombres de tu lista de contactos al corrector"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar tecla"</string>
diff --git a/java/res/values-et-rEE/strings.xml b/java/res/values-et-rEE/strings.xml
index 6fbc4b4..4c8042a 100644
--- a/java/res/values-et-rEE/strings.xml
+++ b/java/res/values-et-rEE/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Sisestusvalikud"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Uuringulogi käsud"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontakti nimede kontroll."</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Õigekirjakontroll kasutab teie kontaktisikute loendi sissekandeid"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreeri klahvivajutusel"</string>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index 04c6a5a..b8cfe03 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"گزینه‌های ورودی"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"فرمان‌های گزارش‌گیری پژوهش"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"جستجوی نام مخاطبین"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"غلط‌گیر املا از ورودی‌های لیست مخاطبین شما استفاده می‌کند"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"لرزش با فشار کلید"</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 756684a..75b949f 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Syöttövalinnat"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Tutkimuslokin komennot"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Hae yht.tietojen nimiä"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Oikeinkirjoituksen tarkistus käyttää yhteystietojasi."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Käytä värinää näppäimiä painettaessa"</string>
diff --git a/java/res/values-fr-rCA/strings.xml b/java/res/values-fr-rCA/strings.xml
index 5b13081..da44271 100644
--- a/java/res/values-fr-rCA/strings.xml
+++ b/java/res/values-fr-rCA/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Options de saisie"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Commandes journaux rech."</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Rechercher noms contacts"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Correcteur orthographique utilise entrées de liste de contacts."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer à chaque touche"</string>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 1bb8567..55f4afd 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Options de saisie"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Commandes journaux rech."</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Rechercher noms contacts"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Correcteur orthographique utilise entrées de liste de contacts."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer à chaque touche"</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 3129d86..73d1c87 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"इनपुट विकल्‍प"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"लॉग आदेशों का शोध करें"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"संपर्क नामों को खोजें"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"वर्तनी परीक्षक आपकी संपर्क सूची की प्रविष्टियों का उपयोग करता है"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"कुंजी दबाने पर कंपन करता है"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index 0882faa..656ba38 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opcije ulaza"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Istraživanje naredbi dnevnika"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Potražite imena kontakata"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Provjera pravopisa upotrebljava unose iz vašeg popisa kontakata"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibracija pri pritisku na tipku"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 8a953ab..575f116 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Beviteli beállítások"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Naplózási parancsok"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Névjegyek keresése"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"A helyesírás-ellenőrző használja a névjegyek bejegyzéseit"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rezgés gombnyomásra"</string>
diff --git a/java/res/values-hy-rAM/strings.xml b/java/res/values-hy-rAM/strings.xml
index 03d56a6..d55af47 100644
--- a/java/res/values-hy-rAM/strings.xml
+++ b/java/res/values-hy-rAM/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Ներածման ընտրանքներ"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Հետազոտական գրառումների հրամաններ"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Փնտրել կոնտակտային անուններ"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Տառասխալների ուղղիչն օգտագործում է ձեր կոնտակտների ցանկի տվյալները"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Թրթռալ սեղմման ժամանակ"</string>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index e3c5516..b2c12dd 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opsi masukan"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Riset Perintah Log"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kontak"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Pemeriksa ejaan menggunakan entri dari daftar kontak Anda"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar jika tombol ditekan"</string>
diff --git a/java/res/values-is/strings.xml b/java/res/values-is/strings.xml
index 1588534..e3efe1f 100644
--- a/java/res/values-is/strings.xml
+++ b/java/res/values-is/strings.xml
@@ -22,7 +22,6 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- no translation found for english_ime_input_options (3909945612939668554) -->
     <skip />
-    <!-- no translation found for english_ime_research_log (8492602295696577851) -->
     <skip />
     <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
     <skip />
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 6685095..eee5729 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opzioni inserimento"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Ricerca comandi di log"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca in nomi contatti"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"La funzione di controllo ortografico usa voci dell\'elenco contatti"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrazione tasti"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index dab2d8e..089aa08 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"אפשרויות קלט"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"פקודות יומן מחקר"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"חפש שמות של אנשי קשר"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"בודק האיות משתמש בערכים מרשימת אנשי הקשר שלך"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"רטט בלחיצה על מקשים"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 7d749a6..dc5c889 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"入力オプション"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"ログコマンドの検索"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"連絡先名の検索"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"スペルチェッカーでは連絡先リストのエントリを使用します"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"キー操作バイブ"</string>
diff --git a/java/res/values-ka-rGE/strings.xml b/java/res/values-ka-rGE/strings.xml
index 547bf29..74da2d0 100644
--- a/java/res/values-ka-rGE/strings.xml
+++ b/java/res/values-ka-rGE/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"შეყვანის მეთოდები"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"კვლევის აღრიცხვის ბრძანებები"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"კონტაქტებში ძებნა"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"კონტაქტების სიის გამოყენება მართლწერის შემოწმებისას"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"ვიბრაცია კლავიშზე დაჭერისას"</string>
diff --git a/java/res/values-kk/strings.xml b/java/res/values-kk/strings.xml
index 83ac0da..9ce3c52 100644
--- a/java/res/values-kk/strings.xml
+++ b/java/res/values-kk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Енгізу опциялары"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Журнал пәрмендерін зерттеу"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Контакт аттарын іздеу"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Емлені тексеру құралы контактілер тізімінің жазбаларын пайдаланады"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Пернені басқан кездегі діріл"</string>
diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml
index 519aa44..671137c 100644
--- a/java/res/values-km-rKH/strings.xml
+++ b/java/res/values-km-rKH/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"ជម្រើស​​បញ្ចូល"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"ពាក្យ​បញ្ជា​កំណត់​ហេតុ​​ការ​ស្រាវជ្រាវ"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"រក​មើល​ឈ្មោះ​ទំនាក់ទំនង"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"កម្មវិធី​ពិនិត្យ​អក្ខរាវិរុទ្ធ​ប្រើ​ធាតុ​ពី​​ក្នុង​បញ្ជី​ទំនាក់ទំនង​របស់​អ្នក"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"ញ័រ​នៅ​ពេល​ចុច​គ្រាប់ចុច"</string>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 4037abd..d6a6653 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"입력 옵션"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"로그 명령 탐색"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"연락처 이름 조회"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"맞춤법 검사기가 주소록의 항목을 사용합니다."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"키를 누를 때 진동 발생"</string>
diff --git a/java/res/values-lo-rLA/strings.xml b/java/res/values-lo-rLA/strings.xml
index 76fe5e0..8e996cd 100644
--- a/java/res/values-lo-rLA/strings.xml
+++ b/java/res/values-lo-rLA/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"ຕົວເລືອກການປ້ອນຂໍ້ມູນ"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Research Log Commands"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"ເບິ່ງທີ່ຊື່ຂອງລາຍຊື່ຜູ່ຕິດຕໍ່"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"ໂຕຊ່ວຍສະກົດໃຊ້ຂໍ້ມູນຈາກລາຍການຂອງລາຍຊື່ຜູ່ຕິດຕໍ່ຂອງທ່ານ"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"ສັ່ນເຕືອນເມື່ອພິມ"</string>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index c049a16..afd968d 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Įvesties parinktys"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Tyrinėti žurnalo komandas"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktų vardų paieška"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Rašybos tikrinimo progr. naudoja įrašus, esančius kontaktų sąraše"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibruoti, kai paspaudžiami klavišai"</string>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 901c348..92c3b26 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Ievades opcijas"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Izpētes žurnāla komandas"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Meklēt kontaktp. vārdus"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Pareizrakst. pārbaudītājs lieto ierakstus no kontaktp. saraksta."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrēt, nospiežot taustiņu"</string>
diff --git a/java/res/values-mk/strings.xml b/java/res/values-mk/strings.xml
index 1588534..e3efe1f 100644
--- a/java/res/values-mk/strings.xml
+++ b/java/res/values-mk/strings.xml
@@ -22,7 +22,6 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- no translation found for english_ime_input_options (3909945612939668554) -->
     <skip />
-    <!-- no translation found for english_ime_research_log (8492602295696577851) -->
     <skip />
     <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
     <skip />
diff --git a/java/res/values-mn-rMN/strings.xml b/java/res/values-mn-rMN/strings.xml
index 4c64b33..cdbe65d 100644
--- a/java/res/values-mn-rMN/strings.xml
+++ b/java/res/values-mn-rMN/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Оруулах сонголтууд"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Судалгааны протоколын командууд"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Харилцагчийн нэр хайх"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Алдаа шалгагч нь таны харилцагчдын жагсаалтаас ашиглана"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Товч дарахад чичрэх"</string>
diff --git a/java/res/values-ms-rMY/strings.xml b/java/res/values-ms-rMY/strings.xml
index cea2021..1c1bbd5 100644
--- a/java/res/values-ms-rMY/strings.xml
+++ b/java/res/values-ms-rMY/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Pilihan input"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Arahan Log Penyelidikan"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kenalan"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Penyemak ejaan menggunakan entri dari senarai kenalan anda"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar pada tekanan kekunci"</string>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index e4f1603..e61f75b 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Inndataalternativer"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Kommandoer for undersøkelseslogging"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå opp kontaktnavn"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Stavekontrollen bruker oppføringer fra kontaktlisten din"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer ved tastetrykk"</string>
diff --git a/java/res/values-ne-rNP/strings.xml b/java/res/values-ne-rNP/strings.xml
index f467443..537685c 100644
--- a/java/res/values-ne-rNP/strings.xml
+++ b/java/res/values-ne-rNP/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"इनपुट विकल्पहरू"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"लग निर्देशनहरू शोध गर्नुहोस्"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"सम्पर्क नामहरू हेर्नुहोस्"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"तपाईँको सम्पर्क सूचीबाट हिज्जे परीक्षकले प्रविष्टिहरूको प्रयोग गर्छ"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"कुञ्जी थिच्दा भाइब्रेट"</string>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index 342464f..d123d36 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropties"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Opdrachten in onderzoekslogbestand"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Contactnamen opzoeken"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"De spellingcontrole gebruikt items uit uw contactenlijst"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Trillen bij toetsaanslag"</string>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index c4261c6..cdd7d41 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opcje wprowadzania"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Polecenia dziennika badań"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Przeszukaj kontakty"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Sprawdzanie pisowni bierze pod uwagę wpisy z listy kontaktów."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Wibracja przy naciśnięciu"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 8b75dd0..d865f47 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opções de introdução"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos de Reg. Invest."</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Procurar nomes de contac."</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"O corretor ortográfico utiliza entradas da sua lista de contactos"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao primir as teclas"</string>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index afee26d..5b4d39b 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opções de entrada"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Pesq. comandos de reg."</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nomes de contatos"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"O corretor ortográfico usa entradas de sua lista de contatos"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao tocar a tecla"</string>
diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml
index 2ea98cf..43e1583 100644
--- a/java/res/values-rm/strings.xml
+++ b/java/res/values-rm/strings.xml
@@ -22,7 +22,6 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- no translation found for english_ime_input_options (3909945612939668554) -->
     <skip />
-    <!-- no translation found for english_ime_research_log (8492602295696577851) -->
     <skip />
     <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
     <skip />
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 51d3c59..dc8c1b8 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opţiuni de introducere text"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Comenzi jurnal cercetare"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Verificare nume în agendă"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Verificatorul ortografic utilizează intrări din lista de contacte"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrare la apăsarea tastei"</string>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index bef2483..065007e 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Настройки"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Все команды"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Поиск контактов"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Обращаться к списку контактов при проверке правописания"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Виброотклик клавиш"</string>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index 9a35647..4eefab9 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávania textu a údajov"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Príkazy denníka výskumu"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhľadať kontakty"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kontrola pravopisu používa záznamy z vášho zoznamu kontaktov"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Pri stlačení klávesu vibrovať"</string>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index 2594aae..b411dc4 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti vnosa"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Ukazi za dnevnik raziskav"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Iskanje imen stikov"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Črkovalnik uporablja vnose s seznama stikov"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibriranje ob pritisku tipke"</string>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 7bd7f67..2db4704 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Опције уноса"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Команде евиденције истраживања"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Потражи имена контаката"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Контролор правописа користи уносе са листе контаката"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вибрирај на притисак тастера"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 7092e68..116d2f4 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Inmatningsalternativ"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Loggkommandon"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Sök namn på kontakter"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"I stavningskontrollen används poster från kontaktlistan"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrera vid tangenttryck"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 5631289..7a40e5c 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Chaguo za uingizaji"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Amri za Kumbukumbu za Utafiti"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Angalia majina ya unaowasiliana nao"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kikagua tahajia hutumia majina yaliyoingizwa katika orodha yako ya anwani"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tetema unabofya kitufe"</string>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index ece0c4b..02fbd61 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"ตัวเลือกการป้อนข้อมูล"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"คำสั่งบันทึกการวิจัย"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"ค้นหารายชื่อติดต่อ"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"เครื่องมือตรวจการสะกดใช้รายการจากรายชื่อติดต่อของคุณ"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"สั่นเมื่อกดปุ่ม"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index ce1207a..43bbcd0 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Mga pagpipilian sa input"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Cmmnd sa Log ng Pnnliksik"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Maghanap pangalan contact"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Gumagamit ang Spell Checker ng entries mula sa iyong contact list."</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Mag-vibrate sa keypress"</string>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index 3584ec5..329c7c6 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Giriş seçenekleri"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Araştırma Günlüğü Komutları"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kişi adlarını denetle"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Yazım denetleyici, kişi listenizdeki girişleri kullanır"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tuşa basıldığında titret"</string>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index 15a3080..ab42832 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Парам. введення"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Команди журналу дослідж."</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Шукати імена контактів"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Програма перевірки правопису використ. записи зі списку контактів"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вібр. при натисканні клавіш"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index 529dcec..0196207 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Tùy chọn nhập"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Lệnh ghi nhật ký cho nghiên cứu"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Tra cứu tên liên hệ"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Trình kiểm tra chính tả sử dụng các mục nhập từ danh sách liên hệ của bạn"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rung khi nhấn phím"</string>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index 41fe0bf..134b9d5 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"输入选项"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"研究记录命令"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查找联系人姓名"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"拼写检查工具会使用您的联系人列表中的条目"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"按键振动"</string>
diff --git a/java/res/values-zh-rHK/strings.xml b/java/res/values-zh-rHK/strings.xml
index 34fa9c0..f2453a7 100644
--- a/java/res/values-zh-rHK/strings.xml
+++ b/java/res/values-zh-rHK/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"輸入選項"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"研究記錄指令"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查找聯絡人姓名"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"拼字檢查程式使用您的聯絡人名單中的各項記錄"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"按鍵時震動"</string>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 9c9f5e0..d9ee790 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"輸入選項"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"研究紀錄指令"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查詢聯絡人姓名"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"拼字檢查程式使用您的聯絡人清單項目"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"按鍵時震動"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index c79d81d..488fcdf 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="english_ime_input_options" msgid="3909945612939668554">"Okukhethwa kukho kokungenayo"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Imiyalo yefayela lokungena lokucwaninga"</string>
     <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Bheka amagama woxhumana nabo"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Isihloli sokupela sisebenzisa okungenayo kusuka kuhlu lalabo oxhumana nabo"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Dlidlizelisa ngokucindezela inkinobho"</string>
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 415dd0b..83d082f 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -137,6 +137,4 @@
         <item>tr:AsciiCapable,SupportTouchPositionCorrection,EmojiCapable</item>
         <item>qwerty</item>
     </string-array>
-
-    <string name="settings_warning_researcher_mode">Attention!  You are using the special keyboard for research purposes.</string>
 </resources>
diff --git a/java/res/values/research_strings.xml b/java/res/values/research_strings.xml
deleted file mode 100644
index e738711..0000000
--- a/java/res/values/research_strings.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2012, 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.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Contents of note explaining what data is collected and how. -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_splash_content" translatable="false"></string>
-    <!-- Account type allowed for inclusion in user-invoked feedback logs [CHAR LIMIT=38] -->
-    <string name="research_account_type" translatable="false"></string>
-    <!-- Account domain allowed for inclusion in user-invoked feedback logs [CHAR LIMIT=38] -->
-    <string name="research_allowed_account_domain" translatable="false"></string>
-
-    <!-- Menu option that lets user send feedback for research purposes about the IME [CHAR LIMIT=38] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_menu_option" translatable="false">Send feedback</string>
-    <!-- Title of dialog box that lets user send feedback for research purposes about the IME [CHAR LIMIT=38] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_dialog_title" translatable="false">Send feedback</string>
-    <!-- Hint to user about the text entry field where they should enter research feedback [CHAR LIMIT=40] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_hint" translatable="false">Enter your feedback here.</string>
-    <!-- Message informing the user that the feedback string must not be empty [CHAR LIMIT=100] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_empty_feedback_error_message" translatable="false">The feedback field must not be empty.</string>
-</resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 9f93055..a053b0b 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -21,9 +21,6 @@
     <!-- Title for Latin keyboard input options dialog [CHAR LIMIT=25] -->
     <string name="english_ime_input_options">Input options</string>
 
-    <!-- Title for Latin keyboard research log dialog, which contains special commands for users that contribute data for research. [CHAR LIMIT=33] -->
-    <string name="english_ime_research_log">Research Log Commands</string>
-
     <!-- Title for the spell checker option to turn on/off contact names lookup [CHAR LIMIT=25] -->
     <string name="use_contacts_for_spellchecking_option_title">Look up contact names</string>
 
@@ -166,68 +163,8 @@
     <!-- Title for input language selection screen -->
     <string name="language_selection_title">Input languages</string>
 
-    <!-- Title for dialog option to let users cancel logging and delete log for this session [CHAR LIMIT=35] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_do_not_log_this_session" translatable="false">Suspend logging</string>
-    <!-- Title for dialog option to let users reenable logging [CHAR LIMIT=35] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_enable_session_logging" translatable="false">Enable logging</string>
-    <!-- Toast notification that the system is processing the request to delete the log for this session [CHAR LIMIT=35] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_notify_session_log_deleting" translatable="false">Deleting session log</string>
-    <!-- Toast notification that the system has successfully deleted the log for this session [CHAR LIMIT=35] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_notify_logging_suspended" translatable="false">Logging temporarily suspended.  To disable permanently, go to Android Keyboard Settings</string>
-    <!-- Toast notification that the system has failed to delete the log for this session [CHAR LIMIT=35] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_notify_session_log_not_deleted" translatable="false">Session log NOT deleted</string>
-    <!-- Toast notification that the system is enabling logging [CHAR LIMIT=35] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_notify_session_logging_enabled" translatable="false">Session logging enabled</string>
-
-    <!-- Text for checkbox option to include user data in feedback for research purposes [CHAR LIMIT=50] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_include_history_label" translatable="false">Include session history</string>
-    <!-- Text for checkbox option to include user account name in feedback for research purposes [CHAR LIMIT=50] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_include_account_name_label" translatable="false">Include account name</string>
-    <!-- Text for checkbox option to include a recording in feedback for research purposes [CHAR LIMIT=50] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_include_recording_label" translatable="false">Include recorded demonstration</string>
-    <!-- Dialog button choice to send research feedback [CHAR LIMIT=35] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_send" translatable="false">Send</string>
-    <!-- Dialog button choice to cancel sending research feedback [CHAR LIMIT=35] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_cancel" translatable="false">Cancel</string>
-    <!-- Temporary notification to provide user with instructions about stopping a recording
-      - operation[CHAR LIMIT=100] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_demonstration_instructions" translatable="false">Please demonstrate the issue you are writing about.\n\nWhen finished, select the \"Bug?\" button again."</string>
     <!-- Title of a preference to send feedback. [CHAR LIMIT=30]-->
     <string name="send_feedback">Send feedback</string>
-    <!-- Temporary notification of recording failure [CHAR LIMIT=100] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_feedback_recording_failure" translatable="false">Recording cancelled due to timeout</string>
-    <!-- Toast notification to ask user to quit the research feedback dialog to perform this operation [CHAR LIMIT=100] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_please_exit_feedback_form" translatable="false">Please exit the feedback dialog to access the research log menu</string>
-
-    <!-- Title of dialog shown at start informing users about contributing research usage data-->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_splash_title" translatable="false">Warning</string>
-
-    <!-- Toast message informing users that logging has been disabled -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_logging_disabled" translatable="false">Logging Disabled</string>
-
-    <!-- Name for the research uploading service to be displayed to users.  [CHAR LIMIT=50] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_log_uploader_name" translatable="false">Research Uploader Service</string>
-
-    <!-- Name for the research replaying service to be displayed to users.  [CHAR LIMIT=50] -->
-    <!-- TODO: remove translatable=false attribute once text is stable -->
-    <string name="research_log_replayer_name" translatable="false">Research Replayer Service</string>
 
     <!-- Preference for input language selection -->
     <string name="select_language">Input languages</string>
diff --git a/java/res/values/urls.xml b/java/res/values/urls.xml
deleted file mode 100644
index a8e9ad7..0000000
--- a/java/res/values/urls.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2012, 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.
-*/
--->
-<resources>
-    <string name="research_logger_upload_url" translatable="false"></string>
-</resources>
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index f90ad79..ca7da6e 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -37,9 +37,7 @@
 import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.utils.TypefaceUtils;
-import com.android.inputmethod.research.ResearchLogger;
 
 import java.util.HashSet;
 
@@ -317,13 +315,6 @@
             }
         }
 
-        // Research Logging (Development Only Diagnostics) indicator.
-        // TODO: Reimplement using a keyboard background image specific to the ResearchLogger,
-        // and remove this call.
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.getInstance().paintIndicator(this, paint, canvas, width, height);
-        }
-
         mInvalidatedKeys.clear();
         mInvalidateAllKeys = false;
     }
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index f291a7e..4362a24 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -55,13 +55,11 @@
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.settings.DebugSettings;
 import com.android.inputmethod.latin.utils.CoordinateUtils;
 import com.android.inputmethod.latin.utils.SpacebarLanguageUtils;
 import com.android.inputmethod.latin.utils.TypefaceUtils;
 import com.android.inputmethod.latin.utils.UsabilityStudyLogUtils;
-import com.android.inputmethod.research.ResearchLogger;
 
 import java.util.WeakHashMap;
 
@@ -387,10 +385,6 @@
         mSpaceKey = keyboard.getKey(Constants.CODE_SPACE);
         final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
         mLanguageOnSpacebarTextSize = keyHeight * mLanguageOnSpacebarTextRatio;
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            final int orientation = getContext().getResources().getConfiguration().orientation;
-            ResearchLogger.mainKeyboardView_setKeyboard(keyboard, orientation);
-        }
 
         mAccessibilityDelegate.setKeyboard(keyboard);
     }
@@ -552,24 +546,12 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         installPreviewPlacerView();
-        // Notify the ResearchLogger (development only diagnostics) that the keyboard view has
-        // been attached.  This is needed to properly show the splash screen, which requires that
-        // the window token of the KeyboardView be non-null.
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.getInstance().mainKeyboardView_onAttachedToWindow(this);
-        }
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         mDrawingPreviewPlacerView.removeAllViews();
-        // Notify the ResearchLogger (development only diagnostics) that the keyboard view has
-        // been detached.  This is needed to invalidate the reference of {@link MainKeyboardView}
-        // to null.
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.getInstance().mainKeyboardView_onDetachedFromWindow();
-        }
     }
 
     private MoreKeysPanel onCreateMoreKeysPanel(final Key key, final Context context) {
@@ -605,9 +587,6 @@
         if (key == null) {
             return;
         }
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.mainKeyboardView_onLongPress();
-        }
         final KeyboardActionListener listener = mKeyboardActionListener;
         if (key.hasNoPanelAutoMoreKey()) {
             final int moreKeyCode = key.getMoreKeys()[0].mCode;
@@ -723,10 +702,6 @@
         if (LatinImeLogger.sUsabilityStudy) {
             UsabilityStudyLogUtils.writeMotionEvent(me);
         }
-        // Currently the same "move" event is being logged twice.
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.mainKeyboardView_processMotionEvent(me);
-        }
 
         final int index = me.getActionIndex();
         final int id = me.getPointerId(index);
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 303886c..f807611 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -35,11 +35,9 @@
 import com.android.inputmethod.latin.InputPointers;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.utils.CoordinateUtils;
 import com.android.inputmethod.latin.utils.ResourceUtils;
-import com.android.inputmethod.research.ResearchLogger;
 
 import java.util.ArrayList;
 
@@ -335,10 +333,6 @@
                     output, ignoreModifierKey ? " ignoreModifier" : "",
                     altersCode ? " altersCode" : "", key.isEnabled() ? "" : " disabled"));
         }
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.pointerTracker_callListenerOnCodeInput(key, x, y, ignoreModifierKey,
-                    altersCode, code);
-        }
         if (ignoreModifierKey) {
             return;
         }
@@ -373,10 +367,6 @@
                     withSliding ? " sliding" : "", ignoreModifierKey ? " ignoreModifier" : "",
                     key.isEnabled() ?  "": " disabled"));
         }
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.pointerTracker_callListenerOnRelease(key, primaryCode, withSliding,
-                    ignoreModifierKey);
-        }
         if (ignoreModifierKey) {
             return;
         }
@@ -396,9 +386,6 @@
         if (DEBUG_LISTENER) {
             Log.d(TAG, String.format("[%d] onCancelInput", mPointerId));
         }
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.pointerTracker_callListenerOnCancelInput();
-        }
         sListener.onCancelInput();
     }
 
@@ -702,9 +689,6 @@
                     Log.w(TAG, String.format("[%d] onDownEvent:"
                             + " ignore potential noise: time=%d distance=%d",
                             mPointerId, deltaT, distance));
-                if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                    ResearchLogger.pointerTracker_onDownEvent(deltaT, distance * distance);
-                }
                 cancelTrackingForAction();
                 return;
             }
@@ -876,10 +860,6 @@
                     lastX, lastY, Constants.printableCode(oldKey.getCode()),
                     x, y, Constants.printableCode(key.getCode())));
         }
-        // TODO: This should be moved to outside of this nested if-clause?
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY);
-        }
         onUpEventInternal(x, y, eventTime);
         onDownEventInternal(x, y, eventTime);
     }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index aeae6aa..a325416 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -28,7 +28,6 @@
 import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
@@ -38,7 +37,6 @@
 import android.os.Debug;
 import android.os.IBinder;
 import android.os.Message;
-import android.preference.PreferenceManager;
 import android.text.InputType;
 import android.text.TextUtils;
 import android.util.Log;
@@ -90,7 +88,6 @@
 import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
 import com.android.inputmethod.latin.utils.StatsUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
-import com.android.inputmethod.research.ResearchLogger;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -494,11 +491,6 @@
         loadSettings();
         resetSuggest();
 
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.getInstance().init(this, mKeyboardSwitcher);
-            ResearchLogger.getInstance().initDictionary(mDictionaryFacilitator);
-        }
-
         // Register to receive ringer mode change and network state change.
         // Also receive installation and removal of a dictionary pack.
         final IntentFilter filter = new IntentFilter();
@@ -631,9 +623,6 @@
         mDictionaryFacilitator.closeDictionaries();
         mSettings.onDestroy();
         unregisterReceiver(mConnectivityAndRingerModeChangeReceiver);
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.getInstance().onDestroy();
-        }
         unregisterReceiver(mDictionaryPackInstallReceiver);
         unregisterReceiver(mDictionaryDumpBroadcastReceiver);
         PersonalizationDictionarySessionRegistrar.close(this);
@@ -757,10 +746,6 @@
         }
         Log.i(TAG, "Starting input. Cursor position = "
                 + editorInfo.initialSelStart + "," + editorInfo.initialSelEnd);
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
-            ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, prefs);
-        }
         if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) {
             Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions);
             Log.w(TAG, "Use " + getPackageName() + "." + NO_MICROPHONE + " instead");
@@ -905,10 +890,6 @@
         mHandler.cancelUpdateSuggestionStrip();
         // Should do the following in onFinishInputInternal but until JB MR2 it's not called :(
         mInputLogic.finishInput();
-        // Notify ResearchLogger
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_onFinishInputViewInternal(finishingInput);
-        }
     }
 
     @Override
@@ -922,11 +903,6 @@
                     + ", nss=" + newSelStart + ", nse=" + newSelEnd
                     + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd);
         }
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_onUpdateSelection(oldSelStart, oldSelEnd,
-                    oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart,
-                    composingSpanEnd, mInputLogic.mConnection);
-        }
 
         // If the keyboard is not visible, we don't need to do all the housekeeping work, as it
         // will be reset when the keyboard shows up anyway.
@@ -1013,9 +989,6 @@
         }
         if (applicationSpecifiedCompletions == null) {
             setNeutralSuggestionStrip();
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.latinIME_onDisplayCompletions(null);
-            }
             return;
         }
 
@@ -1027,9 +1000,6 @@
                 false /* isObsoleteSuggestions */, false /* isPrediction */);
         // When in fullscreen mode, show completions generated by the application forcibly
         setSuggestedWords(suggestedWords, true /* isSuggestionStripVisible */);
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions);
-        }
     }
 
     private int getAdjustedBackingViewHeight() {
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index e7c1636..46c0151 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -26,14 +26,12 @@
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
 
-import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 import com.android.inputmethod.latin.utils.CapsModeUtils;
 import com.android.inputmethod.latin.utils.DebugLogUtils;
 import com.android.inputmethod.latin.utils.SpannableStringUtils;
 import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.TextRange;
-import com.android.inputmethod.research.ResearchLogger;
 
 import java.util.Arrays;
 import java.util.regex.Pattern;
@@ -174,9 +172,6 @@
         }
         if (null != mIC && shouldFinishComposition) {
             mIC.finishComposingText();
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.richInputConnection_finishComposingText();
-            }
         }
         return true;
     }
@@ -223,9 +218,6 @@
         mComposingText.setLength(0);
         if (null != mIC) {
             mIC.finishComposingText();
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.richInputConnection_finishComposingText();
-            }
         }
     }
 
@@ -363,9 +355,6 @@
         }
         if (null != mIC) {
             mIC.deleteSurroundingText(beforeLength, afterLength);
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.richInputConnection_deleteSurroundingText(beforeLength, afterLength);
-            }
         }
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
     }
@@ -374,9 +363,6 @@
         mIC = mParent.getCurrentInputConnection();
         if (null != mIC) {
             mIC.performEditorAction(actionId);
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.richInputConnection_performEditorAction(actionId);
-            }
         }
     }
 
@@ -429,9 +415,6 @@
         }
         if (null != mIC) {
             mIC.sendKeyEvent(keyEvent);
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.richInputConnection_sendKeyEvent(keyEvent);
-            }
         }
     }
 
@@ -469,9 +452,6 @@
         // newCursorPosition != 1.
         if (null != mIC) {
             mIC.setComposingText(text, newCursorPosition);
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.richInputConnection_setComposingText(text, newCursorPosition);
-            }
         }
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
     }
@@ -500,9 +480,6 @@
             if (!isIcValid) {
                 return false;
             }
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.richInputConnection_setSelection(start, end);
-            }
         }
         return reloadTextCache();
     }
@@ -530,9 +507,6 @@
         mComposingText.setLength(0);
         if (null != mIC) {
             mIC.commitCompletion(completionInfo);
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.richInputConnection_commitCompletion(completionInfo);
-            }
         }
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
     }
@@ -765,9 +739,6 @@
         deleteSurroundingText(2, 0);
         final String singleSpace = " ";
         commitText(singleSpace, 1);
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.richInputConnection_revertDoubleSpacePeriod();
-        }
         return true;
     }
 
@@ -790,9 +761,6 @@
         deleteSurroundingText(2, 0);
         final String text = " " + textBeforeCursor.subSequence(0, 1);
         commitText(text, 1);
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.richInputConnection_revertSwapPunctuation();
-        }
         return true;
     }
 
diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
index 761f457..9725802 100644
--- a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
+++ b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
@@ -21,13 +21,6 @@
         // This class is not publicly instantiable.
     }
 
-    public static final boolean USES_DEVELOPMENT_ONLY_DIAGNOSTICS = false;
-
-    // When false, USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG suggests that all guarded
-    // class-private DEBUG flags should be false, and any privacy controls should be enforced.
-    // USES_DEVELOPMENT_ONLY_DIAGNOSTICS must be false for any production build.
-    public static final boolean USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG = false;
-
     public static final boolean IS_HARDWARE_KEYBOARD_SUPPORTED = false;
 
     // When true, enable {@link InputMethodService#onUpdateCursor} callback with
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 2b7024a..2530f64 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -44,7 +44,6 @@
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.WordComposer;
-import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.settings.SettingsValues;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 import com.android.inputmethod.latin.suggestions.SuggestionStripViewAccessor;
@@ -54,7 +53,6 @@
 import com.android.inputmethod.latin.utils.RecapitalizeStatus;
 import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.TextRange;
-import com.android.inputmethod.research.ResearchLogger;
 
 import java.util.ArrayList;
 import java.util.TreeSet;
@@ -201,19 +199,11 @@
             resetComposingState(true /* alsoResetLastComposedWord */);
         }
         handler.postUpdateSuggestionStrip();
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS
-                && ResearchLogger.RESEARCH_KEY_OUTPUT_TEXT.equals(rawText)) {
-            ResearchLogger.getInstance().onResearchKeySelected(mLatinIME);
-            return;
-        }
         final String text = performSpecificTldProcessingOnTextInput(rawText);
         if (SpaceState.PHANTOM == mSpaceState) {
             promotePhantomSpace(settingsValues);
         }
         mConnection.commitText(text, 1);
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_onTextInput(text, false /* isBatchMode */);
-        }
         mConnection.endBatchEdit();
         // Space state must be updated before calling updateShiftState
         mSpaceState = SpaceState.NONE;
@@ -244,10 +234,6 @@
             LatinImeLogger.logOnManualSuggestion("", suggestion, index, suggestedWords);
             // Rely on onCodeInput to do the complicated swapping/stripping logic consistently.
             final Event event = Event.createPunctuationSuggestionPickedEvent(suggestionInfo);
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.latinIME_punctuationSuggestion(index, suggestion,
-                        false /* isBatchMode */, suggestedWords.mIsPrediction);
-            }
             return onCodeInput(settingsValues, event, keyboardShiftState, handler);
         }
 
@@ -286,11 +272,6 @@
         LatinImeLogger.logOnManualSuggestion(replacedWord, suggestion, index, suggestedWords);
         commitChosenWord(settingsValues, suggestion,
                 LastComposedWord.COMMIT_TYPE_MANUAL_PICK, LastComposedWord.NOT_A_SEPARATOR);
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_pickSuggestionManually(replacedWord, index, suggestion,
-                    mWordComposer.isBatchMode(), suggestionInfo.mScore,
-                    suggestionInfo.mKindAndFlags, suggestionInfo.mSourceDict.mDictType);
-        }
         mConnection.endBatchEdit();
         // Don't allow cancellation of manual pick
         mLastComposedWord.deactivate();
@@ -403,9 +384,6 @@
         final InputTransaction inputTransaction = new InputTransaction(settingsValues, event,
                 SystemClock.uptimeMillis(), mSpaceState,
                 getActualCapsMode(settingsValues, keyboardShiftMode));
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_onCodeInput(code, event.mX, event.mY);
-        }
         if (event.mKeyCode != Constants.CODE_DELETE
                 || inputTransaction.mTimestamp > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) {
             mDeleteCount = 0;
@@ -854,9 +832,6 @@
         if (needsPrecedingSpace) {
             promotePhantomSpace(settingsValues);
         }
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_handleSeparator(codePoint, mWordComposer.isComposingWord());
-        }
 
         if (!shouldAvoidSendingCode) {
             sendKeyCodePoint(settingsValues, codePoint);
@@ -932,10 +907,6 @@
         }
         if (mWordComposer.isComposingWord()) {
             if (mWordComposer.isBatchMode()) {
-                if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                    final String word = mWordComposer.getTypedWord();
-                    ResearchLogger.latinIME_handleBackspace_batch(word, 1);
-                }
                 final String rejectedSuggestion = mWordComposer.getTypedWord();
                 mWordComposer.reset();
                 mWordComposer.setRejectedBatchModeSuggestion(rejectedSuggestion);
@@ -961,9 +932,6 @@
                 // This is triggered on backspace after a key that inputs multiple characters,
                 // like the smiley key or the .com key.
                 mConnection.deleteSurroundingText(mEnteredText.length(), 0);
-                if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                    ResearchLogger.latinIME_handleBackspace_cancelTextInput(mEnteredText);
-                }
                 mEnteredText = null;
                 // If we have mEnteredText, then we know that mHasUncommittedTypedChars == false.
                 // In addition we know that spaceState is false, and that we should not be
@@ -993,10 +961,6 @@
                 mConnection.setSelection(mConnection.getExpectedSelectionEnd(),
                         mConnection.getExpectedSelectionEnd());
                 mConnection.deleteSurroundingText(numCharsDeleted, 0);
-                if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                    ResearchLogger.latinIME_handleBackspace(numCharsDeleted,
-                            false /* shouldUncommitLogUnit */);
-                }
             } else {
                 // There is no selection, just delete one character.
                 if (Constants.NOT_A_CURSOR_POSITION == mConnection.getExpectedSelectionEnd()) {
@@ -1031,10 +995,6 @@
                     final int lengthToDelete =
                             Character.isSupplementaryCodePoint(codePointBeforeCursor) ? 2 : 1;
                     mConnection.deleteSurroundingText(lengthToDelete, 0);
-                    if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                        ResearchLogger.latinIME_handleBackspace(lengthToDelete,
-                                true /* shouldUncommitLogUnit */);
-                    }
                     if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) {
                         final int codePointBeforeCursorToDeleteAgain =
                                 mConnection.getCodePointBeforeCursor();
@@ -1042,10 +1002,6 @@
                             final int lengthToDeleteAgain = Character.isSupplementaryCodePoint(
                                     codePointBeforeCursorToDeleteAgain) ? 2 : 1;
                             mConnection.deleteSurroundingText(lengthToDeleteAgain, 0);
-                            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                                ResearchLogger.latinIME_handleBackspace(lengthToDeleteAgain,
-                                        true /* shouldUncommitLogUnit */);
-                            }
                         }
                     }
                 }
@@ -1083,9 +1039,6 @@
             mConnection.deleteSurroundingText(2, 0);
             final String text = lastTwo.charAt(1) + " ";
             mConnection.commitText(text, 1);
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.latinIME_swapSwapperAndSpace(lastTwo, text);
-            }
             inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
         }
     }
@@ -1169,10 +1122,6 @@
             final String textToInsert = inputTransaction.mSettingsValues.mSpacingAndPunctuations
                     .mSentenceSeparatorAndSpace;
             mConnection.commitText(textToInsert, 1);
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.latinIME_maybeDoubleSpacePeriod(textToInsert,
-                        false /* isBatchMode */);
-            }
             mWordComposer.discardPreviousWordForSuggestion();
             return true;
         }
@@ -1519,13 +1468,7 @@
             LatinImeLoggerUtils.onSeparator(mLastComposedWord.mSeparatorString,
                     Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
         }
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_revertCommit(committedWord.toString(),
-                    originallyTypedWord.toString(),
-                    mWordComposer.isBatchMode(), mLastComposedWord.mSeparatorString);
-        }
-        // Don't restart suggestion yet. We'll restart if the user deletes the
-        // separator.
+        // Don't restart suggestion yet. We'll restart if the user deletes the separator.
         mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
         // We have a separator between the word and the cursor: we should show predictions.
         inputTransaction.setRequiresUpdateSuggestions();
@@ -1789,9 +1732,6 @@
      */
     // TODO: replace these two parameters with an InputTransaction
     private void sendKeyCodePoint(final SettingsValues settingsValues, final int codePoint) {
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_sendKeyCodePoint(codePoint);
-        }
         // TODO: Remove this special handling of digit letters.
         // For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}.
         if (codePoint >= '0' && codePoint <= '9') {
@@ -1823,9 +1763,6 @@
         if (settingsValues.shouldInsertSpacesAutomatically()
                 && settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces
                 && !mConnection.textBeforeCursorLooksLikeURL()) {
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.latinIME_promotePhantomSpace();
-            }
             sendKeyCodePoint(settingsValues, Constants.CODE_SPACE);
         }
     }
@@ -1867,9 +1804,6 @@
             mConnection.setComposingText(batchInputText, 1);
         }
         mConnection.endBatchEdit();
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.latinIME_onEndBatchInput(batchInputText, 0, suggestedWords);
-        }
         // Space state must be updated before calling updateShiftState
         mSpaceState = SpaceState.PHANTOM;
         keyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(settingsValues),
@@ -1896,9 +1830,6 @@
         if (!mWordComposer.isComposingWord()) return;
         final String typedWord = mWordComposer.getTypedWord();
         if (typedWord.length() > 0) {
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.getInstance().onWordFinished(typedWord, mWordComposer.isBatchMode());
-            }
             commitChosenWord(settingsValues, typedWord,
                     LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, separatorString);
         }
@@ -1942,11 +1873,6 @@
                 LatinImeLoggerUtils.onAutoCorrection(
                         typedWord, autoCorrection, separator, mWordComposer);
             }
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                final SuggestedWords suggestedWords = mSuggestedWords;
-                ResearchLogger.latinIme_commitCurrentAutoCorrection(typedWord, autoCorrection,
-                        separator, mWordComposer.isBatchMode(), suggestedWords);
-            }
             commitChosenWord(settingsValues, autoCorrection,
                     LastComposedWord.COMMIT_TYPE_DECIDED_WORD, separator);
             if (!typedWord.equals(autoCorrection)) {
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
index c4c1234..5fa15f4 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
@@ -76,7 +76,6 @@
             final CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref;
             checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE,
                     LatinImeLogger.getUsabilityStudyMode(prefs)));
-            checkbox.setSummary(R.string.settings_warning_researcher_mode);
         }
         final Preference statisticsLoggingPref = findPreference(PREF_STATISTICS_LOGGING);
         if (statisticsLoggingPref instanceof CheckBoxPreference) {
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
index 302ae43..af46aad 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
@@ -41,7 +41,6 @@
 import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SubtypeSwitcher;
-import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager;
 import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
 import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
@@ -152,10 +151,6 @@
                 miscSettings.removePreference(aboutSettings);
             }
         }
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            // The about screen contains items that may be confusing in development-only versions.
-            miscSettings.removePreference(aboutSettings);
-        }
 
         final boolean showVoiceKeyOption = res.getBoolean(
                 R.bool.config_enable_show_voice_key_option);
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index c400f66..4a5a7f0 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -47,11 +47,9 @@
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.suggestions.MoreSuggestionsView.MoreSuggestionsListener;
 import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
-import com.android.inputmethod.research.ResearchLogger;
 
 import java.util.ArrayList;
 
@@ -226,9 +224,6 @@
         mSuggestedWords = suggestedWords;
         mSuggestionsCountInStrip = mLayoutHelper.layoutAndReturnSuggestionCountInStrip(
                 mSuggestedWords, mSuggestionsStrip, this);
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            ResearchLogger.suggestionStripView_setSuggestions(mSuggestedWords);
-        }
         mStripVisibilityGroup.showSuggestionsStrip(isVoiceKeyEnabled());
     }
 
diff --git a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
index 149fbb3..e300bd1 100644
--- a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
@@ -26,7 +26,6 @@
 import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
 import com.android.inputmethod.latin.userdictionary.UserDictionaryLocalePicker;
 import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
-import com.android.inputmethod.research.FeedbackFragment;
 
 import java.util.HashSet;
 
@@ -43,7 +42,6 @@
         sLatinImeFragments.add(UserDictionaryList.class.getName());
         sLatinImeFragments.add(UserDictionaryLocalePicker.class.getName());
         sLatinImeFragments.add(UserDictionarySettings.class.getName());
-        sLatinImeFragments.add(FeedbackFragment.class.getName());
     }
 
     public static boolean isValidFragment(String fragmentName) {
diff --git a/java/src/com/android/inputmethod/latin/utils/UsabilityStudyLogUtils.java b/java/src/com/android/inputmethod/latin/utils/UsabilityStudyLogUtils.java
index 06826da..fac932d 100644
--- a/java/src/com/android/inputmethod/latin/utils/UsabilityStudyLogUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/UsabilityStudyLogUtils.java
@@ -43,7 +43,6 @@
 import java.util.Locale;
 
 public final class UsabilityStudyLogUtils {
-    // TODO: remove code duplication with ResearchLog class
     private static final String USABILITY_TAG = UsabilityStudyLogUtils.class.getSimpleName();
     private static final String FILENAME = "log.txt";
     private final Handler mLoggingHandler;
@@ -190,7 +189,7 @@
         return sb.toString();
     }
 
-    public void emailResearcherLogsAll() {
+    public void emailUsabilityStudyLogsAll() {
         mLoggingHandler.post(new Runnable() {
             @Override
             public void run() {
@@ -210,7 +209,7 @@
                 }
                 mWriter.flush();
                 final String destPath = Environment.getExternalStorageDirectory()
-                        + "/research-" + currentDateTimeString + ".log";
+                        + "/usability-" + currentDateTimeString + ".log";
                 final File destFile = new File(destPath);
                 try {
                     final FileInputStream srcStream = new FileInputStream(mFile);
@@ -241,7 +240,7 @@
                 intent.setType("text/plain");
                 intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + destPath));
                 intent.putExtra(Intent.EXTRA_SUBJECT,
-                        "[Research Logs] " + currentDateTimeString);
+                        "[Usability Study Logs] " + currentDateTimeString);
                 mIms.startActivity(intent);
             }
         });
diff --git a/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java b/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java
deleted file mode 100644
index 4f86526..0000000
--- a/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Arrange for the uploading service to be run on regular intervals.
- */
-public final class BootBroadcastReceiver extends BroadcastReceiver {
-    @Override
-    public void onReceive(final Context context, final Intent intent) {
-        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
-            UploaderService.cancelAndRescheduleUploadingService(context,
-                    true /* needsRescheduling */);
-        }
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/FeedbackActivity.java b/java/src/com/android/inputmethod/research/FeedbackActivity.java
deleted file mode 100644
index 520b88d..0000000
--- a/java/src/com/android/inputmethod/research/FeedbackActivity.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-import com.android.inputmethod.latin.R;
-
-public class FeedbackActivity extends Activity {
-    @Override
-    protected void onCreate(final Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.research_feedback_activity);
-        final FeedbackLayout layout = (FeedbackLayout) findViewById(R.id.research_feedback_layout);
-        layout.setActivity(this);
-    }
-
-    @Override
-    public void onBackPressed() {
-        ResearchLogger.getInstance().onLeavingSendFeedbackDialog();
-        super.onBackPressed();
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/FeedbackFragment.java b/java/src/com/android/inputmethod/research/FeedbackFragment.java
deleted file mode 100644
index 75fbbf1..0000000
--- a/java/src/com/android/inputmethod/research/FeedbackFragment.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.app.Fragment;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.EditText;
-import android.widget.Toast;
-
-import com.android.inputmethod.latin.R;
-
-public class FeedbackFragment extends Fragment implements OnClickListener {
-    private static final String TAG = FeedbackFragment.class.getSimpleName();
-
-    public static final String KEY_FEEDBACK_STRING = "FeedbackString";
-    public static final String KEY_INCLUDE_ACCOUNT_NAME = "IncludeAccountName";
-    public static final String KEY_HAS_USER_RECORDING = "HasRecording";
-
-    private EditText mEditText;
-    private CheckBox mIncludingAccountNameCheckBox;
-    private CheckBox mIncludingUserRecordingCheckBox;
-    private Button mSendButton;
-    private Button mCancelButton;
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        final View view = inflater.inflate(R.layout.research_feedback_fragment_layout, container,
-                false);
-        mEditText = (EditText) view.findViewById(R.id.research_feedback_contents);
-        mEditText.requestFocus();
-        mIncludingAccountNameCheckBox = (CheckBox) view.findViewById(
-                R.id.research_feedback_include_account_name);
-        mIncludingUserRecordingCheckBox = (CheckBox) view.findViewById(
-                R.id.research_feedback_include_recording_checkbox);
-        mIncludingUserRecordingCheckBox.setOnClickListener(this);
-
-        mSendButton = (Button) view.findViewById(R.id.research_feedback_send_button);
-        mSendButton.setOnClickListener(this);
-        mCancelButton = (Button) view.findViewById(R.id.research_feedback_cancel_button);
-        mCancelButton.setOnClickListener(this);
-
-        if (savedInstanceState != null) {
-            restoreState(savedInstanceState);
-        } else {
-            final Bundle bundle = getActivity().getIntent().getExtras();
-            if (bundle != null) {
-                restoreState(bundle);
-            }
-        }
-        return view;
-    }
-
-    @Override
-    public void onClick(final View view) {
-        final ResearchLogger researchLogger = ResearchLogger.getInstance();
-        if (view == mIncludingUserRecordingCheckBox) {
-            if (mIncludingUserRecordingCheckBox.isChecked()) {
-                final Bundle bundle = new Bundle();
-                onSaveInstanceState(bundle);
-
-                // Let the user make a recording
-                getActivity().finish();
-
-                researchLogger.setFeedbackDialogBundle(bundle);
-                researchLogger.onLeavingSendFeedbackDialog();
-                researchLogger.startRecording();
-            }
-        } else if (view == mSendButton) {
-            final Editable editable = mEditText.getText();
-            final String feedbackContents = editable.toString();
-            if (TextUtils.isEmpty(feedbackContents)) {
-                Toast.makeText(getActivity(),
-                        R.string.research_feedback_empty_feedback_error_message,
-                        Toast.LENGTH_LONG).show();
-            } else {
-                final boolean isIncludingAccountName = mIncludingAccountNameCheckBox.isChecked();
-                researchLogger.sendFeedback(feedbackContents, false /* isIncludingHistory */,
-                        isIncludingAccountName, mIncludingUserRecordingCheckBox.isChecked());
-                getActivity().finish();
-                researchLogger.setFeedbackDialogBundle(null);
-                researchLogger.onLeavingSendFeedbackDialog();
-            }
-        } else if (view == mCancelButton) {
-            Log.d(TAG, "Finishing");
-            getActivity().finish();
-            researchLogger.setFeedbackDialogBundle(null);
-            researchLogger.onLeavingSendFeedbackDialog();
-        } else {
-            Log.e(TAG, "Unknown view passed to FeedbackFragment.onClick()");
-        }
-    }
-
-    @Override
-    public void onSaveInstanceState(final Bundle bundle) {
-        final String savedFeedbackString = mEditText.getText().toString();
-
-        bundle.putString(KEY_FEEDBACK_STRING, savedFeedbackString);
-        bundle.putBoolean(KEY_INCLUDE_ACCOUNT_NAME, mIncludingAccountNameCheckBox.isChecked());
-        bundle.putBoolean(KEY_HAS_USER_RECORDING, mIncludingUserRecordingCheckBox.isChecked());
-    }
-
-    private void restoreState(final Bundle bundle) {
-        mEditText.setText(bundle.getString(KEY_FEEDBACK_STRING));
-        mIncludingAccountNameCheckBox.setChecked(bundle.getBoolean(KEY_INCLUDE_ACCOUNT_NAME));
-        mIncludingUserRecordingCheckBox.setChecked(bundle.getBoolean(KEY_HAS_USER_RECORDING));
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/FeedbackLayout.java b/java/src/com/android/inputmethod/research/FeedbackLayout.java
deleted file mode 100644
index d283d14..0000000
--- a/java/src/com/android/inputmethod/research/FeedbackLayout.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.app.Activity;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.widget.LinearLayout;
-
-public class FeedbackLayout extends LinearLayout {
-    private Activity mActivity;
-
-    public FeedbackLayout(Context context) {
-        super(context);
-    }
-
-    public FeedbackLayout(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public FeedbackLayout(Context context, AttributeSet attrs, int defstyle) {
-        super(context, attrs, defstyle);
-    }
-
-    public void setActivity(Activity activity) {
-        mActivity = activity;
-    }
-
-    @Override
-    public boolean dispatchKeyEventPreIme(KeyEvent event) {
-        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
-            KeyEvent.DispatcherState state = getKeyDispatcherState();
-            if (state != null) {
-                if (event.getAction() == KeyEvent.ACTION_DOWN
-                        && event.getRepeatCount() == 0) {
-                    state.startTracking(event, this);
-                    return true;
-                } else if (event.getAction() == KeyEvent.ACTION_UP
-                        && !event.isCanceled() && state.isTracking(event)) {
-                    mActivity.onBackPressed();
-                    return true;
-                }
-            }
-        }
-        return super.dispatchKeyEventPreIme(event);
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/FeedbackLog.java b/java/src/com/android/inputmethod/research/FeedbackLog.java
deleted file mode 100644
index 5af194c..0000000
--- a/java/src/com/android/inputmethod/research/FeedbackLog.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2013 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.research;
-
-import android.content.Context;
-
-import java.io.File;
-
-public class FeedbackLog extends ResearchLog {
-    public FeedbackLog(final File outputFile, final Context context) {
-        super(outputFile, context);
-    }
-
-    @Override
-    public boolean isFeedbackLog() {
-        return true;
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/FixedLogBuffer.java b/java/src/com/android/inputmethod/research/FixedLogBuffer.java
deleted file mode 100644
index 2100156..0000000
--- a/java/src/com/android/inputmethod/research/FixedLogBuffer.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-
-/**
- * A buffer that holds a fixed number of LogUnits.
- *
- * LogUnits are added in and shifted out in temporal order.  Only a subset of the LogUnits are
- * actual words; the other LogUnits do not count toward the word limit.  Once the buffer reaches
- * capacity, adding another LogUnit that is a word evicts the oldest LogUnits out one at a time to
- * stay under the capacity limit.
- *
- * This variant of a LogBuffer has a limited memory footprint because of its limited size.  This
- * makes it useful, for example, for recording a window of the user's most recent actions in case
- * they want to report an observed error that they do not know how to reproduce.
- */
-public class FixedLogBuffer extends LogBuffer {
-    /* package for test */ int mWordCapacity;
-    // The number of members of mLogUnits that are actual words.
-    private int mNumActualWords;
-
-    /**
-     * Create a new LogBuffer that can hold a fixed number of LogUnits that are words (and
-     * unlimited number of non-word LogUnits), and that outputs its result to a researchLog.
-     *
-     * @param wordCapacity maximum number of words
-     */
-    public FixedLogBuffer(final int wordCapacity) {
-        super();
-        if (wordCapacity <= 0) {
-            throw new IllegalArgumentException("wordCapacity must be 1 or greater.");
-        }
-        mWordCapacity = wordCapacity;
-        mNumActualWords = 0;
-    }
-
-    /**
-     * Adds a new LogUnit to the front of the LIFO queue, evicting existing LogUnit's
-     * (oldest first) if word capacity is reached.
-     */
-    @Override
-    public void shiftIn(final LogUnit newLogUnit) {
-        if (!newLogUnit.hasOneOrMoreWords()) {
-            // This LogUnit doesn't contain any word, so it doesn't count toward the word-limit.
-            super.shiftIn(newLogUnit);
-            return;
-        }
-        final int numWordsIncoming = newLogUnit.getNumWords();
-        if (mNumActualWords >= mWordCapacity) {
-            // Give subclass a chance to handle the buffer full condition by shifting out logUnits.
-            // TODO: Tell onBufferFull() how much space it needs to make to avoid forced eviction.
-            onBufferFull();
-            // If still full, evict.
-            if (mNumActualWords >= mWordCapacity) {
-                shiftOutWords(numWordsIncoming);
-            }
-        }
-        super.shiftIn(newLogUnit);
-        mNumActualWords += numWordsIncoming;
-    }
-
-    @Override
-    public LogUnit unshiftIn() {
-        final LogUnit logUnit = super.unshiftIn();
-        if (logUnit != null && logUnit.hasOneOrMoreWords()) {
-            mNumActualWords -= logUnit.getNumWords();
-        }
-        return logUnit;
-    }
-
-    public int getNumWords() {
-        return mNumActualWords;
-    }
-
-    /**
-     * Removes all LogUnits from the buffer without calling onShiftOut().
-     */
-    @Override
-    public void clear() {
-        super.clear();
-        mNumActualWords = 0;
-    }
-
-    /**
-     * Called when the buffer has just shifted in one more word than its maximum, and its about to
-     * shift out LogUnits to bring it back down to the maximum.
-     *
-     * Base class does nothing; subclasses may override if they want to record non-privacy sensitive
-     * events that fall off the end.
-     */
-    protected void onBufferFull() {
-    }
-
-    @Override
-    public LogUnit shiftOut() {
-        final LogUnit logUnit = super.shiftOut();
-        if (logUnit != null && logUnit.hasOneOrMoreWords()) {
-            mNumActualWords -= logUnit.getNumWords();
-        }
-        return logUnit;
-    }
-
-    /**
-     * Remove LogUnits from the front of the LogBuffer until {@code numWords} have been removed.
-     *
-     * If there are less than {@code numWords} in the buffer, shifts out all {@code LogUnit}s.
-     *
-     * @param numWords the minimum number of words in {@link LogUnit}s to shift out
-     * @return the number of actual words LogUnit}s shifted out
-     */
-    protected int shiftOutWords(final int numWords) {
-        int numWordsShiftedOut = 0;
-        do {
-            final LogUnit logUnit = shiftOut();
-            if (logUnit == null) break;
-            numWordsShiftedOut += logUnit.getNumWords();
-        } while (numWordsShiftedOut < numWords);
-        return numWordsShiftedOut;
-    }
-
-    public void shiftOutAll() {
-        final LinkedList<LogUnit> logUnits = getLogUnits();
-        while (!logUnits.isEmpty()) {
-            shiftOut();
-        }
-        mNumActualWords = 0;
-    }
-
-    /**
-     * Returns a list of {@link LogUnit}s at the front of the buffer that have words associated with
-     * them.
-     *
-     * There will be no more than {@code n} words in the returned list.  So if 2 words are
-     * requested, and the first LogUnit has 3 words, it is not returned.  If 2 words are requested,
-     * and the first LogUnit has only 1 word, and the next LogUnit 2 words, only the first LogUnit
-     * is returned.  If the first LogUnit has no words associated with it, and the second LogUnit
-     * has three words, then only the first LogUnit (which has no associated words) is returned.  If
-     * there are not enough LogUnits in the buffer to meet the word requirement, then all LogUnits
-     * will be returned.
-     *
-     * @param n The maximum number of {@link LogUnit}s with words to return.
-     * @return The list of the {@link LogUnit}s containing the first n words
-     */
-    public ArrayList<LogUnit> peekAtFirstNWords(int n) {
-        final LinkedList<LogUnit> logUnits = getLogUnits();
-        // Allocate space for n*2 logUnits.  There will be at least n, one for each word, and
-        // there may be additional for punctuation, between-word commands, etc.  This should be
-        // enough that reallocation won't be necessary.
-        final ArrayList<LogUnit> resultList = new ArrayList<>(n * 2);
-        for (final LogUnit logUnit : logUnits) {
-            n -= logUnit.getNumWords();
-            if (n < 0) break;
-            resultList.add(logUnit);
-        }
-        return resultList;
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/JsonUtils.java b/java/src/com/android/inputmethod/research/JsonUtils.java
deleted file mode 100644
index 63c08e8..0000000
--- a/java/src/com/android/inputmethod/research/JsonUtils.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.content.SharedPreferences;
-import android.util.JsonWriter;
-import android.view.MotionEvent;
-import android.view.inputmethod.CompletionInfo;
-
-import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-
-import java.io.IOException;
-import java.util.Map;
-
-/**
- * Routines for mapping classes and variables to JSON representations for logging.
- */
-/* package */ class JsonUtils {
-    private JsonUtils() {
-        // This utility class is not publicly instantiable.
-    }
-
-    /* package */ static void writeJson(final CompletionInfo[] ci, final JsonWriter jsonWriter)
-            throws IOException {
-        jsonWriter.beginArray();
-        for (int j = 0; j < ci.length; j++) {
-            jsonWriter.value(ci[j].toString());
-        }
-        jsonWriter.endArray();
-    }
-
-    /* package */ static void writeJson(final SharedPreferences prefs, final JsonWriter jsonWriter)
-            throws IOException {
-        jsonWriter.beginObject();
-        for (Map.Entry<String,?> entry : prefs.getAll().entrySet()) {
-            jsonWriter.name(entry.getKey());
-            final Object innerValue = entry.getValue();
-            if (innerValue == null) {
-                jsonWriter.nullValue();
-            } else if (innerValue instanceof Boolean) {
-                jsonWriter.value((Boolean) innerValue);
-            } else if (innerValue instanceof Number) {
-                jsonWriter.value((Number) innerValue);
-            } else {
-                jsonWriter.value(innerValue.toString());
-            }
-        }
-        jsonWriter.endObject();
-    }
-
-    /* package */ static void writeJson(final Key[] keys, final JsonWriter jsonWriter)
-            throws IOException {
-        jsonWriter.beginArray();
-        for (Key key : keys) {
-            writeJson(key, jsonWriter);
-        }
-        jsonWriter.endArray();
-    }
-
-    private static void writeJson(final Key key, final JsonWriter jsonWriter) throws IOException {
-        jsonWriter.beginObject();
-        jsonWriter.name("code").value(key.getCode());
-        jsonWriter.name("altCode").value(key.getAltCode());
-        jsonWriter.name("x").value(key.getX());
-        jsonWriter.name("y").value(key.getY());
-        jsonWriter.name("w").value(key.getWidth());
-        jsonWriter.name("h").value(key.getHeight());
-        jsonWriter.endObject();
-    }
-
-    /* package */ static void writeJson(final SuggestedWords words, final JsonWriter jsonWriter)
-            throws IOException {
-        jsonWriter.beginObject();
-        jsonWriter.name("typedWordValid").value(words.mTypedWordValid);
-        jsonWriter.name("willAutoCorrect")
-                .value(words.mWillAutoCorrect);
-        jsonWriter.name("isPunctuationSuggestions")
-                .value(words.isPunctuationSuggestions());
-        jsonWriter.name("isObsoleteSuggestions").value(words.mIsObsoleteSuggestions);
-        jsonWriter.name("isPrediction").value(words.mIsPrediction);
-        jsonWriter.name("suggestedWords");
-        jsonWriter.beginArray();
-        final int size = words.size();
-        for (int j = 0; j < size; j++) {
-            final SuggestedWordInfo wordInfo = words.getInfo(j);
-            jsonWriter.beginObject();
-            jsonWriter.name("word").value(wordInfo.toString());
-            jsonWriter.name("score").value(wordInfo.mScore);
-            jsonWriter.name("kind").value(wordInfo.getKind());
-            jsonWriter.name("sourceDict").value(wordInfo.mSourceDict.mDictType);
-            jsonWriter.endObject();
-        }
-        jsonWriter.endArray();
-        jsonWriter.endObject();
-    }
-
-    /* package */ static void writeJson(final MotionEvent me, final JsonWriter jsonWriter)
-            throws IOException {
-        jsonWriter.beginObject();
-        jsonWriter.name("pointerIds");
-        jsonWriter.beginArray();
-        final int pointerCount = me.getPointerCount();
-        for (int index = 0; index < pointerCount; index++) {
-            jsonWriter.value(me.getPointerId(index));
-        }
-        jsonWriter.endArray();
-
-        jsonWriter.name("xyt");
-        jsonWriter.beginArray();
-        final int historicalSize = me.getHistorySize();
-        for (int index = 0; index < historicalSize; index++) {
-            jsonWriter.beginObject();
-            jsonWriter.name("t");
-            jsonWriter.value(me.getHistoricalEventTime(index));
-            jsonWriter.name("d");
-            jsonWriter.beginArray();
-            for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
-                jsonWriter.beginObject();
-                jsonWriter.name("x");
-                jsonWriter.value(me.getHistoricalX(pointerIndex, index));
-                jsonWriter.name("y");
-                jsonWriter.value(me.getHistoricalY(pointerIndex, index));
-                jsonWriter.endObject();
-            }
-            jsonWriter.endArray();
-            jsonWriter.endObject();
-        }
-        jsonWriter.beginObject();
-        jsonWriter.name("t");
-        jsonWriter.value(me.getEventTime());
-        jsonWriter.name("d");
-        jsonWriter.beginArray();
-        for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
-            jsonWriter.beginObject();
-            jsonWriter.name("x");
-            jsonWriter.value(me.getX(pointerIndex));
-            jsonWriter.name("y");
-            jsonWriter.value(me.getY(pointerIndex));
-            jsonWriter.endObject();
-        }
-        jsonWriter.endArray();
-        jsonWriter.endObject();
-        jsonWriter.endArray();
-        jsonWriter.endObject();
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/LogBuffer.java b/java/src/com/android/inputmethod/research/LogBuffer.java
deleted file mode 100644
index 0d9c357..0000000
--- a/java/src/com/android/inputmethod/research/LogBuffer.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import java.util.LinkedList;
-
-/**
- * Maintain a FIFO queue of LogUnits.
- *
- * This class provides an unbounded queue.  This is useful when the user is aware that their actions
- * are being recorded, such as when they are trying to reproduce a bug.  In this case, there should
- * not be artificial restrictions on how many events that can be saved.
- */
-public class LogBuffer {
-    // TODO: Gracefully handle situations in which this LogBuffer is consuming too much memory.
-    // This may happen, for example, if the user has forgotten that data is being logged.
-    private final LinkedList<LogUnit> mLogUnits;
-
-    public LogBuffer() {
-        mLogUnits = new LinkedList<>();
-    }
-
-    protected LinkedList<LogUnit> getLogUnits() {
-        return mLogUnits;
-    }
-
-    public void clear() {
-        mLogUnits.clear();
-    }
-
-    public void shiftIn(final LogUnit logUnit) {
-        mLogUnits.add(logUnit);
-    }
-
-    public LogUnit unshiftIn() {
-        if (mLogUnits.isEmpty()) {
-            return null;
-        }
-        return mLogUnits.removeLast();
-    }
-
-    public LogUnit peekLastLogUnit() {
-        if (mLogUnits.isEmpty()) {
-            return null;
-        }
-        return mLogUnits.peekLast();
-    }
-
-    public boolean isEmpty() {
-        return mLogUnits.isEmpty();
-    }
-
-    public LogUnit shiftOut() {
-        if (isEmpty()) {
-            return null;
-        }
-        return mLogUnits.removeFirst();
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/LogStatement.java b/java/src/com/android/inputmethod/research/LogStatement.java
deleted file mode 100644
index 06b918a..0000000
--- a/java/src/com/android/inputmethod/research/LogStatement.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2013 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.research;
-
-import android.content.SharedPreferences;
-import android.util.JsonWriter;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.inputmethod.CompletionInfo;
-
-import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.define.ProductionFlag;
-
-import java.io.IOException;
-
-/**
- * A template for typed information stored in the logs.
- *
- * A LogStatement contains a name, keys, and flags about whether the {@code Object[] values}
- * associated with the {@code String[] keys} are likely to reveal information about the user.  The
- * actual values are stored separately.
- */
-public class LogStatement {
-    private static final String TAG = LogStatement.class.getSimpleName();
-    private static final boolean DEBUG = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-
-    // Constants for particular statements
-    public static final String TYPE_POINTER_TRACKER_CALL_LISTENER_ON_CODE_INPUT =
-            "PointerTrackerCallListenerOnCodeInput";
-    public static final String KEY_CODE = "code";
-    public static final String VALUE_RESEARCH = "research";
-    public static final String TYPE_MAIN_KEYBOARD_VIEW_ON_LONG_PRESS =
-            "MainKeyboardViewOnLongPress";
-    public static final String ACTION = "action";
-    public static final String VALUE_DOWN = "DOWN";
-    public static final String TYPE_MOTION_EVENT = "MotionEvent";
-    public static final String KEY_IS_LOGGING_RELATED = "isLoggingRelated";
-
-    // Keys for internal key/value pairs
-    private static final String CURRENT_TIME_KEY = "_ct";
-    private static final String UPTIME_KEY = "_ut";
-    private static final String EVENT_TYPE_KEY = "_ty";
-
-    // Name specifying the LogStatement type.
-    private final String mType;
-
-    // mIsPotentiallyPrivate indicates that event contains potentially private information.  If
-    // the word that this event is a part of is determined to be privacy-sensitive, then this
-    // event should not be included in the output log.  The system waits to output until the
-    // containing word is known.
-    private final boolean mIsPotentiallyPrivate;
-
-    // mIsPotentiallyRevealing indicates that this statement may disclose details about other
-    // words typed in other LogUnits.  This can happen if the user is not inserting spaces, and
-    // data from Suggestions and/or Composing text reveals the entire "megaword".  For example,
-    // say the user is typing "for the win", and the system wants to record the bigram "the
-    // win".  If the user types "forthe", omitting the space, the system will give "for the" as
-    // a suggestion.  If the user accepts the autocorrection, the suggestion for "for the" is
-    // included in the log for the word "the", disclosing that the previous word had been "for".
-    // For now, we simply do not include this data when logging part of a "megaword".
-    private final boolean mIsPotentiallyRevealing;
-
-    // mKeys stores the names that are the attributes in the output json objects
-    private final String[] mKeys;
-    private static final String[] NULL_KEYS = new String[0];
-
-    LogStatement(final String name, final boolean isPotentiallyPrivate,
-            final boolean isPotentiallyRevealing, final String... keys) {
-        mType = name;
-        mIsPotentiallyPrivate = isPotentiallyPrivate;
-        mIsPotentiallyRevealing = isPotentiallyRevealing;
-        mKeys = (keys == null) ? NULL_KEYS : keys;
-    }
-
-    public String getType() {
-        return mType;
-    }
-
-    public boolean isPotentiallyPrivate() {
-        return mIsPotentiallyPrivate;
-    }
-
-    public boolean isPotentiallyRevealing() {
-        return mIsPotentiallyRevealing;
-    }
-
-    public String[] getKeys() {
-        return mKeys;
-    }
-
-    /**
-     * Utility function to test whether a key-value pair exists in a LogStatement.
-     *
-     * A LogStatement is really just a template -- it does not contain the values, only the
-     * keys.  So the values must be passed in as an argument.
-     *
-     * @param queryKey the String that is tested by {@code String.equals()} to the keys in the
-     * LogStatement
-     * @param queryValue an Object that must be {@code Object.equals()} to the key's corresponding
-     * value in the {@code values} array
-     * @param values the values corresponding to mKeys
-     *
-     * @returns {@true} if {@code queryKey} exists in the keys for this LogStatement, and {@code
-     * queryValue} matches the corresponding value in {@code values}
-     *
-     * @throws IllegalArgumentException if {@code values.length} is not equal to keys().length()
-     */
-    public boolean containsKeyValuePair(final String queryKey, final Object queryValue,
-            final Object[] values) {
-        if (mKeys.length != values.length) {
-            throw new IllegalArgumentException("Mismatched number of keys and values.");
-        }
-        final int length = mKeys.length;
-        for (int i = 0; i < length; i++) {
-            if (mKeys[i].equals(queryKey) && values[i].equals(queryValue)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Utility function to set a value in a LogStatement.
-     *
-     * A LogStatement is really just a template -- it does not contain the values, only the
-     * keys.  So the values must be passed in as an argument.
-     *
-     * @param queryKey the String that is tested by {@code String.equals()} to the keys in the
-     * LogStatement
-     * @param values the array of values corresponding to mKeys
-     * @param newValue the replacement value to go into the {@code values} array
-     *
-     * @returns {@true} if the key exists and the value was successfully set, {@false} otherwise
-     *
-     * @throws IllegalArgumentException if {@code values.length} is not equal to keys().length()
-     */
-    public boolean setValue(final String queryKey, final Object[] values, final Object newValue) {
-        if (mKeys.length != values.length) {
-            throw new IllegalArgumentException("Mismatched number of keys and values.");
-        }
-        final int length = mKeys.length;
-        for (int i = 0; i < length; i++) {
-            if (mKeys[i].equals(queryKey)) {
-                values[i] = newValue;
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Write the contents out through jsonWriter.
-     *
-     * The JsonWriter class must have already had {@code JsonWriter.beginArray} called on it.
-     *
-     * Note that this method is not thread safe for the same jsonWriter.  Callers must ensure
-     * thread safety.
-     */
-    public boolean outputToLocked(final JsonWriter jsonWriter, final Long time,
-            final Object... values) {
-        if (DEBUG) {
-            if (mKeys.length != values.length) {
-                Log.d(TAG, "Key and Value list sizes do not match. " + mType);
-            }
-        }
-        try {
-            jsonWriter.beginObject();
-            jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis());
-            jsonWriter.name(UPTIME_KEY).value(time);
-            jsonWriter.name(EVENT_TYPE_KEY).value(mType);
-            final int length = values.length;
-            for (int i = 0; i < length; i++) {
-                jsonWriter.name(mKeys[i]);
-                final Object value = values[i];
-                if (value instanceof CharSequence) {
-                    jsonWriter.value(value.toString());
-                } else if (value instanceof Number) {
-                    jsonWriter.value((Number) value);
-                } else if (value instanceof Boolean) {
-                    jsonWriter.value((Boolean) value);
-                } else if (value instanceof CompletionInfo[]) {
-                    JsonUtils.writeJson((CompletionInfo[]) value, jsonWriter);
-                } else if (value instanceof SharedPreferences) {
-                    JsonUtils.writeJson((SharedPreferences) value, jsonWriter);
-                } else if (value instanceof Key[]) {
-                    JsonUtils.writeJson((Key[]) value, jsonWriter);
-                } else if (value instanceof SuggestedWords) {
-                    JsonUtils.writeJson((SuggestedWords) value, jsonWriter);
-                } else if (value instanceof MotionEvent) {
-                    JsonUtils.writeJson((MotionEvent) value, jsonWriter);
-                } else if (value == null) {
-                    jsonWriter.nullValue();
-                } else {
-                    if (DEBUG) {
-                        Log.w(TAG, "Unrecognized type to be logged: "
-                                + (value == null ? "<null>" : value.getClass().getName()));
-                    }
-                    jsonWriter.nullValue();
-                }
-            }
-            jsonWriter.endObject();
-        } catch (IOException e) {
-            e.printStackTrace();
-            Log.w(TAG, "Error in JsonWriter; skipping LogStatement");
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/LogUnit.java b/java/src/com/android/inputmethod/research/LogUnit.java
deleted file mode 100644
index 1750751..0000000
--- a/java/src/com/android/inputmethod/research/LogUnit.java
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.JsonWriter;
-import android.util.Log;
-
-import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import com.android.inputmethod.latin.define.ProductionFlag;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Pattern;
-
-/**
- * A group of log statements related to each other.
- *
- * A LogUnit is collection of LogStatements, each of which is generated by at a particular point
- * in the code.  (There is no LogStatement class; the data is stored across the instance variables
- * here.)  A single LogUnit's statements can correspond to all the calls made while in the same
- * composing region, or all the calls between committing the last composing region, and the first
- * character of the next composing region.
- *
- * Individual statements in a log may be marked as potentially private.  If so, then they are only
- * published to a ResearchLog if the ResearchLogger determines that publishing the entire LogUnit
- * will not violate the user's privacy.  Checks for this may include whether other LogUnits have
- * been published recently, or whether the LogUnit contains numbers, etc.
- */
-public class LogUnit {
-    private static final String TAG = LogUnit.class.getSimpleName();
-    private static final boolean DEBUG = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-
-    private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+");
-    private static final String[] EMPTY_STRING_ARRAY = new String[0];
-
-    private final ArrayList<LogStatement> mLogStatementList;
-    private final ArrayList<Object[]> mValuesList;
-    // Assume that mTimeList is sorted in increasing order.  Do not insert null values into
-    // mTimeList.
-    private final ArrayList<Long> mTimeList;
-    // Words that this LogUnit generates.  Should be null if the data in the LogUnit does not
-    // generate a genuine word (i.e. separators alone do not count as a word).  Should never be
-    // empty.  Note that if the user types spaces explicitly, then normally mWords should contain
-    // only a single word; it will only contain space-separate multiple words if the user does not
-    // enter a space, and the system enters one automatically.
-    private String mWords;
-    private String[] mWordArray = EMPTY_STRING_ARRAY;
-    private boolean mMayContainDigit;
-    private boolean mIsPartOfMegaword;
-    private boolean mContainsUserDeletions;
-
-    // mCorrectionType indicates whether the word was corrected at all, and if so, the nature of the
-    // correction.
-    private int mCorrectionType;
-    // LogUnits start in this state.  If a word is entered without being corrected, it will have
-    // this CorrectiontType.
-    public static final int CORRECTIONTYPE_NO_CORRECTION = 0;
-    // The LogUnit was corrected manually by the user in an unspecified way.
-    public static final int CORRECTIONTYPE_CORRECTION = 1;
-    // The LogUnit was corrected manually by the user to a word not in the list of suggestions of
-    // the first word typed here.  (Note: this is a heuristic value, it may be incorrect, for
-    // example, if the user repositions the cursor).
-    public static final int CORRECTIONTYPE_DIFFERENT_WORD = 2;
-    // The LogUnit was corrected manually by the user to a word that was in the list of suggestions
-    // of the first word typed here.  (Again, a heuristic).  It is probably a typo correction.
-    public static final int CORRECTIONTYPE_TYPO = 3;
-    // TODO: Rather than just tracking the current state, keep a historical record of the LogUnit's
-    // state and statistics.  This should include how many times it has been corrected, whether
-    // other LogUnit edits were done between edits to this LogUnit, etc.  Also track when a LogUnit
-    // previously contained a word, but was corrected to empty (because it was deleted, and there is
-    // no known replacement).
-
-    private SuggestedWords mSuggestedWords;
-
-    public LogUnit() {
-        mLogStatementList = new ArrayList<>();
-        mValuesList = new ArrayList<>();
-        mTimeList = new ArrayList<>();
-        mIsPartOfMegaword = false;
-        mCorrectionType = CORRECTIONTYPE_NO_CORRECTION;
-        mSuggestedWords = null;
-    }
-
-    private LogUnit(final ArrayList<LogStatement> logStatementList,
-            final ArrayList<Object[]> valuesList,
-            final ArrayList<Long> timeList,
-            final boolean isPartOfMegaword) {
-        mLogStatementList = logStatementList;
-        mValuesList = valuesList;
-        mTimeList = timeList;
-        mIsPartOfMegaword = isPartOfMegaword;
-        mCorrectionType = CORRECTIONTYPE_NO_CORRECTION;
-        mSuggestedWords = null;
-    }
-
-    private static final Object[] NULL_VALUES = new Object[0];
-    /**
-     * Adds a new log statement.  The time parameter in successive calls to this method must be
-     * monotonically increasing, or splitByTime() will not work.
-     */
-    public void addLogStatement(final LogStatement logStatement, final long time,
-            Object... values) {
-        if (values == null) {
-            values = NULL_VALUES;
-        }
-        mLogStatementList.add(logStatement);
-        mValuesList.add(values);
-        mTimeList.add(time);
-    }
-
-    /**
-     * Publish the contents of this LogUnit to {@code researchLog}.
-     *
-     * For each publishable {@code LogStatement}, invoke {@link LogStatement#outputToLocked}.
-     *
-     * @param researchLog where to publish the contents of this {@code LogUnit}
-     * @param canIncludePrivateData whether the private data in this {@code LogUnit} should be
-     * included
-     *
-     * @throws IOException if publication to the log file is not possible
-     */
-    public synchronized void publishTo(final ResearchLog researchLog,
-            final boolean canIncludePrivateData) throws IOException {
-        // Write out any logStatement that passes the privacy filter.
-        final int size = mLogStatementList.size();
-        if (size != 0) {
-            // Note that jsonWriter is only set to a non-null value if the logUnit start text is
-            // output and at least one logStatement is output.
-            JsonWriter jsonWriter = researchLog.getInitializedJsonWriterLocked();
-            outputLogUnitStart(jsonWriter, canIncludePrivateData);
-            for (int i = 0; i < size; i++) {
-                final LogStatement logStatement = mLogStatementList.get(i);
-                if (!canIncludePrivateData && logStatement.isPotentiallyPrivate()) {
-                    continue;
-                }
-                if (mIsPartOfMegaword && logStatement.isPotentiallyRevealing()) {
-                    continue;
-                }
-                logStatement.outputToLocked(jsonWriter, mTimeList.get(i), mValuesList.get(i));
-            }
-            outputLogUnitStop(jsonWriter);
-        }
-    }
-
-    private static final String WORD_KEY = "_wo";
-    private static final String NUM_WORDS_KEY = "_nw";
-    private static final String CORRECTION_TYPE_KEY = "_corType";
-    private static final String LOG_UNIT_BEGIN_KEY = "logUnitStart";
-    private static final String LOG_UNIT_END_KEY = "logUnitEnd";
-
-    final LogStatement LOGSTATEMENT_LOG_UNIT_BEGIN_WITH_PRIVATE_DATA =
-            new LogStatement(LOG_UNIT_BEGIN_KEY, false /* isPotentiallyPrivate */,
-                    false /* isPotentiallyRevealing */, WORD_KEY, CORRECTION_TYPE_KEY,
-                    NUM_WORDS_KEY);
-    final LogStatement LOGSTATEMENT_LOG_UNIT_BEGIN_WITHOUT_PRIVATE_DATA =
-            new LogStatement(LOG_UNIT_BEGIN_KEY, false /* isPotentiallyPrivate */,
-                    false /* isPotentiallyRevealing */, NUM_WORDS_KEY);
-    private void outputLogUnitStart(final JsonWriter jsonWriter,
-            final boolean canIncludePrivateData) {
-        final LogStatement logStatement;
-        if (canIncludePrivateData) {
-            LOGSTATEMENT_LOG_UNIT_BEGIN_WITH_PRIVATE_DATA.outputToLocked(jsonWriter,
-                    SystemClock.uptimeMillis(), getWordsAsString(), getCorrectionType(),
-                    getNumWords());
-        } else {
-            LOGSTATEMENT_LOG_UNIT_BEGIN_WITHOUT_PRIVATE_DATA.outputToLocked(jsonWriter,
-                    SystemClock.uptimeMillis(), getNumWords());
-        }
-    }
-
-    final LogStatement LOGSTATEMENT_LOG_UNIT_END =
-            new LogStatement(LOG_UNIT_END_KEY, false /* isPotentiallyPrivate */,
-                    false /* isPotentiallyRevealing */);
-    private void outputLogUnitStop(final JsonWriter jsonWriter) {
-        LOGSTATEMENT_LOG_UNIT_END.outputToLocked(jsonWriter, SystemClock.uptimeMillis());
-    }
-
-    /**
-     * Mark the current logUnit as containing data to generate {@code newWords}.
-     *
-     * If {@code setWord()} was previously called for this LogUnit, then the method will try to
-     * determine what kind of correction it is, and update its internal state of the correctionType
-     * accordingly.
-     *
-     * @param newWords The words this LogUnit generates.  Caller should not pass null or the empty
-     * string.
-     */
-    public void setWords(final String newWords) {
-        if (hasOneOrMoreWords()) {
-            // The word was already set once, and it is now being changed.  See if the new word
-            // is close to the old word.  If so, then the change is probably a typo correction.
-            // If not, the user may have decided to enter a different word, so flag it.
-            if (mSuggestedWords != null) {
-                if (isInSuggestedWords(newWords, mSuggestedWords)) {
-                    mCorrectionType = CORRECTIONTYPE_TYPO;
-                } else {
-                    mCorrectionType = CORRECTIONTYPE_DIFFERENT_WORD;
-                }
-            } else {
-                // No suggested words, so it's not clear whether it's a typo or different word.
-                // Mark it as a generic correction.
-                mCorrectionType = CORRECTIONTYPE_CORRECTION;
-            }
-        } else {
-            mCorrectionType = CORRECTIONTYPE_NO_CORRECTION;
-        }
-        mWords = newWords;
-
-        // Update mWordArray
-        mWordArray = (TextUtils.isEmpty(mWords)) ? EMPTY_STRING_ARRAY
-                : WHITESPACE_PATTERN.split(mWords);
-        if (mWordArray.length > 0 && TextUtils.isEmpty(mWordArray[0])) {
-            // Empty string at beginning of array.  Must have been whitespace at the start of the
-            // word.  Remove the empty string.
-            mWordArray = Arrays.copyOfRange(mWordArray, 1, mWordArray.length);
-        }
-    }
-
-    public String getWordsAsString() {
-        return mWords;
-    }
-
-    /**
-     * Retuns the words generated by the data in this LogUnit.
-     *
-     * The first word may be an empty string, if the data in the LogUnit started by generating
-     * whitespace.
-     *
-     * @return the array of words. an empty list of there are no words associated with this LogUnit.
-     */
-    public String[] getWordsAsStringArray() {
-        return mWordArray;
-    }
-
-    public boolean hasOneOrMoreWords() {
-        return mWordArray.length >= 1;
-    }
-
-    public int getNumWords() {
-        return mWordArray.length;
-    }
-
-    // TODO: Refactor to eliminate getter/setters
-    public void setMayContainDigit() {
-        mMayContainDigit = true;
-    }
-
-    // TODO: Refactor to eliminate getter/setters
-    public boolean mayContainDigit() {
-        return mMayContainDigit;
-    }
-
-    // TODO: Refactor to eliminate getter/setters
-    public void setContainsUserDeletions() {
-        mContainsUserDeletions = true;
-    }
-
-    // TODO: Refactor to eliminate getter/setters
-    public boolean containsUserDeletions() {
-        return mContainsUserDeletions;
-    }
-
-    // TODO: Refactor to eliminate getter/setters
-    public void setCorrectionType(final int correctionType) {
-        mCorrectionType = correctionType;
-    }
-
-    // TODO: Refactor to eliminate getter/setters
-    public int getCorrectionType() {
-        return mCorrectionType;
-    }
-
-    public boolean isEmpty() {
-        return mLogStatementList.isEmpty();
-    }
-
-    /**
-     * Split this logUnit, with all events before maxTime staying in the current logUnit, and all
-     * events after maxTime going into a new LogUnit that is returned.
-     */
-    public LogUnit splitByTime(final long maxTime) {
-        // Assume that mTimeList is in sorted order.
-        final int length = mTimeList.size();
-        // TODO: find time by binary search, e.g. using Collections#binarySearch()
-        for (int index = 0; index < length; index++) {
-            if (mTimeList.get(index) > maxTime) {
-                final List<LogStatement> laterLogStatements =
-                        mLogStatementList.subList(index, length);
-                final List<Object[]> laterValues = mValuesList.subList(index, length);
-                final List<Long> laterTimes = mTimeList.subList(index, length);
-
-                // Create the LogUnit containing the later logStatements and associated data.
-                final LogUnit newLogUnit = new LogUnit(
-                        new ArrayList<>(laterLogStatements),
-                        new ArrayList<>(laterValues),
-                        new ArrayList<>(laterTimes),
-                        true /* isPartOfMegaword */);
-                newLogUnit.mWords = null;
-                newLogUnit.mMayContainDigit = mMayContainDigit;
-                newLogUnit.mContainsUserDeletions = mContainsUserDeletions;
-
-                // Purge the logStatements and associated data from this LogUnit.
-                laterLogStatements.clear();
-                laterValues.clear();
-                laterTimes.clear();
-                mIsPartOfMegaword = true;
-
-                return newLogUnit;
-            }
-        }
-        return new LogUnit();
-    }
-
-    public void append(final LogUnit logUnit) {
-        mLogStatementList.addAll(logUnit.mLogStatementList);
-        mValuesList.addAll(logUnit.mValuesList);
-        mTimeList.addAll(logUnit.mTimeList);
-        mWords = null;
-        if (logUnit.mWords != null) {
-            setWords(logUnit.mWords);
-        }
-        mMayContainDigit = mMayContainDigit || logUnit.mMayContainDigit;
-        mContainsUserDeletions = mContainsUserDeletions || logUnit.mContainsUserDeletions;
-        mIsPartOfMegaword = false;
-    }
-
-    public SuggestedWords getSuggestions() {
-        return mSuggestedWords;
-    }
-
-    /**
-     * Initialize the suggestions.
-     *
-     * Once set to a non-null value, the suggestions may not be changed again.  This is to keep
-     * track of the list of words that are close to the user's initial effort to type the word.
-     * Only words that are close to the initial effort are considered typo corrections.
-     */
-    public void initializeSuggestions(final SuggestedWords suggestedWords) {
-        if (mSuggestedWords == null) {
-            mSuggestedWords = suggestedWords;
-        }
-    }
-
-    private static boolean isInSuggestedWords(final String queryWord,
-            final SuggestedWords suggestedWords) {
-        if (TextUtils.isEmpty(queryWord)) {
-            return false;
-        }
-        final int size = suggestedWords.size();
-        for (int i = 0; i < size; i++) {
-            final SuggestedWordInfo wordInfo = suggestedWords.getInfo(i);
-            if (queryWord.equals(wordInfo.mWord)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Remove data associated with selecting the Research button.
-     *
-     * A LogUnit will capture all user interactions with the IME, including the "meta-interactions"
-     * of using the Research button to control the logging (e.g. by starting and stopping recording
-     * of a test case).  Because meta-interactions should not be part of the normal log, calling
-     * this method will set a field in the LogStatements of the motion events to indiciate that
-     * they should be disregarded.
-     *
-     * This implementation assumes that the data recorded by the meta-interaction takes the
-     * form of all events following the first MotionEvent.ACTION_DOWN before the first long-press
-     * before the last onCodeEvent containing a code matching {@code LogStatement.VALUE_RESEARCH}.
-     *
-     * @returns true if data was removed
-     */
-    public boolean removeResearchButtonInvocation() {
-        // This method is designed to be idempotent.
-
-        // First, find last invocation of "research" key
-        final int indexOfLastResearchKey = findLastIndexContainingKeyValue(
-                LogStatement.TYPE_POINTER_TRACKER_CALL_LISTENER_ON_CODE_INPUT,
-                LogStatement.KEY_CODE, LogStatement.VALUE_RESEARCH);
-        if (indexOfLastResearchKey < 0) {
-            // Could not find invocation of "research" key.  Leave log as is.
-            if (DEBUG) {
-                Log.d(TAG, "Could not find research key");
-            }
-            return false;
-        }
-
-        // Look for the long press that started the invocation of the research key code input.
-        final int indexOfLastLongPressBeforeResearchKey =
-                findLastIndexBefore(LogStatement.TYPE_MAIN_KEYBOARD_VIEW_ON_LONG_PRESS,
-                        indexOfLastResearchKey);
-
-        // Look for DOWN event preceding the long press
-        final int indexOfLastDownEventBeforeLongPress =
-                findLastIndexContainingKeyValueBefore(LogStatement.TYPE_MOTION_EVENT,
-                        LogStatement.ACTION, LogStatement.VALUE_DOWN,
-                        indexOfLastLongPressBeforeResearchKey);
-
-        // Flag all LatinKeyboardViewProcessMotionEvents from the DOWN event to the research key as
-        // logging-related
-        final int startingIndex = indexOfLastDownEventBeforeLongPress == -1 ? 0
-                : indexOfLastDownEventBeforeLongPress;
-        for (int index = startingIndex; index < indexOfLastResearchKey; index++) {
-            final LogStatement logStatement = mLogStatementList.get(index);
-            final String type = logStatement.getType();
-            final Object[] values = mValuesList.get(index);
-            if (type.equals(LogStatement.TYPE_MOTION_EVENT)) {
-                logStatement.setValue(LogStatement.KEY_IS_LOGGING_RELATED, values, true);
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Find the index of the last LogStatement before {@code startingIndex} of type {@code type}.
-     *
-     * @param queryType a String that must be {@code String.equals()} to the LogStatement type
-     * @param startingIndex the index to start the backward search from.  Must be less than the
-     * length of mLogStatementList, or an IndexOutOfBoundsException is thrown.  Can be negative,
-     * in which case -1 is returned.
-     *
-     * @return The index of the last LogStatement, -1 if none exists.
-     */
-    private int findLastIndexBefore(final String queryType, final int startingIndex) {
-        return findLastIndexContainingKeyValueBefore(queryType, null, null, startingIndex);
-    }
-
-    /**
-     * Find the index of the last LogStatement before {@code startingIndex} of type {@code type}
-     * containing the given key-value pair.
-     *
-     * @param queryType a String that must be {@code String.equals()} to the LogStatement type
-     * @param queryKey a String that must be {@code String.equals()} to a key in the LogStatement
-     * @param queryValue an Object that must be {@code String.equals()} to the key's corresponding
-     * value
-     *
-     * @return The index of the last LogStatement, -1 if none exists.
-     */
-    private int findLastIndexContainingKeyValue(final String queryType, final String queryKey,
-            final Object queryValue) {
-        return findLastIndexContainingKeyValueBefore(queryType, queryKey, queryValue,
-                mLogStatementList.size() - 1);
-    }
-
-    /**
-     * Find the index of the last LogStatement before {@code startingIndex} of type {@code type}
-     * containing the given key-value pair.
-     *
-     * @param queryType a String that must be {@code String.equals()} to the LogStatement type
-     * @param queryKey a String that must be {@code String.equals()} to a key in the LogStatement
-     * @param queryValue an Object that must be {@code String.equals()} to the key's corresponding
-     * value
-     * @param startingIndex the index to start the backward search from.  Must be less than the
-     * length of mLogStatementList, or an IndexOutOfBoundsException is thrown.  Can be negative,
-     * in which case -1 is returned.
-     *
-     * @return The index of the last LogStatement, -1 if none exists.
-     */
-    private int findLastIndexContainingKeyValueBefore(final String queryType, final String queryKey,
-            final Object queryValue, final int startingIndex) {
-        if (startingIndex < 0) {
-            return -1;
-        }
-        for (int index = startingIndex; index >= 0; index--) {
-            final LogStatement logStatement = mLogStatementList.get(index);
-            final String type = logStatement.getType();
-            if (type.equals(queryType) && (queryKey == null
-                    || logStatement.containsKeyValuePair(queryKey, queryValue,
-                            mValuesList.get(index)))) {
-                return index;
-            }
-        }
-        return -1;
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/LoggingUtils.java b/java/src/com/android/inputmethod/research/LoggingUtils.java
deleted file mode 100644
index 1261d67..0000000
--- a/java/src/com/android/inputmethod/research/LoggingUtils.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2013 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.research;
-
-import android.view.MotionEvent;
-
-/* package */ class LoggingUtils {
-    private LoggingUtils() {
-        // This utility class is not publicly instantiable.
-    }
-
-    /* package */ static String getMotionEventActionTypeString(final int actionType) {
-        switch (actionType) {
-        case MotionEvent.ACTION_CANCEL: return "CANCEL";
-        case MotionEvent.ACTION_UP: return "UP";
-        case MotionEvent.ACTION_DOWN: return "DOWN";
-        case MotionEvent.ACTION_POINTER_UP: return "POINTER_UP";
-        case MotionEvent.ACTION_POINTER_DOWN: return "POINTER_DOWN";
-        case MotionEvent.ACTION_MOVE: return "MOVE";
-        case MotionEvent.ACTION_OUTSIDE: return "OUTSIDE";
-        default: return "ACTION_" + actionType;
-        }
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/MainLogBuffer.java b/java/src/com/android/inputmethod/research/MainLogBuffer.java
deleted file mode 100644
index 3806ac7..0000000
--- a/java/src/com/android/inputmethod/research/MainLogBuffer.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.util.Log;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.define.ProductionFlag;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.LinkedList;
-
-/**
- * MainLogBuffer is a FixedLogBuffer that tracks the state of LogUnits to make privacy guarantees.
- *
- * There are three forms of privacy protection: 1) only words in the main dictionary are allowed to
- * be logged in enough detail to determine their contents, 2) only a subset of words are logged
- * in detail, such as 10%, and 3) no numbers are logged.
- *
- * This class maintains a list of LogUnits, each corresponding to a word.  As the user completes
- * words, they are added here.  But if the user backs up over their current word to edit a word
- * entered earlier, then it is pulled out of this LogBuffer, changes are then added to the end of
- * the LogUnit, and it is pushed back in here when the user is done.  Because words may be pulled
- * back out even after they are pushed in, we must not publish the contents of this LogBuffer too
- * quickly.  However, we cannot let the contents pile up either, or it will limit the editing that
- * a user can perform.
- *
- * To balance these requirements (keep history so user can edit, flush history so it does not pile
- * up), the LogBuffer is considered "complete" when the user has entered enough words to form an
- * n-gram, followed by enough additional non-detailed words (that are in the 90%, as per above).
- * Once complete, the n-gram may be published to flash storage (via the ResearchLog class).
- * However, the additional non-detailed words are retained, in case the user backspaces to edit
- * them.  The MainLogBuffer then continues to add words, publishing individual non-detailed words
- * as new words arrive.  After enough non-detailed words have been pushed out to account for the
- * 90% between words, the words at the front of the LogBuffer can be published as an n-gram again.
- *
- * If the words that would form the valid n-gram are not in the dictionary, then words are pushed
- * through the LogBuffer one at a time until an n-gram is found that is entirely composed of
- * dictionary words.
- *
- * If the user closes a session, then the entire LogBuffer is flushed, publishing any embedded
- * n-gram containing dictionary words.
- */
-public abstract class MainLogBuffer extends FixedLogBuffer {
-    private static final String TAG = MainLogBuffer.class.getSimpleName();
-    private static final boolean DEBUG = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-
-    // Keep consistent with switch statement in Statistics.recordPublishabilityResultCode()
-    public static final int PUBLISHABILITY_PUBLISHABLE = 0;
-    public static final int PUBLISHABILITY_UNPUBLISHABLE_STOPPING = 1;
-    public static final int PUBLISHABILITY_UNPUBLISHABLE_INCORRECT_WORD_COUNT = 2;
-    public static final int PUBLISHABILITY_UNPUBLISHABLE_SAMPLED_TOO_RECENTLY = 3;
-    public static final int PUBLISHABILITY_UNPUBLISHABLE_DICTIONARY_UNAVAILABLE = 4;
-    public static final int PUBLISHABILITY_UNPUBLISHABLE_MAY_CONTAIN_DIGIT = 5;
-    public static final int PUBLISHABILITY_UNPUBLISHABLE_NOT_IN_DICTIONARY = 6;
-
-    // The size of the n-grams logged.  E.g. N_GRAM_SIZE = 2 means to sample bigrams.
-    public static final int N_GRAM_SIZE = 2;
-
-    private final DictionaryFacilitator mDictionaryFacilitator;
-    @UsedForTesting
-    private Dictionary mDictionaryForTesting;
-    private boolean mIsStopping = false;
-
-    /* package for test */ int mNumWordsBetweenNGrams;
-
-    // Counter for words left to suppress before an n-gram can be sampled.  Reset to mMinWordPeriod
-    // after a sample is taken.
-    /* package for test */ int mNumWordsUntilSafeToSample;
-
-    public MainLogBuffer(final int wordsBetweenSamples, final int numInitialWordsToIgnore,
-            final DictionaryFacilitator dictionaryFacilitator) {
-        super(N_GRAM_SIZE + wordsBetweenSamples);
-        mNumWordsBetweenNGrams = wordsBetweenSamples;
-        mNumWordsUntilSafeToSample = DEBUG ? 0 : numInitialWordsToIgnore;
-        mDictionaryFacilitator = dictionaryFacilitator;
-    }
-
-    @UsedForTesting
-    /* package for test */ void setDictionaryForTesting(final Dictionary dictionary) {
-        mDictionaryForTesting = dictionary;
-    }
-
-    private boolean isValidDictWord(final String word) {
-        if (mDictionaryForTesting != null) {
-            return mDictionaryForTesting.isValidWord(word);
-        }
-        if (mDictionaryFacilitator != null) {
-            return mDictionaryFacilitator.isValidMainDictWord(word);
-        }
-        return false;
-    }
-
-    public void setIsStopping() {
-        mIsStopping = true;
-    }
-
-    /**
-     * Determines whether the string determined by a series of LogUnits will not violate user
-     * privacy if published.
-     *
-     * @param logUnits a LogUnit list to check for publishability
-     * @param nGramSize the smallest n-gram acceptable to be published.  if
-     * {@link ResearchLogger#IS_LOGGING_EVERYTHING} is true, then publish if there are more than
-     * {@code minNGramSize} words in the logUnits, otherwise wait.  if {@link
-     * ResearchLogger#IS_LOGGING_EVERYTHING} is false, then ensure that there are exactly nGramSize
-     * words in the LogUnits.
-     *
-     * @return one of the {@code PUBLISHABILITY_*} result codes defined in this class.
-     */
-    private int getPublishabilityResultCode(final ArrayList<LogUnit> logUnits,
-            final int nGramSize) {
-        // Bypass privacy checks when debugging.
-        if (ResearchLogger.IS_LOGGING_EVERYTHING) {
-            if (mIsStopping) {
-                return PUBLISHABILITY_UNPUBLISHABLE_STOPPING;
-            }
-            // Only check that it is the right length.  If not, wait for later words to make
-            // complete n-grams.
-            int numWordsInLogUnitList = 0;
-            final int length = logUnits.size();
-            for (int i = 0; i < length; i++) {
-                final LogUnit logUnit = logUnits.get(i);
-                numWordsInLogUnitList += logUnit.getNumWords();
-            }
-            if (numWordsInLogUnitList >= nGramSize) {
-                return PUBLISHABILITY_PUBLISHABLE;
-            } else {
-                return PUBLISHABILITY_UNPUBLISHABLE_INCORRECT_WORD_COUNT;
-            }
-        }
-
-        // Check that we are not sampling too frequently.  Having sampled recently might disclose
-        // too much of the user's intended meaning.
-        if (mNumWordsUntilSafeToSample > 0) {
-            return PUBLISHABILITY_UNPUBLISHABLE_SAMPLED_TOO_RECENTLY;
-        }
-        // Reload the dictionary in case it has changed (e.g., because the user has changed
-        // languages).
-        if ((mDictionaryFacilitator == null
-                || !mDictionaryFacilitator.hasInitializedMainDictionary())
-                        && mDictionaryForTesting == null) {
-            // Main dictionary is unavailable.  Since we cannot check it, we cannot tell if a
-            // word is out-of-vocabulary or not.  Therefore, we must judge the entire buffer
-            // contents to potentially pose a privacy risk.
-            return PUBLISHABILITY_UNPUBLISHABLE_DICTIONARY_UNAVAILABLE;
-        }
-
-        // Check each word in the buffer.  If any word poses a privacy threat, we cannot upload
-        // the complete buffer contents in detail.
-        int numWordsInLogUnitList = 0;
-        for (final LogUnit logUnit : logUnits) {
-            if (!logUnit.hasOneOrMoreWords()) {
-                // Digits outside words are a privacy threat.
-                if (logUnit.mayContainDigit()) {
-                    return PUBLISHABILITY_UNPUBLISHABLE_MAY_CONTAIN_DIGIT;
-                }
-            } else {
-                numWordsInLogUnitList += logUnit.getNumWords();
-                final String[] words = logUnit.getWordsAsStringArray();
-                for (final String word : words) {
-                    // Words not in the dictionary are a privacy threat.
-                    if (ResearchLogger.hasLetters(word) && !isValidDictWord(word)) {
-                        if (DEBUG) {
-                            Log.d(TAG, "\"" + word + "\" NOT SAFE!: hasLetters: "
-                                    + ResearchLogger.hasLetters(word)
-                                    + ", isValid: " + isValidDictWord(word));
-                        }
-                        return PUBLISHABILITY_UNPUBLISHABLE_NOT_IN_DICTIONARY;
-                    }
-                }
-            }
-        }
-
-        // Finally, only return true if the ngram is the right size.
-        if (numWordsInLogUnitList == nGramSize) {
-            return PUBLISHABILITY_PUBLISHABLE;
-        } else {
-            return PUBLISHABILITY_UNPUBLISHABLE_INCORRECT_WORD_COUNT;
-        }
-    }
-
-    public void shiftAndPublishAll() throws IOException {
-        final LinkedList<LogUnit> logUnits = getLogUnits();
-        while (!logUnits.isEmpty()) {
-            publishLogUnitsAtFrontOfBuffer();
-        }
-    }
-
-    @Override
-    protected final void onBufferFull() {
-        try {
-            publishLogUnitsAtFrontOfBuffer();
-        } catch (final IOException e) {
-            if (DEBUG) {
-                Log.w(TAG, "IOException when publishing front of LogBuffer", e);
-            }
-        }
-    }
-
-    /**
-     * If there is a safe n-gram at the front of this log buffer, publish it with all details, and
-     * remove the LogUnits that constitute it.
-     *
-     * An n-gram might not be "safe" if it violates privacy controls.  E.g., it might contain
-     * numbers, an out-of-vocabulary word, or another n-gram may have been published recently.  If
-     * there is no safe n-gram, then the LogUnits up through the first word-containing LogUnit are
-     * published, but without disclosing any privacy-related details, such as the word the LogUnit
-     * generated, motion data, etc.
-     *
-     * Note that a LogUnit can hold more than one word if the user types without explicit spaces.
-     * In this case, the words may be grouped together in such a way that pulling an n-gram off the
-     * front would require splitting a LogUnit.  Splitting a LogUnit is not possible, so this case
-     * is treated just as the unsafe n-gram case.  This may cause n-grams to be sampled at slightly
-     * less than the target frequency.
-     */
-    protected final void publishLogUnitsAtFrontOfBuffer() throws IOException {
-        // TODO: Refactor this method to require fewer passes through the LogUnits.  Should really
-        // require only one pass.
-        ArrayList<LogUnit> logUnits = peekAtFirstNWords(N_GRAM_SIZE);
-        final int publishabilityResultCode = getPublishabilityResultCode(logUnits, N_GRAM_SIZE);
-        ResearchLogger.recordPublishabilityResultCode(publishabilityResultCode);
-        if (publishabilityResultCode == MainLogBuffer.PUBLISHABILITY_PUBLISHABLE) {
-            // Good n-gram at the front of the buffer.  Publish it, disclosing details.
-            publish(logUnits, true /* canIncludePrivateData */);
-            shiftOutWords(N_GRAM_SIZE);
-            mNumWordsUntilSafeToSample = mNumWordsBetweenNGrams;
-            return;
-        }
-        // No good n-gram at front, and buffer is full.  Shift out up through the first logUnit
-        // with associated words (or if there is none, all the existing logUnits).
-        logUnits.clear();
-        LogUnit logUnit = shiftOut();
-        while (logUnit != null) {
-            logUnits.add(logUnit);
-            final int numWords = logUnit.getNumWords();
-            if (numWords > 0) {
-                mNumWordsUntilSafeToSample = Math.max(0, mNumWordsUntilSafeToSample - numWords);
-                break;
-            }
-            logUnit = shiftOut();
-        }
-        publish(logUnits, false /* canIncludePrivateData */);
-    }
-
-    /**
-     * Called when a list of logUnits should be published.
-     *
-     * It is the subclass's responsibility to implement the publication.
-     *
-     * @param logUnits The list of logUnits to be published.
-     * @param canIncludePrivateData Whether the private data in the logUnits can be included in
-     * publication.
-     *
-     * @throws IOException if publication to the log file is not possible
-     */
-    protected abstract void publish(final ArrayList<LogUnit> logUnits,
-            final boolean canIncludePrivateData) throws IOException;
-
-    @Override
-    protected int shiftOutWords(final int numWords) {
-        final int numWordsShiftedOut = super.shiftOutWords(numWords);
-        mNumWordsUntilSafeToSample = Math.max(0, mNumWordsUntilSafeToSample - numWordsShiftedOut);
-        if (DEBUG) {
-            Log.d(TAG, "wordsUntilSafeToSample now at " + mNumWordsUntilSafeToSample);
-        }
-        return numWordsShiftedOut;
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/MotionEventReader.java b/java/src/com/android/inputmethod/research/MotionEventReader.java
deleted file mode 100644
index f6b7352..0000000
--- a/java/src/com/android/inputmethod/research/MotionEventReader.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (C) 2013 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.research;
-
-import android.util.JsonReader;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
-import android.view.MotionEvent.PointerProperties;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.define.ProductionFlag;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-
-public class MotionEventReader {
-    private static final String TAG = MotionEventReader.class.getSimpleName();
-    private static final boolean DEBUG = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-    // Assumes that MotionEvent.ACTION_MASK does not have all bits set.`
-    private static final int UNINITIALIZED_ACTION = ~MotionEvent.ACTION_MASK;
-    // No legitimate int is negative
-    private static final int UNINITIALIZED_INT = -1;
-    // No legitimate long is negative
-    private static final long UNINITIALIZED_LONG = -1L;
-    // No legitimate float is negative
-    private static final float UNINITIALIZED_FLOAT = -1.0f;
-
-    public ReplayData readMotionEventData(final File file) {
-        final ReplayData replayData = new ReplayData();
-        try {
-            // Read file
-            final JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(
-                    new FileInputStream(file))));
-            jsonReader.beginArray();
-            while (jsonReader.hasNext()) {
-                readLogStatement(jsonReader, replayData);
-            }
-            jsonReader.endArray();
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        return replayData;
-    }
-
-    @UsedForTesting
-    static class ReplayData {
-        final ArrayList<Integer> mActions = new ArrayList<>();
-        final ArrayList<PointerProperties[]> mPointerPropertiesArrays = new ArrayList<>();
-        final ArrayList<PointerCoords[]> mPointerCoordsArrays = new ArrayList<>();
-        final ArrayList<Long> mTimes = new ArrayList<>();
-    }
-
-    /**
-     * Read motion data from a logStatement and store it in {@code replayData}.
-     *
-     * Two kinds of logStatements can be read.  In the first variant, the MotionEvent data is
-     * represented as attributes at the top level like so:
-     *
-     * <pre>
-     * {
-     *   "_ct": 1359590400000,
-     *   "_ut": 4381933,
-     *   "_ty": "MotionEvent",
-     *   "action": "UP",
-     *   "isLoggingRelated": false,
-     *   "x": 100,
-     *   "y": 200
-     * }
-     * </pre>
-     *
-     * In the second variant, there is a separate attribute for the MotionEvent that includes
-     * historical data if present:
-     *
-     * <pre>
-     * {
-     *   "_ct": 135959040000,
-     *   "_ut": 4382702,
-     *   "_ty": "MotionEvent",
-     *   "action": "MOVE",
-     *   "isLoggingRelated": false,
-     *   "motionEvent": {
-     *     "pointerIds": [
-     *       0
-     *     ],
-     *     "xyt": [
-     *       {
-     *         "t": 4382551,
-     *         "d": [
-     *           {
-     *             "x": 141.25,
-     *             "y": 151.8485107421875,
-     *             "toma": 101.82337188720703,
-     *             "tomi": 101.82337188720703,
-     *             "o": 0.0
-     *           }
-     *         ]
-     *       },
-     *       {
-     *         "t": 4382559,
-     *         "d": [
-     *           {
-     *             "x": 140.7266082763672,
-     *             "y": 151.8485107421875,
-     *             "toma": 101.82337188720703,
-     *             "tomi": 101.82337188720703,
-     *             "o": 0.0
-     *           }
-     *         ]
-     *       }
-     *     ]
-     *   }
-     * },
-     * </pre>
-     */
-    @UsedForTesting
-    /* package for test */ void readLogStatement(final JsonReader jsonReader,
-            final ReplayData replayData) throws IOException {
-        String logStatementType = null;
-        int actionType = UNINITIALIZED_ACTION;
-        int x = UNINITIALIZED_INT;
-        int y = UNINITIALIZED_INT;
-        long time = UNINITIALIZED_LONG;
-        boolean isLoggingRelated = false;
-
-        jsonReader.beginObject();
-        while (jsonReader.hasNext()) {
-            final String key = jsonReader.nextName();
-            if (key.equals("_ty")) {
-                logStatementType = jsonReader.nextString();
-            } else if (key.equals("_ut")) {
-                time = jsonReader.nextLong();
-            } else if (key.equals("x")) {
-                x = jsonReader.nextInt();
-            } else if (key.equals("y")) {
-                y = jsonReader.nextInt();
-            } else if (key.equals("action")) {
-                final String s = jsonReader.nextString();
-                if (s.equals("UP")) {
-                    actionType = MotionEvent.ACTION_UP;
-                } else if (s.equals("DOWN")) {
-                    actionType = MotionEvent.ACTION_DOWN;
-                } else if (s.equals("MOVE")) {
-                    actionType = MotionEvent.ACTION_MOVE;
-                }
-            } else if (key.equals("loggingRelated")) {
-                isLoggingRelated = jsonReader.nextBoolean();
-            } else if (logStatementType != null && logStatementType.equals("MotionEvent")
-                    && key.equals("motionEvent")) {
-                if (actionType == UNINITIALIZED_ACTION) {
-                    Log.e(TAG, "no actionType assigned in MotionEvent json");
-                }
-                // Second variant of LogStatement.
-                if (isLoggingRelated) {
-                    jsonReader.skipValue();
-                } else {
-                    readEmbeddedMotionEvent(jsonReader, replayData, actionType);
-                }
-            } else {
-                if (DEBUG) {
-                    Log.w(TAG, "Unknown JSON key in LogStatement: " + key);
-                }
-                jsonReader.skipValue();
-            }
-        }
-        jsonReader.endObject();
-
-        if (logStatementType != null && time != UNINITIALIZED_LONG && x != UNINITIALIZED_INT
-                && y != UNINITIALIZED_INT && actionType != UNINITIALIZED_ACTION
-                && logStatementType.equals("MotionEvent") && !isLoggingRelated) {
-            // First variant of LogStatement.
-            final PointerProperties pointerProperties = new PointerProperties();
-            pointerProperties.id = 0;
-            pointerProperties.toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
-            final PointerProperties[] pointerPropertiesArray = {
-                pointerProperties
-            };
-            final PointerCoords pointerCoords = new PointerCoords();
-            pointerCoords.x = x;
-            pointerCoords.y = y;
-            pointerCoords.pressure = 1.0f;
-            pointerCoords.size = 1.0f;
-            final PointerCoords[] pointerCoordsArray = {
-                pointerCoords
-            };
-            addMotionEventData(replayData, actionType, time, pointerPropertiesArray,
-                    pointerCoordsArray);
-        }
-    }
-
-    private void readEmbeddedMotionEvent(final JsonReader jsonReader, final ReplayData replayData,
-            final int actionType) throws IOException {
-        jsonReader.beginObject();
-        PointerProperties[] pointerPropertiesArray = null;
-        while (jsonReader.hasNext()) {  // pointerIds/xyt
-            final String name = jsonReader.nextName();
-            if (name.equals("pointerIds")) {
-                pointerPropertiesArray = readPointerProperties(jsonReader);
-            } else if (name.equals("xyt")) {
-                readPointerData(jsonReader, replayData, actionType, pointerPropertiesArray);
-            }
-        }
-        jsonReader.endObject();
-    }
-
-    private PointerProperties[] readPointerProperties(final JsonReader jsonReader)
-            throws IOException {
-        final ArrayList<PointerProperties> pointerPropertiesArrayList = new ArrayList<>();
-        jsonReader.beginArray();
-        while (jsonReader.hasNext()) {
-            final PointerProperties pointerProperties = new PointerProperties();
-            pointerProperties.id = jsonReader.nextInt();
-            pointerProperties.toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
-            pointerPropertiesArrayList.add(pointerProperties);
-        }
-        jsonReader.endArray();
-        return pointerPropertiesArrayList.toArray(
-                new PointerProperties[pointerPropertiesArrayList.size()]);
-    }
-
-    private void readPointerData(final JsonReader jsonReader, final ReplayData replayData,
-            final int actionType, final PointerProperties[] pointerPropertiesArray)
-            throws IOException {
-        if (pointerPropertiesArray == null) {
-            Log.e(TAG, "PointerIDs must be given before xyt data in json for MotionEvent");
-            jsonReader.skipValue();
-            return;
-        }
-        long time = UNINITIALIZED_LONG;
-        jsonReader.beginArray();
-        while (jsonReader.hasNext()) {  // Array of historical data
-            jsonReader.beginObject();
-            final ArrayList<PointerCoords> pointerCoordsArrayList = new ArrayList<>();
-            while (jsonReader.hasNext()) {  // Time/data object
-                final String name = jsonReader.nextName();
-                if (name.equals("t")) {
-                    time = jsonReader.nextLong();
-                } else if (name.equals("d")) {
-                    jsonReader.beginArray();
-                    while (jsonReader.hasNext()) {  // array of data per pointer
-                        final PointerCoords pointerCoords = readPointerCoords(jsonReader);
-                        if (pointerCoords != null) {
-                            pointerCoordsArrayList.add(pointerCoords);
-                        }
-                    }
-                    jsonReader.endArray();
-                } else {
-                    jsonReader.skipValue();
-                }
-            }
-            jsonReader.endObject();
-            // Data was recorded as historical events, but must be split apart into
-            // separate MotionEvents for replaying
-            if (time != UNINITIALIZED_LONG) {
-                addMotionEventData(replayData, actionType, time, pointerPropertiesArray,
-                        pointerCoordsArrayList.toArray(
-                                new PointerCoords[pointerCoordsArrayList.size()]));
-            } else {
-                Log.e(TAG, "Time not assigned in json for MotionEvent");
-            }
-        }
-        jsonReader.endArray();
-    }
-
-    private PointerCoords readPointerCoords(final JsonReader jsonReader) throws IOException {
-        jsonReader.beginObject();
-        float x = UNINITIALIZED_FLOAT;
-        float y = UNINITIALIZED_FLOAT;
-        while (jsonReader.hasNext()) {  // x,y
-            final String name = jsonReader.nextName();
-            if (name.equals("x")) {
-                x = (float) jsonReader.nextDouble();
-            } else if (name.equals("y")) {
-                y = (float) jsonReader.nextDouble();
-            } else {
-                jsonReader.skipValue();
-            }
-        }
-        jsonReader.endObject();
-
-        if (Float.compare(x, UNINITIALIZED_FLOAT) == 0
-                || Float.compare(y, UNINITIALIZED_FLOAT) == 0) {
-            Log.w(TAG, "missing x or y value in MotionEvent json");
-            return null;
-        }
-        final PointerCoords pointerCoords = new PointerCoords();
-        pointerCoords.x = x;
-        pointerCoords.y = y;
-        pointerCoords.pressure = 1.0f;
-        pointerCoords.size = 1.0f;
-        return pointerCoords;
-    }
-
-    private void addMotionEventData(final ReplayData replayData, final int actionType,
-            final long time, final PointerProperties[] pointerProperties,
-            final PointerCoords[] pointerCoords) {
-        replayData.mActions.add(actionType);
-        replayData.mTimes.add(time);
-        replayData.mPointerPropertiesArrays.add(pointerProperties);
-        replayData.mPointerCoordsArrays.add(pointerCoords);
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/Replayer.java b/java/src/com/android/inputmethod/research/Replayer.java
deleted file mode 100644
index 903875f..0000000
--- a/java/src/com/android/inputmethod/research/Replayer.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.SystemClock;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
-import android.view.MotionEvent.PointerProperties;
-
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.MainKeyboardView;
-import com.android.inputmethod.latin.define.ProductionFlag;
-import com.android.inputmethod.research.MotionEventReader.ReplayData;
-
-/**
- * Replays a sequence of motion events in realtime on the screen.
- *
- * Useful for user inspection of logged data.
- */
-public class Replayer {
-    private static final String TAG = Replayer.class.getSimpleName();
-    private static final boolean DEBUG = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-    private static final long START_TIME_DELAY_MS = 500;
-
-    private boolean mIsReplaying = false;
-    private KeyboardSwitcher mKeyboardSwitcher;
-
-    private Replayer() {
-    }
-
-    private static final Replayer sInstance = new Replayer();
-    public static Replayer getInstance() {
-        return sInstance;
-    }
-
-    public void setKeyboardSwitcher(final KeyboardSwitcher keyboardSwitcher) {
-        mKeyboardSwitcher = keyboardSwitcher;
-    }
-
-    private static final int MSG_MOTION_EVENT = 0;
-    private static final int MSG_DONE = 1;
-    private static final int COMPLETION_TIME_MS = 500;
-
-    // TODO: Support historical events and multi-touch.
-    public void replay(final ReplayData replayData, final Runnable callback) {
-        if (mIsReplaying) {
-            return;
-        }
-        mIsReplaying = true;
-        final int numActions = replayData.mActions.size();
-        if (DEBUG) {
-            Log.d(TAG, "replaying " + numActions + " actions");
-        }
-        if (numActions == 0) {
-            mIsReplaying = false;
-            return;
-        }
-        final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
-
-        // The reference time relative to the times stored in events.
-        final long origStartTime = replayData.mTimes.get(0);
-        // The reference time relative to which events are replayed in the present.
-        final long currentStartTime = SystemClock.uptimeMillis() + START_TIME_DELAY_MS;
-        // The adjustment needed to translate times from the original recorded time to the current
-        // time.
-        final long timeAdjustment = currentStartTime - origStartTime;
-        final Handler handler = new Handler(Looper.getMainLooper()) {
-            // Track the time of the most recent DOWN event, to be passed as a parameter when
-            // constructing a MotionEvent.  It's initialized here to the origStartTime, but this is
-            // only a precaution.  The value should be overwritten by the first ACTION_DOWN event
-            // before the first use of the variable.  Note that this may cause the first few events
-            // to have incorrect {@code downTime}s.
-            private long mOrigDownTime = origStartTime;
-
-            @Override
-            public void handleMessage(final Message msg) {
-                switch (msg.what) {
-                case MSG_MOTION_EVENT:
-                    final int index = msg.arg1;
-                    final int action = replayData.mActions.get(index);
-                    final PointerProperties[] pointerPropertiesArray =
-                            replayData.mPointerPropertiesArrays.get(index);
-                    final PointerCoords[] pointerCoordsArray =
-                            replayData.mPointerCoordsArrays.get(index);
-                    final long origTime = replayData.mTimes.get(index);
-                    if (action == MotionEvent.ACTION_DOWN) {
-                        mOrigDownTime = origTime;
-                    }
-
-                    final MotionEvent me = MotionEvent.obtain(mOrigDownTime + timeAdjustment,
-                            origTime + timeAdjustment, action,
-                            pointerPropertiesArray.length, pointerPropertiesArray,
-                            pointerCoordsArray, 0, 0, 1.0f, 1.0f, 0, 0, 0, 0);
-                    mainKeyboardView.processMotionEvent(me);
-                    me.recycle();
-                    break;
-                case MSG_DONE:
-                    mIsReplaying = false;
-                    ResearchLogger.getInstance().requestIndicatorRedraw();
-                    break;
-                }
-            }
-        };
-
-        handler.post(new Runnable() {
-            @Override
-            public void run() {
-                ResearchLogger.getInstance().requestIndicatorRedraw();
-            }
-        });
-        for (int i = 0; i < numActions; i++) {
-            final Message msg = Message.obtain(handler, MSG_MOTION_EVENT, i, 0);
-            final long msgTime = replayData.mTimes.get(i) + timeAdjustment;
-            handler.sendMessageAtTime(msg, msgTime);
-            if (DEBUG) {
-                Log.d(TAG, "queuing event at " + msgTime);
-            }
-        }
-
-        final long presentDoneTime = replayData.mTimes.get(numActions - 1) + timeAdjustment
-                + COMPLETION_TIME_MS;
-        handler.sendMessageAtTime(Message.obtain(handler, MSG_DONE), presentDoneTime);
-        if (callback != null) {
-            handler.postAtTime(callback, presentDoneTime + 1);
-        }
-    }
-
-    public boolean isReplaying() {
-        return mIsReplaying;
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/ReplayerService.java b/java/src/com/android/inputmethod/research/ReplayerService.java
deleted file mode 100644
index 88d9033..0000000
--- a/java/src/com/android/inputmethod/research/ReplayerService.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.app.IntentService;
-import android.content.Intent;
-import android.util.Log;
-
-import com.android.inputmethod.research.MotionEventReader.ReplayData;
-
-import java.io.File;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Provide a mechanism to invoke the replayer from outside.
- *
- * In particular, makes access from a host possible through {@code adb am startservice}.
- */
-public class ReplayerService extends IntentService {
-    private static final String TAG = ReplayerService.class.getSimpleName();
-    private static final String EXTRA_FILENAME = "com.android.inputmethod.research.extra.FILENAME";
-    private static final long MAX_REPLAY_TIME = TimeUnit.SECONDS.toMillis(60);
-
-    public ReplayerService() {
-        super(ReplayerService.class.getSimpleName());
-    }
-
-    @Override
-    protected void onHandleIntent(final Intent intent) {
-        final String filename = intent.getStringExtra(EXTRA_FILENAME);
-        if (filename == null) return;
-
-        final ReplayData replayData = new MotionEventReader().readMotionEventData(
-                new File(filename));
-        synchronized (this) {
-            Replayer.getInstance().replay(replayData, new Runnable() {
-                @Override
-                public void run() {
-                    synchronized (ReplayerService.this) {
-                        ReplayerService.this.notify();
-                    }
-                }
-            });
-            try {
-                wait(MAX_REPLAY_TIME);
-            } catch (InterruptedException e) {
-                Log.e(TAG, "Timeout while replaying.", e);
-            }
-        }
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/ResearchLog.java b/java/src/com/android/inputmethod/research/ResearchLog.java
deleted file mode 100644
index 46e620a..0000000
--- a/java/src/com/android/inputmethod/research/ResearchLog.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.content.Context;
-import android.util.JsonWriter;
-import android.util.Log;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.define.ProductionFlag;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Logs the use of the LatinIME keyboard.
- *
- * This class logs operations on the IME keyboard, including what the user has typed.  Data is
- * written to a {@link JsonWriter}, which will write to a local file.
- *
- * The JsonWriter is created on-demand by calling {@link #getInitializedJsonWriterLocked}.
- *
- * This class uses an executor to perform file-writing operations on a separate thread.  It also
- * tries to avoid creating unnecessary files if there is nothing to write.  It also handles
- * flushing, making sure it happens, but not too frequently.
- *
- * This functionality is off by default. See
- * {@link ProductionFlag#USES_DEVELOPMENT_ONLY_DIAGNOSTICS}.
- */
-public class ResearchLog {
-    // TODO: Automatically initialize the JsonWriter rather than requiring the caller to manage it.
-    private static final String TAG = ResearchLog.class.getSimpleName();
-    private static final boolean DEBUG = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-    private static final long FLUSH_DELAY_IN_MS = TimeUnit.SECONDS.toMillis(5);
-
-    /* package */ final ScheduledExecutorService mExecutor;
-    /* package */ final File mFile;
-    private final Context mContext;
-
-    // Earlier implementations used a dummy JsonWriter that just swallowed what it was given, but
-    // this was tricky to do well, because JsonWriter throws an exception if it is passed more than
-    // one top-level object.
-    private JsonWriter mJsonWriter = null;
-
-    // true if at least one byte of data has been written out to the log file.  This must be
-    // remembered because JsonWriter requires that calls matching calls to beginObject and
-    // endObject, as well as beginArray and endArray, and the file is opened lazily, only when
-    // it is certain that data will be written.  Alternatively, the matching call exceptions
-    // could be caught, but this might suppress other errors.
-    private boolean mHasWrittenData = false;
-
-    public ResearchLog(final File outputFile, final Context context) {
-        mExecutor = Executors.newSingleThreadScheduledExecutor();
-        mFile = outputFile;
-        mContext = context;
-    }
-
-    /**
-     * Returns true if this is a FeedbackLog.
-     *
-     * FeedbackLogs record only the data associated with a Feedback dialog. Instead of normal
-     * logging, they contain a LogStatement with the complete feedback string and optionally a
-     * recording of the user's supplied demo of the problem.
-     */
-    public boolean isFeedbackLog() {
-        return false;
-    }
-
-    /**
-     * Waits for any publication requests to finish and closes the {@link JsonWriter} used for
-     * output.
-     *
-     * See class comment for details about {@code JsonWriter} construction.
-     *
-     * @param onClosed run after the close() operation has completed asynchronously
-     */
-    private synchronized void close(final Runnable onClosed) {
-        mExecutor.submit(new Callable<Object>() {
-            @Override
-            public Object call() throws Exception {
-                try {
-                    if (mJsonWriter == null) return null;
-                    // TODO: This is necessary to avoid an exception.  Better would be to not even
-                    // open the JsonWriter if the file is not even opened unless there is valid data
-                    // to write.
-                    if (!mHasWrittenData) {
-                        mJsonWriter.beginArray();
-                    }
-                    mJsonWriter.endArray();
-                    mHasWrittenData = false;
-                    mJsonWriter.flush();
-                    mJsonWriter.close();
-                    if (DEBUG) {
-                        Log.d(TAG, "closed " + mFile);
-                    }
-                } catch (final Exception e) {
-                    Log.d(TAG, "error when closing ResearchLog:", e);
-                } finally {
-                    // Marking the file as read-only signals that this log file is ready to be
-                    // uploaded.
-                    if (mFile != null && mFile.exists()) {
-                        mFile.setWritable(false, false);
-                    }
-                    if (onClosed != null) {
-                        onClosed.run();
-                    }
-                }
-                return null;
-            }
-        });
-        removeAnyScheduledFlush();
-        mExecutor.shutdown();
-    }
-
-    /**
-     * Block until the research log has shut down and spooled out all output or {@code timeout}
-     * occurs.
-     *
-     * @param timeout time to wait for close in milliseconds
-     */
-    public void blockingClose(final long timeout) {
-        close(null);
-        awaitTermination(timeout, TimeUnit.MILLISECONDS);
-    }
-
-    /**
-     * Waits for publication requests to finish, closes the JsonWriter, but then deletes the backing
-     * output file.
-     *
-     * @param onAbort run after the abort() operation has completed asynchronously
-     */
-    private synchronized void abort(final Runnable onAbort) {
-        mExecutor.submit(new Callable<Object>() {
-            @Override
-            public Object call() throws Exception {
-                try {
-                    if (mJsonWriter == null) return null;
-                    if (mHasWrittenData) {
-                        // TODO: This is necessary to avoid an exception.  Better would be to not
-                        // even open the JsonWriter if the file is not even opened unless there is
-                        // valid data to write.
-                        if (!mHasWrittenData) {
-                            mJsonWriter.beginArray();
-                        }
-                        mJsonWriter.endArray();
-                        mJsonWriter.close();
-                        mHasWrittenData = false;
-                    }
-                } finally {
-                    if (mFile != null) {
-                        mFile.delete();
-                    }
-                    if (onAbort != null) {
-                        onAbort.run();
-                    }
-                }
-                return null;
-            }
-        });
-        removeAnyScheduledFlush();
-        mExecutor.shutdown();
-    }
-
-    /**
-     * Block until the research log has aborted or {@code timeout} occurs.
-     *
-     * @param timeout time to wait for close in milliseconds
-     */
-    public void blockingAbort(final long timeout) {
-        abort(null);
-        awaitTermination(timeout, TimeUnit.MILLISECONDS);
-    }
-
-    @UsedForTesting
-    public void awaitTermination(final long delay, final TimeUnit timeUnit) {
-        try {
-            if (!mExecutor.awaitTermination(delay, timeUnit)) {
-                Log.e(TAG, "ResearchLog executor timed out while awaiting terminaion");
-            }
-        } catch (final InterruptedException e) {
-            Log.e(TAG, "ResearchLog executor interrupted while awaiting terminaion", e);
-        }
-    }
-
-    /* package */ synchronized void flush() {
-        removeAnyScheduledFlush();
-        mExecutor.submit(mFlushCallable);
-    }
-
-    private final Callable<Object> mFlushCallable = new Callable<Object>() {
-        @Override
-        public Object call() throws Exception {
-            if (mJsonWriter != null) mJsonWriter.flush();
-            return null;
-        }
-    };
-
-    private ScheduledFuture<Object> mFlushFuture;
-
-    private void removeAnyScheduledFlush() {
-        if (mFlushFuture != null) {
-            mFlushFuture.cancel(false);
-            mFlushFuture = null;
-        }
-    }
-
-    private void scheduleFlush() {
-        removeAnyScheduledFlush();
-        mFlushFuture = mExecutor.schedule(mFlushCallable, FLUSH_DELAY_IN_MS, TimeUnit.MILLISECONDS);
-    }
-
-    /**
-     * Queues up {@code logUnit} to be published in the background.
-     *
-     * @param logUnit the {@link LogUnit} to be published
-     * @param canIncludePrivateData whether private data in the LogUnit should be included
-     */
-    public synchronized void publish(final LogUnit logUnit, final boolean canIncludePrivateData) {
-        try {
-            mExecutor.submit(new Callable<Object>() {
-                @Override
-                public Object call() throws Exception {
-                    logUnit.publishTo(ResearchLog.this, canIncludePrivateData);
-                    scheduleFlush();
-                    return null;
-                }
-            });
-        } catch (final RejectedExecutionException e) {
-            // TODO: Add code to record loss of data, and report.
-            if (DEBUG) {
-                Log.d(TAG, "ResearchLog.publish() rejecting scheduled execution", e);
-            }
-        }
-    }
-
-    /**
-     * Return a JsonWriter for this ResearchLog.  It is initialized the first time this method is
-     * called.  The cached value is returned in future calls.
-     *
-     * @throws IOException if opening the JsonWriter is not possible
-     */
-    public JsonWriter getInitializedJsonWriterLocked() throws IOException {
-        if (mJsonWriter != null) return mJsonWriter;
-        if (mFile == null) throw new FileNotFoundException();
-        try {
-            final JsonWriter jsonWriter = createJsonWriter(mContext, mFile);
-            if (jsonWriter == null) throw new IOException("Could not create JsonWriter");
-
-            jsonWriter.beginArray();
-            mJsonWriter = jsonWriter;
-            mHasWrittenData = true;
-            return mJsonWriter;
-        } catch (final IOException e) {
-            if (DEBUG) {
-                Log.w(TAG, "Exception when creating JsonWriter", e);
-                Log.w(TAG, "Closing JsonWriter");
-            }
-            if (mJsonWriter != null) mJsonWriter.close();
-            mJsonWriter = null;
-            throw e;
-        }
-    }
-
-    /**
-     * Create the JsonWriter to write the ResearchLog to.
-     *
-     * This method may be overriden in testing to redirect the output.
-     */
-    /* package for test */ JsonWriter createJsonWriter(final Context context, final File file)
-            throws IOException {
-        return new JsonWriter(new BufferedWriter(new OutputStreamWriter(
-                context.openFileOutput(file.getName(), Context.MODE_PRIVATE))));
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/ResearchLogDirectory.java b/java/src/com/android/inputmethod/research/ResearchLogDirectory.java
deleted file mode 100644
index d156068..0000000
--- a/java/src/com/android/inputmethod/research/ResearchLogDirectory.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2013 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.research;
-
-import android.content.Context;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileFilter;
-
-/**
- * Manages log files.
- *
- * This class handles all aspects where and how research log data is stored.  This includes
- * generating log filenames in the correct place with the correct names, and cleaning up log files
- * under this directory.
- */
-public class ResearchLogDirectory {
-    public static final String TAG = ResearchLogDirectory.class.getSimpleName();
-    /* package */ static final String LOG_FILENAME_PREFIX = "researchLog";
-    private static final String FILENAME_SUFFIX = ".txt";
-    private static final String USER_RECORDING_FILENAME_PREFIX = "recording";
-
-    private static final ReadOnlyLogFileFilter sUploadableLogFileFilter =
-            new ReadOnlyLogFileFilter();
-
-    private final File mFilesDir;
-
-    static class ReadOnlyLogFileFilter implements FileFilter {
-        @Override
-        public boolean accept(final File pathname) {
-            return pathname.getName().startsWith(ResearchLogDirectory.LOG_FILENAME_PREFIX)
-                    && !pathname.canWrite();
-        }
-    }
-
-    /**
-     * Creates a new ResearchLogDirectory, creating the storage directory if it does not exist.
-     */
-    public ResearchLogDirectory(final Context context) {
-        mFilesDir = getLoggingDirectory(context);
-        if (mFilesDir == null) {
-            throw new NullPointerException("No files directory specified");
-        }
-        if (!mFilesDir.exists()) {
-            mFilesDir.mkdirs();
-        }
-    }
-
-    private File getLoggingDirectory(final Context context) {
-        // TODO: Switch to using a subdirectory of getFilesDir().
-        return context.getFilesDir();
-    }
-
-    /**
-     * Get an array of log files that are ready for uploading.
-     *
-     * A file is ready for uploading if it is marked as read-only.
-     *
-     * @return the array of uploadable files
-     */
-    public File[] getUploadableLogFiles() {
-        try {
-            return mFilesDir.listFiles(sUploadableLogFileFilter);
-        } catch (final SecurityException e) {
-            Log.e(TAG, "Could not cleanup log directory, permission denied", e);
-            return new File[0];
-        }
-    }
-
-    public void cleanupLogFilesOlderThan(final long time) {
-        try {
-            for (final File file : mFilesDir.listFiles()) {
-                final String filename = file.getName();
-                if ((filename.startsWith(LOG_FILENAME_PREFIX)
-                        || filename.startsWith(USER_RECORDING_FILENAME_PREFIX))
-                        && (file.lastModified() < time)) {
-                    file.delete();
-                }
-            }
-        } catch (final SecurityException e) {
-            Log.e(TAG, "Could not cleanup log directory, permission denied", e);
-        }
-    }
-
-    public File getLogFilePath(final long time, final long nanoTime) {
-        return new File(mFilesDir, getUniqueFilename(LOG_FILENAME_PREFIX, time, nanoTime));
-    }
-
-    public File getUserRecordingFilePath(final long time, final long nanoTime) {
-        return new File(mFilesDir, getUniqueFilename(USER_RECORDING_FILENAME_PREFIX, time,
-                nanoTime));
-    }
-
-    private static String getUniqueFilename(final String prefix, final long time,
-            final long nanoTime) {
-        return prefix + "-" + time + "-" + nanoTime + FILENAME_SUFFIX;
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
deleted file mode 100644
index d73f9c4..0000000
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ /dev/null
@@ -1,1885 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.SystemClock;
-import android.preference.PreferenceManager;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
-import android.widget.Toast;
-
-import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.KeyboardView;
-import com.android.inputmethod.keyboard.MainKeyboardView;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.LatinIME;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.RichInputConnection;
-import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.define.ProductionFlag;
-import com.android.inputmethod.latin.utils.InputTypeUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
-import com.android.inputmethod.latin.utils.TextRange;
-import com.android.inputmethod.research.MotionEventReader.ReplayData;
-import com.android.inputmethod.research.ui.SplashScreen;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Pattern;
-
-// TODO: Add a unit test for every "logging" method (i.e. that is called from the IME and calls
-// enqueueEvent to record a LogStatement).
-/**
- * Logs the use of the LatinIME keyboard.
- *
- * This class logs operations on the IME keyboard, including what the user has typed.
- * Data is stored locally in a file in app-specific storage.
- *
- * This functionality is off by default. See
- * {@link ProductionFlag#USES_DEVELOPMENT_ONLY_DIAGNOSTICS}.
- */
-public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener,
-        SplashScreen.UserConsentListener {
-    // TODO: This class has grown quite large and combines several concerns that should be
-    // separated.  The following refactorings will be applied as soon as possible after adding
-    // support for replaying historical events, fixing some replay bugs, adding some ui constraints
-    // on the feedback dialog, and adding the survey dialog.
-    // TODO: Refactor.  Move feedback screen code into separate class.
-    // TODO: Refactor.  Move logging invocations into their own class.
-    // TODO: Refactor.  Move currentLogUnit management into separate class.
-    private static final String TAG = ResearchLogger.class.getSimpleName();
-    private static final boolean DEBUG = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-    private static final boolean DEBUG_REPLAY_AFTER_FEEDBACK = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-    // Whether the feedback dialog preserves the editable text across invocations.  Should be false
-    // for normal research builds so users do not have to delete the same feedback string they
-    // entered earlier.  Should be true for builds internal to a development team so when the text
-    // field holds a channel name, the developer does not have to re-enter it when using the
-    // feedback mechanism to generate multiple tests.
-    private static final boolean FEEDBACK_DIALOG_SHOULD_PRESERVE_TEXT_FIELD = false;
-    /* package */ static boolean sIsLogging = false;
-    private static final int OUTPUT_FORMAT_VERSION = 6;
-    // Whether all words should be recorded, leaving unsampled word between bigrams.  Useful for
-    // testing.
-    /* package for test */ static final boolean IS_LOGGING_EVERYTHING = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-    // The number of words between n-grams to omit from the log.
-    private static final int NUMBER_OF_WORDS_BETWEEN_SAMPLES =
-            IS_LOGGING_EVERYTHING ? 0 : (DEBUG ? 2 : 18);
-
-    // Whether to show an indicator on the screen that logging is on.  Currently a very small red
-    // dot in the lower right hand corner.  Most users should not notice it.
-    private static final boolean IS_SHOWING_INDICATOR = true;
-    // Change the default indicator to something very visible.  Currently two red vertical bars on
-    // either side of they keyboard.
-    private static final boolean IS_SHOWING_INDICATOR_CLEARLY = false ||
-            (IS_LOGGING_EVERYTHING && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG);
-    // FEEDBACK_WORD_BUFFER_SIZE should add 1 because it must also hold the feedback LogUnit itself.
-    public static final int FEEDBACK_WORD_BUFFER_SIZE = (Integer.MAX_VALUE - 1) + 1;
-
-    // The special output text to invoke a research feedback dialog.
-    public static final String RESEARCH_KEY_OUTPUT_TEXT = ".research.";
-
-    // constants related to specific log points
-    private static final int[] WHITESPACE_SEPARATORS =
-            StringUtils.toSortedCodePointArray(" \t\n\r");
-    private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1
-    private static final String PREF_RESEARCH_SAVED_CHANNEL = "pref_research_saved_channel";
-
-    private static final long RESEARCHLOG_CLOSE_TIMEOUT_IN_MS = TimeUnit.SECONDS.toMillis(5);
-    private static final long RESEARCHLOG_ABORT_TIMEOUT_IN_MS = TimeUnit.SECONDS.toMillis(5);
-    private static final long DURATION_BETWEEN_DIR_CLEANUP_IN_MS = TimeUnit.DAYS.toMillis(1);
-    private static final long MAX_LOGFILE_AGE_IN_MS = TimeUnit.DAYS.toMillis(4);
-
-    private static final ResearchLogger sInstance = new ResearchLogger();
-    private static String sAccountType = null;
-    private static String sAllowedAccountDomain = null;
-    private ResearchLog mMainResearchLog; // always non-null after init() is called
-    // mFeedbackLog records all events for the session, private or not (excepting
-    // passwords).  It is written to permanent storage only if the user explicitly commands
-    // the system to do so.
-    // LogUnits are queued in the LogBuffers and published to the ResearchLogs when words are
-    // complete.
-    /* package for test */ MainLogBuffer mMainLogBuffer; // always non-null after init() is called
-    /* package */ ResearchLog mUserRecordingLog;
-    /* package */ LogBuffer mUserRecordingLogBuffer;
-    private File mUserRecordingFile = null;
-
-    private boolean mIsPasswordView = false;
-    private SharedPreferences mPrefs;
-
-    // digits entered by the user are replaced with this codepoint.
-    /* package for test */ static final int DIGIT_REPLACEMENT_CODEPOINT =
-            Character.codePointAt("\uE000", 0);  // U+E000 is in the "private-use area"
-    // U+E001 is in the "private-use area"
-    /* package for test */ static final String WORD_REPLACEMENT_STRING = "\uE001";
-    protected static final int SUSPEND_DURATION_IN_MINUTES = 1;
-
-    // used to check whether words are not unique
-    private DictionaryFacilitator mDictionaryFacilitator;
-    private MainKeyboardView mMainKeyboardView;
-    // TODO: Check whether a superclass can be used instead of LatinIME.
-    /* package for test */ LatinIME mLatinIME;
-    private final Statistics mStatistics;
-    private final MotionEventReader mMotionEventReader = new MotionEventReader();
-    private final Replayer mReplayer = Replayer.getInstance();
-    private ResearchLogDirectory mResearchLogDirectory;
-    private SplashScreen mSplashScreen;
-
-    private Intent mUploadNowIntent;
-
-    /* package for test */ LogUnit mCurrentLogUnit = new LogUnit();
-
-    // Gestured or tapped words may be committed after the gesture of the next word has started.
-    // To ensure that the gesture data of the next word is not associated with the previous word,
-    // thereby leaking private data, we store the time of the down event that started the second
-    // gesture, and when committing the earlier word, split the LogUnit.
-    private long mSavedDownEventTime;
-    private Bundle mFeedbackDialogBundle = null;
-    // Whether the feedback dialog is visible, and the user is typing into it.  Normal logging is
-    // not performed on text that the user types into the feedback dialog.
-    private boolean mInFeedbackDialog = false;
-    private Handler mUserRecordingTimeoutHandler;
-    private static final long USER_RECORDING_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(30);
-
-    // Stores a temporary LogUnit while generating a phantom space.  Needed because phantom spaces
-    // are issued out-of-order, immediately before the characters generated by other operations that
-    // have already outputted LogStatements.
-    private LogUnit mPhantomSpaceLogUnit = null;
-
-    private ResearchLogger() {
-        mStatistics = Statistics.getInstance();
-    }
-
-    public static ResearchLogger getInstance() {
-        return sInstance;
-    }
-
-    public void init(final LatinIME latinIME, final KeyboardSwitcher keyboardSwitcher) {
-        assert latinIME != null;
-        mLatinIME = latinIME;
-        mPrefs = PreferenceManager.getDefaultSharedPreferences(latinIME);
-        mPrefs.registerOnSharedPreferenceChangeListener(this);
-
-        // Initialize fields from preferences
-        sIsLogging = ResearchSettings.readResearchLoggerEnabledFlag(mPrefs);
-
-        // Initialize fields from resources
-        final Resources res = latinIME.getResources();
-        sAccountType = res.getString(R.string.research_account_type);
-        sAllowedAccountDomain = res.getString(R.string.research_allowed_account_domain);
-
-        // Initialize directory manager
-        mResearchLogDirectory = new ResearchLogDirectory(mLatinIME);
-        cleanLogDirectoryIfNeeded(mResearchLogDirectory, System.currentTimeMillis());
-
-        // Initialize log buffers
-        resetLogBuffers();
-
-        // Initialize external services
-        mUploadNowIntent = new Intent(mLatinIME, UploaderService.class);
-        mUploadNowIntent.putExtra(UploaderService.EXTRA_UPLOAD_UNCONDITIONALLY, true);
-        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-            UploaderService.cancelAndRescheduleUploadingService(mLatinIME,
-                    true /* needsRescheduling */);
-        }
-        mReplayer.setKeyboardSwitcher(keyboardSwitcher);
-    }
-
-    private void resetLogBuffers() {
-        mMainResearchLog = new ResearchLog(mResearchLogDirectory.getLogFilePath(
-                System.currentTimeMillis(), System.nanoTime()), mLatinIME);
-        final int numWordsToIgnore = new Random().nextInt(NUMBER_OF_WORDS_BETWEEN_SAMPLES + 1);
-        mMainLogBuffer = new MainLogBuffer(NUMBER_OF_WORDS_BETWEEN_SAMPLES, numWordsToIgnore,
-                mDictionaryFacilitator) {
-            @Override
-            protected void publish(final ArrayList<LogUnit> logUnits,
-                    boolean canIncludePrivateData) {
-                canIncludePrivateData |= IS_LOGGING_EVERYTHING;
-                for (final LogUnit logUnit : logUnits) {
-                    if (DEBUG) {
-                        final String wordsString = logUnit.getWordsAsString();
-                        Log.d(TAG, "onPublish: '" + wordsString
-                                + "', hc: " + logUnit.containsUserDeletions()
-                                + ", cipd: " + canIncludePrivateData);
-                    }
-                    for (final String word : logUnit.getWordsAsStringArray()) {
-                        final boolean isDictionaryWord = mDictionaryFacilitator != null
-                                && mDictionaryFacilitator.isValidMainDictWord(word);
-                        mStatistics.recordWordEntered(
-                                isDictionaryWord, logUnit.containsUserDeletions());
-                    }
-                }
-                publishLogUnits(logUnits, mMainResearchLog, canIncludePrivateData);
-            }
-        };
-    }
-
-    private void cleanLogDirectoryIfNeeded(final ResearchLogDirectory researchLogDirectory,
-            final long now) {
-        final long lastCleanupTime = ResearchSettings.readResearchLastDirCleanupTime(mPrefs);
-        if (now - lastCleanupTime < DURATION_BETWEEN_DIR_CLEANUP_IN_MS) return;
-        final long oldestAllowedFileTime = now - MAX_LOGFILE_AGE_IN_MS;
-        mResearchLogDirectory.cleanupLogFilesOlderThan(oldestAllowedFileTime);
-        ResearchSettings.writeResearchLastDirCleanupTime(mPrefs, now);
-    }
-
-    public void mainKeyboardView_onAttachedToWindow(final MainKeyboardView mainKeyboardView) {
-        mMainKeyboardView = mainKeyboardView;
-        maybeShowSplashScreen();
-    }
-
-    public void mainKeyboardView_onDetachedFromWindow() {
-        mMainKeyboardView = null;
-    }
-
-    public void onDestroy() {
-        if (mPrefs != null) {
-            mPrefs.unregisterOnSharedPreferenceChangeListener(this);
-        }
-    }
-
-    private void maybeShowSplashScreen() {
-        if (ResearchSettings.readHasSeenSplash(mPrefs)) return;
-        if (mSplashScreen != null && mSplashScreen.isShowing()) return;
-        if (mMainKeyboardView == null) return;
-        final IBinder windowToken = mMainKeyboardView.getWindowToken();
-        if (windowToken == null) return;
-
-        mSplashScreen = new SplashScreen(mLatinIME, this);
-        mSplashScreen.showSplashScreen(windowToken);
-    }
-
-    @Override
-    public void onSplashScreenUserClickedOk() {
-        if (mPrefs == null) {
-            mPrefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME);
-            if (mPrefs == null) return;
-        }
-        sIsLogging = true;
-        ResearchSettings.writeResearchLoggerEnabledFlag(mPrefs, true);
-        ResearchSettings.writeHasSeenSplash(mPrefs, true);
-        restart();
-    }
-
-    private void checkForEmptyEditor() {
-        if (mLatinIME == null) {
-            return;
-        }
-        final InputConnection ic = mLatinIME.getCurrentInputConnection();
-        if (ic == null) {
-            return;
-        }
-        final CharSequence textBefore = ic.getTextBeforeCursor(1, 0);
-        if (!TextUtils.isEmpty(textBefore)) {
-            mStatistics.setIsEmptyUponStarting(false);
-            return;
-        }
-        final CharSequence textAfter = ic.getTextAfterCursor(1, 0);
-        if (!TextUtils.isEmpty(textAfter)) {
-            mStatistics.setIsEmptyUponStarting(false);
-            return;
-        }
-        if (textBefore != null && textAfter != null) {
-            mStatistics.setIsEmptyUponStarting(true);
-        }
-    }
-
-    private void start() {
-        if (DEBUG) {
-            Log.d(TAG, "start called");
-        }
-        maybeShowSplashScreen();
-        requestIndicatorRedraw();
-        mStatistics.reset();
-        checkForEmptyEditor();
-    }
-
-    /* package */ void stop() {
-        if (DEBUG) {
-            Log.d(TAG, "stop called");
-        }
-        // Commit mCurrentLogUnit before closing.
-        commitCurrentLogUnit();
-
-        try {
-            mMainLogBuffer.shiftAndPublishAll();
-        } catch (final IOException e) {
-            Log.w(TAG, "IOException when publishing LogBuffer", e);
-        }
-        logStatistics();
-        commitCurrentLogUnit();
-        mMainLogBuffer.setIsStopping();
-        try {
-            mMainLogBuffer.shiftAndPublishAll();
-        } catch (final IOException e) {
-            Log.w(TAG, "IOException when publishing LogBuffer", e);
-        }
-        mMainResearchLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
-
-        resetLogBuffers();
-        cancelFeedbackDialog();
-    }
-
-    public void abort() {
-        if (DEBUG) {
-            Log.d(TAG, "abort called");
-        }
-        mMainLogBuffer.clear();
-        mMainResearchLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
-
-        resetLogBuffers();
-    }
-
-    private void restart() {
-        stop();
-        start();
-    }
-
-    @Override
-    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
-        if (key == null || prefs == null) {
-            return;
-        }
-        requestIndicatorRedraw();
-        mPrefs = prefs;
-        prefsChanged(prefs);
-    }
-
-    public void onResearchKeySelected(final LatinIME latinIME) {
-        mCurrentLogUnit.removeResearchButtonInvocation();
-        if (mInFeedbackDialog) {
-            Toast.makeText(latinIME, R.string.research_please_exit_feedback_form,
-                    Toast.LENGTH_LONG).show();
-            return;
-        }
-        presentFeedbackDialog(latinIME);
-    }
-
-    public void presentFeedbackDialogFromSettings() {
-        if (mLatinIME != null) {
-            presentFeedbackDialog(mLatinIME);
-        }
-    }
-
-    public void presentFeedbackDialog(final LatinIME latinIME) {
-        if (isMakingUserRecording()) {
-            saveRecording();
-        }
-        mInFeedbackDialog = true;
-
-        final Intent intent = new Intent();
-        intent.setClass(mLatinIME, FeedbackActivity.class);
-        if (mFeedbackDialogBundle == null) {
-            // Restore feedback field with channel name
-            final Bundle bundle = new Bundle();
-            bundle.putBoolean(FeedbackFragment.KEY_INCLUDE_ACCOUNT_NAME, true);
-            bundle.putBoolean(FeedbackFragment.KEY_HAS_USER_RECORDING, false);
-            if (FEEDBACK_DIALOG_SHOULD_PRESERVE_TEXT_FIELD) {
-                final String savedChannelName = mPrefs.getString(PREF_RESEARCH_SAVED_CHANNEL, "");
-                bundle.putString(FeedbackFragment.KEY_FEEDBACK_STRING, savedChannelName);
-            }
-            mFeedbackDialogBundle = bundle;
-        }
-        intent.putExtras(mFeedbackDialogBundle);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        latinIME.startActivity(intent);
-    }
-
-    public void setFeedbackDialogBundle(final Bundle bundle) {
-        mFeedbackDialogBundle = bundle;
-    }
-
-    public void startRecording() {
-        final Resources res = mLatinIME.getResources();
-        Toast.makeText(mLatinIME,
-                res.getString(R.string.research_feedback_demonstration_instructions),
-                Toast.LENGTH_LONG).show();
-        startRecordingInternal();
-    }
-
-    private void startRecordingInternal() {
-        if (mUserRecordingLog != null) {
-            mUserRecordingLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
-        }
-        mUserRecordingFile = mResearchLogDirectory.getUserRecordingFilePath(
-                System.currentTimeMillis(), System.nanoTime());
-        mUserRecordingLog = new ResearchLog(mUserRecordingFile, mLatinIME);
-        mUserRecordingLogBuffer = new LogBuffer();
-        resetRecordingTimer();
-    }
-
-    private boolean isMakingUserRecording() {
-        return mUserRecordingLog != null;
-    }
-
-    private void resetRecordingTimer() {
-        if (mUserRecordingTimeoutHandler == null) {
-            mUserRecordingTimeoutHandler = new Handler();
-        }
-        clearRecordingTimer();
-        mUserRecordingTimeoutHandler.postDelayed(mRecordingHandlerTimeoutRunnable,
-                USER_RECORDING_TIMEOUT_MS);
-    }
-
-    private void clearRecordingTimer() {
-        mUserRecordingTimeoutHandler.removeCallbacks(mRecordingHandlerTimeoutRunnable);
-    }
-
-    private Runnable mRecordingHandlerTimeoutRunnable = new Runnable() {
-        @Override
-        public void run() {
-            cancelRecording();
-            requestIndicatorRedraw();
-            final Resources res = mLatinIME.getResources();
-            Toast.makeText(mLatinIME, res.getString(R.string.research_feedback_recording_failure),
-                    Toast.LENGTH_LONG).show();
-        }
-    };
-
-    private void cancelRecording() {
-        if (mUserRecordingLog != null) {
-            mUserRecordingLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
-        }
-        mUserRecordingLog = null;
-        mUserRecordingLogBuffer = null;
-        if (mFeedbackDialogBundle != null) {
-            mFeedbackDialogBundle.putBoolean("HasRecording", false);
-        }
-    }
-
-    private void saveRecording() {
-        commitCurrentLogUnit();
-        publishLogBuffer(mUserRecordingLogBuffer, mUserRecordingLog, true);
-        mUserRecordingLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
-        mUserRecordingLog = null;
-        mUserRecordingLogBuffer = null;
-
-        if (mFeedbackDialogBundle != null) {
-            mFeedbackDialogBundle.putBoolean(FeedbackFragment.KEY_HAS_USER_RECORDING, true);
-        }
-        clearRecordingTimer();
-    }
-
-    // TODO: currently unreachable.  Remove after being sure enable/disable is
-    // not needed.
-    /*
-    public void enableOrDisable(final boolean showEnable, final LatinIME latinIME) {
-        if (showEnable) {
-            if (!sIsLogging) {
-                setLoggingAllowed(true);
-            }
-            resumeLogging();
-            Toast.makeText(latinIME,
-                    R.string.research_notify_session_logging_enabled,
-                    Toast.LENGTH_LONG).show();
-        } else {
-            Toast toast = Toast.makeText(latinIME,
-                    R.string.research_notify_session_log_deleting,
-                    Toast.LENGTH_LONG);
-            toast.show();
-            boolean isLogDeleted = abort();
-            final long currentTime = System.currentTimeMillis();
-            final long resumeTime = currentTime
-                    + TimeUnit.MINUTES.toMillis(SUSPEND_DURATION_IN_MINUTES);
-            suspendLoggingUntil(resumeTime);
-            toast.cancel();
-            Toast.makeText(latinIME, R.string.research_notify_logging_suspended,
-                    Toast.LENGTH_LONG).show();
-        }
-    }
-    */
-
-    /**
-     * Get the name of the first allowed account on the device.
-     *
-     * Allowed accounts must be in the domain given by ALLOWED_ACCOUNT_DOMAIN.
-     *
-     * @return The user's account name.
-     */
-    public String getAccountName() {
-        if (sAccountType == null || sAccountType.isEmpty()) {
-            return null;
-        }
-        if (sAllowedAccountDomain == null || sAllowedAccountDomain.isEmpty()) {
-            return null;
-        }
-        final AccountManager manager = AccountManager.get(mLatinIME);
-        // Filter first by account type.
-        final Account[] accounts = manager.getAccountsByType(sAccountType);
-
-        for (final Account account : accounts) {
-            if (DEBUG) {
-                Log.d(TAG, account.name);
-            }
-            final String[] parts = account.name.split("@");
-            if (parts.length > 1 && parts[1].equals(sAllowedAccountDomain)) {
-                return parts[0];
-            }
-        }
-        return null;
-    }
-
-    private static final LogStatement LOGSTATEMENT_FEEDBACK =
-            new LogStatement("UserFeedback", false, false, "contents", "accountName", "recording");
-    public void sendFeedback(final String feedbackContents, final boolean includeHistory,
-            final boolean isIncludingAccountName, final boolean isIncludingRecording) {
-        String recording = "";
-        if (isIncludingRecording) {
-            // Try to read recording from recently written json file
-            if (mUserRecordingFile != null) {
-                FileChannel channel = null;
-                try {
-                    channel = new FileInputStream(mUserRecordingFile).getChannel();
-                    final MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0,
-                            channel.size());
-                    // Android's openFileOutput() creates the file, so we use Android's default
-                    // Charset (UTF-8) here to read it.
-                    recording = Charset.defaultCharset().decode(buffer).toString();
-                } catch (FileNotFoundException e) {
-                    Log.e(TAG, "Could not find recording file", e);
-                } catch (IOException e) {
-                    Log.e(TAG, "Error reading recording file", e);
-                } finally {
-                    if (channel != null) {
-                        try {
-                            channel.close();
-                        } catch (IOException e) {
-                            Log.e(TAG, "Error closing recording file", e);
-                        }
-                    }
-                }
-            }
-        }
-        final LogUnit feedbackLogUnit = new LogUnit();
-        final String accountName = isIncludingAccountName ? getAccountName() : "";
-        feedbackLogUnit.addLogStatement(LOGSTATEMENT_FEEDBACK, SystemClock.uptimeMillis(),
-                feedbackContents, accountName, recording);
-
-        final ResearchLog feedbackLog = new FeedbackLog(mResearchLogDirectory.getLogFilePath(
-                System.currentTimeMillis(), System.nanoTime()), mLatinIME);
-        final LogBuffer feedbackLogBuffer = new LogBuffer();
-        feedbackLogBuffer.shiftIn(feedbackLogUnit);
-        publishLogBuffer(feedbackLogBuffer, feedbackLog, true /* isIncludingPrivateData */);
-        feedbackLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
-        uploadNow();
-
-        if (isIncludingRecording && DEBUG_REPLAY_AFTER_FEEDBACK) {
-            final Handler handler = new Handler();
-            handler.postDelayed(new Runnable() {
-                @Override
-                public void run() {
-                    final ReplayData replayData =
-                            mMotionEventReader.readMotionEventData(mUserRecordingFile);
-                    mReplayer.replay(replayData, null);
-                }
-            }, TimeUnit.SECONDS.toMillis(1));
-        }
-
-        if (FEEDBACK_DIALOG_SHOULD_PRESERVE_TEXT_FIELD) {
-            // Use feedback string as a channel name to label feedback strings.  Here we record the
-            // string for prepopulating the field next time.
-            final String channelName = feedbackContents;
-            if (mPrefs == null) {
-                return;
-            }
-            mPrefs.edit().putString(PREF_RESEARCH_SAVED_CHANNEL, channelName).apply();
-        }
-    }
-
-    public void uploadNow() {
-        if (DEBUG) {
-            Log.d(TAG, "calling uploadNow()");
-        }
-        mLatinIME.startService(mUploadNowIntent);
-    }
-
-    public void onLeavingSendFeedbackDialog() {
-        mInFeedbackDialog = false;
-    }
-
-    private void cancelFeedbackDialog() {
-        if (isMakingUserRecording()) {
-            cancelRecording();
-        }
-        mInFeedbackDialog = false;
-    }
-
-    public void initDictionary(final DictionaryFacilitator dictionaryFacilitator) {
-        mDictionaryFacilitator = dictionaryFacilitator;
-        // MainLogBuffer now has an out-of-date Suggest object.  Close down MainLogBuffer and create
-        // a new one.
-        if (mMainLogBuffer != null) {
-            restart();
-        }
-    }
-
-    private void setIsPasswordView(boolean isPasswordView) {
-        mIsPasswordView = isPasswordView;
-    }
-
-    /**
-     * Returns true if logging is permitted.
-     *
-     * This method is called when adding a LogStatement to a LogUnit, and when adding a LogUnit to a
-     * ResearchLog.  It is checked in both places in case conditions change between these times, and
-     * as a defensive measure in case refactoring changes the logging pipeline.
-     */
-    private boolean isAllowedToLogTo(final ResearchLog researchLog) {
-        // Logging is never allowed in these circumstances
-        if (mIsPasswordView) return false;
-        if (!sIsLogging) return false;
-        if (mInFeedbackDialog) {
-            // The FeedbackDialog is up.  Normal logging should not happen (the user might be trying
-            // out things while the dialog is up, and their reporting of an issue may not be
-            // representative of what they normally type).  However, after the user has finished
-            // entering their feedback, the logger packs their comments and an encoded version of
-            // any demonstration of the issue into a special "FeedbackLog".  So if the FeedbackLog
-            // is the destination, we do want to allow logging to it.
-            return researchLog.isFeedbackLog();
-        }
-        // No other exclusions.  Logging is permitted.
-        return true;
-    }
-
-    public void requestIndicatorRedraw() {
-        if (!IS_SHOWING_INDICATOR) {
-            return;
-        }
-        if (mMainKeyboardView == null) {
-            return;
-        }
-        mMainKeyboardView.invalidateAllKeys();
-    }
-
-    private boolean isReplaying() {
-        return mReplayer.isReplaying();
-    }
-
-    private int getIndicatorColor() {
-        if (isMakingUserRecording()) {
-            return Color.YELLOW;
-        }
-        if (isReplaying()) {
-            return Color.GREEN;
-        }
-        return Color.RED;
-    }
-
-    public void paintIndicator(KeyboardView view, Paint paint, Canvas canvas, int width,
-            int height) {
-        // TODO: Reimplement using a keyboard background image specific to the ResearchLogger
-        // and remove this method.
-        // The check for MainKeyboardView ensures that the indicator only decorates the main
-        // keyboard, not every keyboard.
-        if (IS_SHOWING_INDICATOR && (isAllowedToLogTo(mMainResearchLog) || isReplaying())
-                && view instanceof MainKeyboardView) {
-            final int savedColor = paint.getColor();
-            paint.setColor(getIndicatorColor());
-            final Style savedStyle = paint.getStyle();
-            paint.setStyle(Style.STROKE);
-            final float savedStrokeWidth = paint.getStrokeWidth();
-            if (IS_SHOWING_INDICATOR_CLEARLY) {
-                paint.setStrokeWidth(5);
-                canvas.drawLine(0, 0, 0, height, paint);
-                canvas.drawLine(width, 0, width, height, paint);
-            } else {
-                // Put a tiny dot on the screen so a knowledgeable user can check whether it is
-                // enabled.  The dot is actually a zero-width, zero-height rectangle, placed at the
-                // lower-right corner of the canvas, painted with a non-zero border width.
-                paint.setStrokeWidth(3);
-                canvas.drawRect(width - 1, height - 1, width, height, paint);
-            }
-            paint.setColor(savedColor);
-            paint.setStyle(savedStyle);
-            paint.setStrokeWidth(savedStrokeWidth);
-        }
-    }
-
-    /**
-     * Buffer a research log event, flagging it as privacy-sensitive.
-     */
-    private synchronized void enqueueEvent(final LogStatement logStatement,
-            final Object... values) {
-        enqueueEvent(mCurrentLogUnit, logStatement, values);
-    }
-
-    private synchronized void enqueueEvent(final LogUnit logUnit, final LogStatement logStatement,
-            final Object... values) {
-        assert values.length == logStatement.getKeys().length;
-        if (isAllowedToLogTo(mMainResearchLog) && logUnit != null) {
-            final long time = SystemClock.uptimeMillis();
-            logUnit.addLogStatement(logStatement, time, values);
-        }
-    }
-
-    private void setCurrentLogUnitContainsDigitFlag() {
-        mCurrentLogUnit.setMayContainDigit();
-    }
-
-    private void setCurrentLogUnitContainsUserDeletions() {
-        mCurrentLogUnit.setContainsUserDeletions();
-    }
-
-    private void setCurrentLogUnitCorrectionType(final int correctionType) {
-        mCurrentLogUnit.setCorrectionType(correctionType);
-    }
-
-    /* package for test */ void commitCurrentLogUnit() {
-        if (DEBUG) {
-            Log.d(TAG, "commitCurrentLogUnit" + (mCurrentLogUnit.hasOneOrMoreWords() ?
-                    ": " + mCurrentLogUnit.getWordsAsString() : ""));
-        }
-        if (!mCurrentLogUnit.isEmpty()) {
-            mMainLogBuffer.shiftIn(mCurrentLogUnit);
-            if (mUserRecordingLogBuffer != null) {
-                mUserRecordingLogBuffer.shiftIn(mCurrentLogUnit);
-            }
-            mCurrentLogUnit = new LogUnit();
-        } else {
-            if (DEBUG) {
-                Log.d(TAG, "Warning: tried to commit empty log unit.");
-            }
-        }
-    }
-
-    private static final LogStatement LOGSTATEMENT_UNCOMMIT_CURRENT_LOGUNIT =
-            new LogStatement("UncommitCurrentLogUnit", false, false);
-    public void uncommitCurrentLogUnit(final String expectedWord,
-            final boolean dumpCurrentLogUnit) {
-        // The user has deleted this word and returned to the previous.  Check that the word in the
-        // logUnit matches the expected word.  If so, restore the last log unit committed to be the
-        // current logUnit.  I.e., pull out the last LogUnit from all the LogBuffers, and make
-        // it the mCurrentLogUnit so the new edits are captured with the word.  Optionally dump the
-        // contents of mCurrentLogUnit (useful if they contain deletions of the next word that
-        // should not be reported to protect user privacy)
-        //
-        // Note that we don't use mLastLogUnit here, because it only goes one word back and is only
-        // needed for reverts, which only happen one back.
-        final LogUnit oldLogUnit = mMainLogBuffer.peekLastLogUnit();
-
-        // Check that expected word matches.  It's ok if both strings are null, because this is the
-        // case where the LogUnit is storing a non-word, e.g. a separator.
-        if (oldLogUnit != null) {
-            // Because the word is stored in the LogUnit with digits scrubbed, the comparison must
-            // be made on a scrubbed version of the expectedWord as well.
-            final String scrubbedExpectedWord = scrubDigitsFromString(expectedWord);
-            final String oldLogUnitWords = oldLogUnit.getWordsAsString();
-            if (!TextUtils.equals(scrubbedExpectedWord, oldLogUnitWords)) return;
-        }
-
-        // Uncommit, merging if necessary.
-        mMainLogBuffer.unshiftIn();
-        if (oldLogUnit != null && !dumpCurrentLogUnit) {
-            oldLogUnit.append(mCurrentLogUnit);
-            mSavedDownEventTime = Long.MAX_VALUE;
-        }
-        if (oldLogUnit == null) {
-            mCurrentLogUnit = new LogUnit();
-        } else {
-            mCurrentLogUnit = oldLogUnit;
-        }
-        enqueueEvent(LOGSTATEMENT_UNCOMMIT_CURRENT_LOGUNIT);
-        if (DEBUG) {
-            Log.d(TAG, "uncommitCurrentLogUnit (dump=" + dumpCurrentLogUnit + ") back to "
-                    + (mCurrentLogUnit.hasOneOrMoreWords() ? ": '"
-                        + mCurrentLogUnit.getWordsAsString() + "'" : ""));
-        }
-    }
-
-    /**
-     * Publish all the logUnits in the logBuffer, without doing any privacy filtering.
-     */
-    /* package for test */ void publishLogBuffer(final LogBuffer logBuffer,
-            final ResearchLog researchLog, final boolean canIncludePrivateData) {
-        publishLogUnits(logBuffer.getLogUnits(), researchLog, canIncludePrivateData);
-    }
-
-    private static final LogStatement LOGSTATEMENT_LOG_SEGMENT_OPENING =
-            new LogStatement("logSegmentStart", false, false, "isIncludingPrivateData");
-    private static final LogStatement LOGSTATEMENT_LOG_SEGMENT_CLOSING =
-            new LogStatement("logSegmentEnd", false, false);
-    /**
-     * Publish all LogUnits in a list.
-     *
-     * Any privacy checks should be performed before calling this method.
-     */
-    /* package for test */ void publishLogUnits(final List<LogUnit> logUnits,
-            final ResearchLog researchLog, final boolean canIncludePrivateData) {
-        final LogUnit openingLogUnit = new LogUnit();
-        if (logUnits.isEmpty()) return;
-        if (!isAllowedToLogTo(researchLog)) return;
-        // LogUnits not containing private data, such as contextual data for the log, do not require
-        // logSegment boundary statements.
-        if (canIncludePrivateData) {
-            openingLogUnit.addLogStatement(LOGSTATEMENT_LOG_SEGMENT_OPENING,
-                    SystemClock.uptimeMillis(), canIncludePrivateData);
-            researchLog.publish(openingLogUnit, true /* isIncludingPrivateData */);
-        }
-        for (LogUnit logUnit : logUnits) {
-            if (DEBUG) {
-                Log.d(TAG, "publishLogBuffer: " + (logUnit.hasOneOrMoreWords()
-                        ? logUnit.getWordsAsString() : "<wordless>")
-                        + ", correction?: " + logUnit.containsUserDeletions());
-            }
-            researchLog.publish(logUnit, canIncludePrivateData);
-        }
-        if (canIncludePrivateData) {
-            final LogUnit closingLogUnit = new LogUnit();
-            closingLogUnit.addLogStatement(LOGSTATEMENT_LOG_SEGMENT_CLOSING,
-                    SystemClock.uptimeMillis());
-            researchLog.publish(closingLogUnit, true /* isIncludingPrivateData */);
-        }
-    }
-
-    public static boolean hasLetters(final String word) {
-        final int length = word.length();
-        for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
-            final int codePoint = word.codePointAt(i);
-            if (Character.isLetter(codePoint)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Commit the portion of mCurrentLogUnit before maxTime as a worded logUnit.
-     *
-     * After this operation completes, mCurrentLogUnit will hold any logStatements that happened
-     * after maxTime.
-     */
-    /* package for test */ void commitCurrentLogUnitAsWord(final String word, final long maxTime,
-            final boolean isBatchMode) {
-        if (word == null) {
-            return;
-        }
-        if (word.length() > 0 && hasLetters(word)) {
-            mCurrentLogUnit.setWords(word);
-        }
-        final LogUnit newLogUnit = mCurrentLogUnit.splitByTime(maxTime);
-        enqueueCommitText(word, isBatchMode);
-        commitCurrentLogUnit();
-        mCurrentLogUnit = newLogUnit;
-    }
-
-    /**
-     * Record the time of a MotionEvent.ACTION_DOWN.
-     *
-     * Warning: Not thread safe.  Only call from the main thread.
-     */
-    private void setSavedDownEventTime(final long time) {
-        mSavedDownEventTime = time;
-    }
-
-    public void onWordFinished(final String word, final boolean isBatchMode) {
-        commitCurrentLogUnitAsWord(word, mSavedDownEventTime, isBatchMode);
-        mSavedDownEventTime = Long.MAX_VALUE;
-    }
-
-    private static int scrubDigitFromCodePoint(int codePoint) {
-        return Character.isDigit(codePoint) ? DIGIT_REPLACEMENT_CODEPOINT : codePoint;
-    }
-
-    /* package for test */ static String scrubDigitsFromString(final String s) {
-        if (s == null) return null;
-        StringBuilder sb = null;
-        final int length = s.length();
-        for (int i = 0; i < length; i = s.offsetByCodePoints(i, 1)) {
-            final int codePoint = Character.codePointAt(s, i);
-            if (Character.isDigit(codePoint)) {
-                if (sb == null) {
-                    sb = new StringBuilder(length);
-                    sb.append(s.substring(0, i));
-                }
-                sb.appendCodePoint(DIGIT_REPLACEMENT_CODEPOINT);
-            } else {
-                if (sb != null) {
-                    sb.appendCodePoint(codePoint);
-                }
-            }
-        }
-        if (sb == null) {
-            return s;
-        } else {
-            return sb.toString();
-        }
-    }
-
-    private String scrubWord(String word) {
-        if (mDictionaryFacilitator != null && mDictionaryFacilitator.isValidMainDictWord(word)) {
-            return word;
-        }
-        return WORD_REPLACEMENT_STRING;
-    }
-
-    // Specific logging methods follow below.  The comments for each logging method should
-    // indicate what specific method is logged, and how to trigger it from the user interface.
-    //
-    // Logging methods can be generally classified into two flavors, "UserAction", which should
-    // correspond closely to an event that is sensed by the IME, and is usually generated
-    // directly by the user, and "SystemResponse" which corresponds to an event that the IME
-    // generates, often after much processing of user input.  SystemResponses should correspond
-    // closely to user-visible events.
-    // TODO: Consider exposing the UserAction classification in the log output.
-
-    /**
-     * Log a call to LatinIME.onStartInputViewInternal().
-     *
-     * UserAction: called each time the keyboard is opened up.
-     */
-    private static final LogStatement LOGSTATEMENT_LATIN_IME_ON_START_INPUT_VIEW_INTERNAL =
-            new LogStatement("LatinImeOnStartInputViewInternal", false, false, "uuid",
-                    "packageName", "inputType", "imeOptions", "fieldId", "display", "model",
-                    "prefs", "versionCode", "versionName", "outputFormatVersion", "logEverything",
-                    "isDevTeamBuild");
-    public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
-            final SharedPreferences prefs) {
-        final ResearchLogger researchLogger = getInstance();
-        if (editorInfo != null) {
-            final boolean isPassword = InputTypeUtils.isPasswordInputType(editorInfo.inputType)
-                    || InputTypeUtils.isVisiblePasswordInputType(editorInfo.inputType);
-            getInstance().setIsPasswordView(isPassword);
-            researchLogger.start();
-            final Context context = researchLogger.mLatinIME;
-            try {
-                final PackageInfo packageInfo;
-                packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),
-                        0);
-                final Integer versionCode = packageInfo.versionCode;
-                final String versionName = packageInfo.versionName;
-                final String uuid = ResearchSettings.readResearchLoggerUuid(researchLogger.mPrefs);
-                researchLogger.enqueueEvent(LOGSTATEMENT_LATIN_IME_ON_START_INPUT_VIEW_INTERNAL,
-                        uuid, editorInfo.packageName, Integer.toHexString(editorInfo.inputType),
-                        Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId,
-                        Build.DISPLAY, Build.MODEL, prefs, versionCode, versionName,
-                        OUTPUT_FORMAT_VERSION, IS_LOGGING_EVERYTHING,
-                        researchLogger.isDevTeamBuild());
-                // Commit the logUnit so the LatinImeOnStartInputViewInternal event is in its own
-                // logUnit at the beginning of the log.
-                researchLogger.commitCurrentLogUnit();
-            } catch (final NameNotFoundException e) {
-                Log.e(TAG, "NameNotFound", e);
-            }
-        }
-    }
-
-    // TODO: Update this heuristic pattern to something more reliable.  Developer builds tend to
-    // have the developer name and year embedded.
-    private static final Pattern developerBuildRegex = Pattern.compile("[A-Za-z]\\.20[1-9]");
-    private boolean isDevTeamBuild() {
-        try {
-            final PackageInfo packageInfo;
-            packageInfo = mLatinIME.getPackageManager().getPackageInfo(mLatinIME.getPackageName(),
-                    0);
-            final String versionName = packageInfo.versionName;
-            return developerBuildRegex.matcher(versionName).find();
-        } catch (final NameNotFoundException e) {
-            Log.e(TAG, "Could not determine package name", e);
-            return false;
-        }
-    }
-
-    /**
-     * Log a change in preferences.
-     *
-     * UserAction: called when the user changes the settings.
-     */
-    private static final LogStatement LOGSTATEMENT_PREFS_CHANGED =
-            new LogStatement("PrefsChanged", false, false, "prefs");
-    public static void prefsChanged(final SharedPreferences prefs) {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.enqueueEvent(LOGSTATEMENT_PREFS_CHANGED, prefs);
-    }
-
-    /**
-     * Log a call to MainKeyboardView.processMotionEvent().
-     *
-     * UserAction: called when the user puts their finger onto the screen (ACTION_DOWN).
-     *
-     */
-    private static final LogStatement LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT =
-            new LogStatement("MotionEvent", true, false, "action",
-                    LogStatement.KEY_IS_LOGGING_RELATED, "motionEvent");
-    public static void mainKeyboardView_processMotionEvent(final MotionEvent me) {
-        if (me == null) {
-            return;
-        }
-        final int action = me.getActionMasked();
-        final long eventTime = me.getEventTime();
-        final String actionString = LoggingUtils.getMotionEventActionTypeString(action);
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.enqueueEvent(LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT,
-                actionString, false /* IS_LOGGING_RELATED */, MotionEvent.obtain(me));
-        if (action == MotionEvent.ACTION_DOWN) {
-            // Subtract 1 from eventTime so the down event is included in the later
-            // LogUnit, not the earlier (the test is for inequality).
-            researchLogger.setSavedDownEventTime(eventTime - 1);
-        }
-        // Refresh the timer in case we are capturing user feedback.
-        if (researchLogger.isMakingUserRecording()) {
-            researchLogger.resetRecordingTimer();
-        }
-    }
-
-    /**
-     * Log a call to LatinIME.onCodeInput().
-     *
-     * SystemResponse: The main processing step for entering text.  Called when the user performs a
-     * tap, a flick, a long press, releases a gesture, or taps a punctuation suggestion.
-     */
-    private static final LogStatement LOGSTATEMENT_LATIN_IME_ON_CODE_INPUT =
-            new LogStatement("LatinImeOnCodeInput", true, false, "code", "x", "y");
-    public static void latinIME_onCodeInput(final int code, final int x, final int y) {
-        final long time = SystemClock.uptimeMillis();
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.enqueueEvent(LOGSTATEMENT_LATIN_IME_ON_CODE_INPUT,
-                Constants.printableCode(scrubDigitFromCodePoint(code)), x, y);
-        if (Character.isDigit(code)) {
-            researchLogger.setCurrentLogUnitContainsDigitFlag();
-        }
-        researchLogger.mStatistics.recordChar(code, time);
-    }
-    /**
-     * Log a call to LatinIME.onDisplayCompletions().
-     *
-     * SystemResponse: The IME has displayed application-specific completions.  They may show up
-     * in the suggestion strip, such as a landscape phone.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_ONDISPLAYCOMPLETIONS =
-            new LogStatement("LatinIMEOnDisplayCompletions", true, true,
-                    "applicationSpecifiedCompletions");
-    public static void latinIME_onDisplayCompletions(
-            final CompletionInfo[] applicationSpecifiedCompletions) {
-        // Note; passing an array as a single element in a vararg list.  Must create a new
-        // dummy array around it or it will get expanded.
-        getInstance().enqueueEvent(LOGSTATEMENT_LATINIME_ONDISPLAYCOMPLETIONS,
-                new Object[] { applicationSpecifiedCompletions });
-    }
-
-    /**
-     * The IME is finishing; it is either being destroyed, or is about to be hidden.
-     *
-     * UserAction: The user has performed an action that has caused the IME to be closed.  They may
-     * have focused on something other than a text field, or explicitly closed it.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_ONFINISHINPUTVIEWINTERNAL =
-            new LogStatement("LatinIMEOnFinishInputViewInternal", false, false, "isTextTruncated",
-                    "text");
-    public static void latinIME_onFinishInputViewInternal(final boolean finishingInput) {
-        // The finishingInput flag is set in InputMethodService.  It is true if called from
-        // doFinishInput(), which can be called as part of doStartInput().  This can happen at times
-        // when the IME is not closing, such as when powering up.  The finishinInput flag is false
-        // if called from finishViews(), which is called from hideWindow() and onDestroy().  These
-        // are the situations in which we want to finish up the researchLog.
-        if (!finishingInput) {
-            final ResearchLogger researchLogger = getInstance();
-            // Assume that OUTPUT_ENTIRE_BUFFER is only true when we don't care about privacy (e.g.
-            // during a live user test), so the normal isPotentiallyPrivate and
-            // isPotentiallyRevealing flags do not apply
-            researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONFINISHINPUTVIEWINTERNAL,
-                    true /* isTextTruncated */, "" /* text */);
-            researchLogger.commitCurrentLogUnit();
-            getInstance().stop();
-        }
-    }
-
-    /**
-     * Log a call to LatinIME.onUpdateSelection().
-     *
-     * UserAction/SystemResponse: The user has moved the cursor or selection.  This function may
-     * be called, however, when the system has moved the cursor, say by inserting a character.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_ONUPDATESELECTION =
-            new LogStatement("LatinIMEOnUpdateSelection", true, false, "lastSelectionStart",
-                    "lastSelectionEnd", "oldSelStart", "oldSelEnd", "newSelStart", "newSelEnd",
-                    "composingSpanStart", "composingSpanEnd", "expectingUpdateSelection",
-                    "expectingUpdateSelectionFromLogger", "context");
-    public static void latinIME_onUpdateSelection(final int lastSelectionStart,
-            final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd,
-            final int newSelStart, final int newSelEnd, final int composingSpanStart,
-            final int composingSpanEnd, final RichInputConnection connection) {
-        String word = "";
-        if (connection != null) {
-            TextRange range = connection.getWordRangeAtCursor(WHITESPACE_SEPARATORS, 1);
-            if (range != null) {
-                word = range.mWord.toString();
-            }
-        }
-        final ResearchLogger researchLogger = getInstance();
-        final String scrubbedWord = researchLogger.scrubWord(word);
-        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONUPDATESELECTION, lastSelectionStart,
-                lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd,
-                composingSpanStart, composingSpanEnd, false /* expectingUpdateSelection */,
-                false /* expectingUpdateSelectionFromLogger */, scrubbedWord);
-    }
-
-    /**
-     * Log a call to LatinIME.onTextInput().
-     *
-     * SystemResponse: Raw text is added to the TextView.
-     */
-    public static void latinIME_onTextInput(final String text, final boolean isBatchMode) {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.commitCurrentLogUnitAsWord(text, Long.MAX_VALUE, isBatchMode);
-    }
-
-    /**
-     * Log a revert of onTextInput() (known in the IME as "EnteredText").
-     *
-     * SystemResponse: Remove the LogUnit recording the textInput
-     */
-    public static void latinIME_handleBackspace_cancelTextInput(final String text) {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.uncommitCurrentLogUnit(text, true /* dumpCurrentLogUnit */);
-    }
-
-    /**
-     * Log a call to LatinIME.pickSuggestionManually().
-     *
-     * UserAction: The user has chosen a specific word from the suggestion strip.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_PICKSUGGESTIONMANUALLY =
-            new LogStatement("LatinIMEPickSuggestionManually", true, false, "replacedWord", "index",
-                    "suggestion", "x", "y", "isBatchMode", "score", "kind", "sourceDict");
-    /**
-     * Log a call to LatinIME.pickSuggestionManually().
-     *
-     * @param replacedWord the typed word that this manual suggestion replaces. May not be null.
-     * @param index the index in the suggestion strip
-     * @param suggestion the committed suggestion. May not be null.
-     * @param isBatchMode whether this was input in batch mode, aka gesture.
-     * @param score the internal score of the suggestion, as output by the dictionary
-     * @param kind the kind of suggestion, as one of the SuggestedWordInfo#KIND_* constants
-     * @param sourceDict the source origin of this word, as one of the Dictionary#TYPE_* constants.
-     */
-    public static void latinIME_pickSuggestionManually(final String replacedWord,
-            final int index, final String suggestion, final boolean isBatchMode,
-            final int score, final int kind, final String sourceDict) {
-        final ResearchLogger researchLogger = getInstance();
-        // Note : suggestion can't be null here, because it's only called in a place where it
-        // can't be null.
-        if (!replacedWord.equals(suggestion.toString())) {
-            // The user chose something other than what was already there.
-            researchLogger.setCurrentLogUnitContainsUserDeletions();
-            researchLogger.setCurrentLogUnitCorrectionType(LogUnit.CORRECTIONTYPE_TYPO);
-        }
-        final String scrubbedWord = scrubDigitsFromString(suggestion);
-        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_PICKSUGGESTIONMANUALLY,
-                scrubDigitsFromString(replacedWord), index,
-                scrubbedWord, Constants.SUGGESTION_STRIP_COORDINATE,
-                Constants.SUGGESTION_STRIP_COORDINATE, isBatchMode, score, kind, sourceDict);
-        researchLogger.commitCurrentLogUnitAsWord(scrubbedWord, Long.MAX_VALUE, isBatchMode);
-        researchLogger.mStatistics.recordManualSuggestion(SystemClock.uptimeMillis());
-    }
-
-    /**
-     * Log a call to LatinIME.punctuationSuggestion().
-     *
-     * UserAction: The user has chosen punctuation from the punctuation suggestion strip.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_PUNCTUATIONSUGGESTION =
-            new LogStatement("LatinIMEPunctuationSuggestion", false, false, "index", "suggestion",
-                    "x", "y", "isPrediction");
-    public static void latinIME_punctuationSuggestion(final int index, final String suggestion,
-            final boolean isBatchMode, final boolean isPrediction) {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_PUNCTUATIONSUGGESTION, index, suggestion,
-                Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE,
-                isPrediction);
-        researchLogger.commitCurrentLogUnitAsWord(suggestion, Long.MAX_VALUE, isBatchMode);
-    }
-
-    /**
-     * Log a call to LatinIME.sendKeyCodePoint().
-     *
-     * SystemResponse: The IME is inserting text into the TextView for non-word-constituent,
-     * strings (separators, numbers, other symbols).
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_SENDKEYCODEPOINT =
-            new LogStatement("LatinIMESendKeyCodePoint", true, false, "code");
-    public static void latinIME_sendKeyCodePoint(final int code) {
-        final ResearchLogger researchLogger = getInstance();
-        final LogUnit phantomSpaceLogUnit = researchLogger.mPhantomSpaceLogUnit;
-        if (phantomSpaceLogUnit == null) {
-            researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_SENDKEYCODEPOINT,
-                    Constants.printableCode(scrubDigitFromCodePoint(code)));
-            if (Character.isDigit(code)) {
-                researchLogger.setCurrentLogUnitContainsDigitFlag();
-            }
-            researchLogger.commitCurrentLogUnit();
-        } else {
-            researchLogger.enqueueEvent(phantomSpaceLogUnit, LOGSTATEMENT_LATINIME_SENDKEYCODEPOINT,
-                    Constants.printableCode(scrubDigitFromCodePoint(code)));
-            if (Character.isDigit(code)) {
-                phantomSpaceLogUnit.setMayContainDigit();
-            }
-            researchLogger.mMainLogBuffer.shiftIn(phantomSpaceLogUnit);
-            if (researchLogger.mUserRecordingLogBuffer != null) {
-                researchLogger.mUserRecordingLogBuffer.shiftIn(phantomSpaceLogUnit);
-            }
-            researchLogger.mPhantomSpaceLogUnit = null;
-        }
-    }
-
-    /**
-     * Log a call to LatinIME.promotePhantomSpace().
-     *
-     * SystemResponse: The IME is inserting a real space in place of a phantom space.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_PROMOTEPHANTOMSPACE =
-            new LogStatement("LatinIMEPromotePhantomSpace", false, false);
-    public static void latinIME_promotePhantomSpace() {
-        // A phantom space is always added before the text that triggered it.  The triggering text
-        // and the events that created it will be in mCurrentLogUnit, but the phantom space should
-        // be in its own LogUnit, committed before the triggering text.  Although it is created
-        // here, it is not added to the LogBuffer until the following call to
-        // latinIME_sendKeyCodePoint, because SENDKEYCODEPOINT LogStatement also must go into that
-        // LogUnit.
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.mPhantomSpaceLogUnit = new LogUnit();
-        researchLogger.enqueueEvent(researchLogger.mPhantomSpaceLogUnit,
-                LOGSTATEMENT_LATINIME_PROMOTEPHANTOMSPACE);
-    }
-
-    /**
-     * Log a call to LatinIME.swapSwapperAndSpace().
-     *
-     * SystemResponse: A symbol has been swapped with a space character.  E.g. punctuation may swap
-     * if a soft space is inserted after a word.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_SWAPSWAPPERANDSPACE =
-            new LogStatement("LatinIMESwapSwapperAndSpace", false, false, "originalCharacters",
-                    "charactersAfterSwap");
-    public static void latinIME_swapSwapperAndSpace(final CharSequence originalCharacters,
-            final String charactersAfterSwap) {
-        final ResearchLogger researchLogger = getInstance();
-        final LogUnit logUnit;
-        logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
-        if (logUnit != null) {
-            researchLogger.enqueueEvent(logUnit, LOGSTATEMENT_LATINIME_SWAPSWAPPERANDSPACE,
-                    originalCharacters, charactersAfterSwap);
-        }
-    }
-
-    /**
-     * Log a call to LatinIME.maybeDoubleSpacePeriod().
-     *
-     * SystemResponse: Two spaces have been replaced by period space.
-     */
-    public static void latinIME_maybeDoubleSpacePeriod(final String text,
-            final boolean isBatchMode) {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.commitCurrentLogUnitAsWord(text, Long.MAX_VALUE, isBatchMode);
-    }
-
-    /**
-     * Log a call to MainKeyboardView.onLongPress().
-     *
-     * UserAction: The user has performed a long-press on a key.
-     */
-    private static final LogStatement LOGSTATEMENT_MAINKEYBOARDVIEW_ONLONGPRESS =
-            new LogStatement("MainKeyboardViewOnLongPress", false, false);
-    public static void mainKeyboardView_onLongPress() {
-        getInstance().enqueueEvent(LOGSTATEMENT_MAINKEYBOARDVIEW_ONLONGPRESS);
-    }
-
-    /**
-     * Log a call to MainKeyboardView.setKeyboard().
-     *
-     * SystemResponse: The IME has switched to a new keyboard (e.g. French, English).
-     * This is typically called right after LatinIME.onStartInputViewInternal (when starting a new
-     * IME), but may happen at other times if the user explicitly requests a keyboard change.
-     */
-    private static final LogStatement LOGSTATEMENT_MAINKEYBOARDVIEW_SETKEYBOARD =
-            new LogStatement("MainKeyboardViewSetKeyboard", false, false, "elementId", "locale",
-                    "orientation", "width", "modeName", "action", "navigateNext",
-                    "navigatePrevious", "clobberSettingsKey", "passwordInput",
-                    "supportsSwitchingToShortcutIme", "hasShortcutKey", "languageSwitchKeyEnabled",
-                    "isMultiLine", "tw", "th",
-                    "keys");
-    public static void mainKeyboardView_setKeyboard(final Keyboard keyboard,
-            final int orientation) {
-        final KeyboardId kid = keyboard.mId;
-        final boolean isPasswordView = kid.passwordInput();
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.setIsPasswordView(isPasswordView);
-        researchLogger.enqueueEvent(LOGSTATEMENT_MAINKEYBOARDVIEW_SETKEYBOARD,
-                KeyboardId.elementIdToName(kid.mElementId),
-                kid.mLocale + ":" + kid.mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
-                orientation, kid.mWidth, KeyboardId.modeName(kid.mMode), kid.imeAction(),
-                kid.navigateNext(), kid.navigatePrevious(), kid.mClobberSettingsKey,
-                isPasswordView, kid.mSupportsSwitchingToShortcutIme, kid.mHasShortcutKey,
-                kid.mLanguageSwitchKeyEnabled, kid.isMultiLine(), keyboard.mOccupiedWidth,
-                keyboard.mOccupiedHeight, keyboard.getSortedKeys());
-    }
-
-    /**
-     * Log a call to LatinIME.revertCommit().
-     *
-     * SystemResponse: The IME has reverted commited text.  This happens when the user enters
-     * a word, commits it by pressing space or punctuation, and then reverts the commit by hitting
-     * backspace.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_REVERTCOMMIT =
-            new LogStatement("LatinIMERevertCommit", true, false, "committedWord",
-                    "originallyTypedWord", "separatorString");
-    public static void latinIME_revertCommit(final String committedWord,
-            final String originallyTypedWord, final boolean isBatchMode,
-            final String separatorString) {
-        // TODO: Prioritize adding a unit test for this method (as it is especially complex)
-        // TODO: Update the UserRecording LogBuffer as well as the MainLogBuffer
-        final ResearchLogger researchLogger = getInstance();
-        //
-        // 1. Remove separator LogUnit
-        final LogUnit lastLogUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
-        // Check that we're not at the beginning of input
-        if (lastLogUnit == null) return;
-        // Check that we're after a separator
-        if (lastLogUnit.getWordsAsString() != null) return;
-        // Remove separator
-        final LogUnit separatorLogUnit = researchLogger.mMainLogBuffer.unshiftIn();
-
-        // 2. Add revert LogStatement
-        final LogUnit revertedLogUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
-        if (revertedLogUnit == null) return;
-        if (!revertedLogUnit.getWordsAsString().equals(scrubDigitsFromString(committedWord))) {
-            // Any word associated with the reverted LogUnit has already had its digits scrubbed, so
-            // any digits in the committedWord argument must also be scrubbed for an accurate
-            // comparison.
-            return;
-        }
-        researchLogger.enqueueEvent(revertedLogUnit, LOGSTATEMENT_LATINIME_REVERTCOMMIT,
-                committedWord, originallyTypedWord, separatorString);
-
-        // 3. Update the word associated with the LogUnit
-        revertedLogUnit.setWords(originallyTypedWord);
-        revertedLogUnit.setContainsUserDeletions();
-
-        // 4. Re-add the separator LogUnit
-        researchLogger.mMainLogBuffer.shiftIn(separatorLogUnit);
-
-        // 5. Record stats
-        researchLogger.mStatistics.recordRevertCommit(SystemClock.uptimeMillis());
-    }
-
-    /**
-     * Log a call to PointerTracker.callListenerOnCancelInput().
-     *
-     * UserAction: The user has canceled the input, e.g., by pressing down, but then removing
-     * outside the keyboard area.
-     * TODO: Verify
-     */
-    private static final LogStatement LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONCANCELINPUT =
-            new LogStatement("PointerTrackerCallListenerOnCancelInput", false, false);
-    public static void pointerTracker_callListenerOnCancelInput() {
-        getInstance().enqueueEvent(LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONCANCELINPUT);
-    }
-
-    /**
-     * Log a call to PointerTracker.callListenerOnCodeInput().
-     *
-     * SystemResponse: The user has entered a key through the normal tapping mechanism.
-     * LatinIME.onCodeInput will also be called.
-     */
-    private static final LogStatement LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONCODEINPUT =
-            new LogStatement("PointerTrackerCallListenerOnCodeInput", true, false, "code",
-                    "outputText", "x", "y", "ignoreModifierKey", "altersCode", "isEnabled");
-    public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x,
-            final int y, final boolean ignoreModifierKey, final boolean altersCode,
-            final int code) {
-        if (key != null) {
-            String outputText = key.getOutputText();
-            final ResearchLogger researchLogger = getInstance();
-            researchLogger.enqueueEvent(LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONCODEINPUT,
-                    Constants.printableCode(scrubDigitFromCodePoint(code)),
-                    outputText == null ? null : scrubDigitsFromString(outputText.toString()),
-                    x, y, ignoreModifierKey, altersCode, key.isEnabled());
-        }
-    }
-
-    /**
-     * Log a call to PointerTracker.callListenerCallListenerOnRelease().
-     *
-     * UserAction: The user has released their finger or thumb from the screen.
-     */
-    private static final LogStatement LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONRELEASE =
-            new LogStatement("PointerTrackerCallListenerOnRelease", true, false, "code",
-                    "withSliding", "ignoreModifierKey", "isEnabled");
-    public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode,
-            final boolean withSliding, final boolean ignoreModifierKey) {
-        if (key != null) {
-            getInstance().enqueueEvent(LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONRELEASE,
-                    Constants.printableCode(scrubDigitFromCodePoint(primaryCode)), withSliding,
-                    ignoreModifierKey, key.isEnabled());
-        }
-    }
-
-    /**
-     * Log a call to PointerTracker.onDownEvent().
-     *
-     * UserAction: The user has pressed down on a key.
-     * TODO: Differentiate with LatinIME.processMotionEvent.
-     */
-    private static final LogStatement LOGSTATEMENT_POINTERTRACKER_ONDOWNEVENT =
-            new LogStatement("PointerTrackerOnDownEvent", true, false, "deltaT", "distanceSquared");
-    public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) {
-        getInstance().enqueueEvent(LOGSTATEMENT_POINTERTRACKER_ONDOWNEVENT, deltaT,
-                distanceSquared);
-    }
-
-    /**
-     * Log a call to PointerTracker.onMoveEvent().
-     *
-     * UserAction: The user has moved their finger while pressing on the screen.
-     * TODO: Differentiate with LatinIME.processMotionEvent().
-     */
-    private static final LogStatement LOGSTATEMENT_POINTERTRACKER_ONMOVEEVENT =
-            new LogStatement("PointerTrackerOnMoveEvent", true, false, "x", "y", "lastX", "lastY");
-    public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX,
-            final int lastY) {
-        getInstance().enqueueEvent(LOGSTATEMENT_POINTERTRACKER_ONMOVEEVENT, x, y, lastX, lastY);
-    }
-
-    /**
-     * Log a call to RichInputConnection.commitCompletion().
-     *
-     * SystemResponse: The IME has committed a completion.  A completion is an application-
-     * specific suggestion that is presented in a pop-up menu in the TextView.
-     */
-    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_COMMITCOMPLETION =
-            new LogStatement("RichInputConnectionCommitCompletion", true, false, "completionInfo");
-    public static void richInputConnection_commitCompletion(final CompletionInfo completionInfo) {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_COMMITCOMPLETION,
-                completionInfo);
-    }
-
-    /**
-     * Log a call to RichInputConnection.revertDoubleSpacePeriod().
-     *
-     * SystemResponse: The IME has reverted ". ", which had previously replaced two typed spaces.
-     */
-    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_REVERTDOUBLESPACEPERIOD =
-            new LogStatement("RichInputConnectionRevertDoubleSpacePeriod", false, false);
-    public static void richInputConnection_revertDoubleSpacePeriod() {
-        final ResearchLogger researchLogger = getInstance();
-        // An extra LogUnit is added for the period; this is removed here because of the revert.
-        researchLogger.uncommitCurrentLogUnit(null, true /* dumpCurrentLogUnit */);
-        // TODO: This will probably be lost as the user backspaces further.  Figure out how to put
-        // it into the right logUnit.
-        researchLogger.enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_REVERTDOUBLESPACEPERIOD);
-    }
-
-    /**
-     * Log a call to RichInputConnection.revertSwapPunctuation().
-     *
-     * SystemResponse: The IME has reverted a punctuation swap.
-     */
-    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_REVERTSWAPPUNCTUATION =
-            new LogStatement("RichInputConnectionRevertSwapPunctuation", false, false);
-    public static void richInputConnection_revertSwapPunctuation() {
-        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_REVERTSWAPPUNCTUATION);
-    }
-
-    /**
-     * Log a call to LatinIME.commitCurrentAutoCorrection().
-     *
-     * SystemResponse: The IME has committed an auto-correction.  An auto-correction changes the raw
-     * text input to another word (or words) that the user more likely desired to type.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_COMMITCURRENTAUTOCORRECTION =
-            new LogStatement("LatinIMECommitCurrentAutoCorrection", true, true, "typedWord",
-                    "autoCorrection", "separatorString");
-    public static void latinIme_commitCurrentAutoCorrection(final String typedWord,
-            final String autoCorrection, final String separatorString, final boolean isBatchMode,
-            final SuggestedWords suggestedWords) {
-        final String scrubbedTypedWord = scrubDigitsFromString(typedWord);
-        final String scrubbedAutoCorrection = scrubDigitsFromString(autoCorrection);
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.mCurrentLogUnit.initializeSuggestions(suggestedWords);
-        researchLogger.onWordFinished(scrubbedAutoCorrection, isBatchMode);
-
-        // Add the autocorrection logStatement at the end of the logUnit for the committed word.
-        // We have to do this after calling commitCurrentLogUnitAsWord, because it may split the
-        // current logUnit, and then we have to peek to get the logUnit reference back.
-        final LogUnit logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
-        // TODO: Add test to confirm that the commitCurrentAutoCorrection log statement should
-        // always be added to logUnit (if non-null) and not mCurrentLogUnit.
-        researchLogger.enqueueEvent(logUnit, LOGSTATEMENT_LATINIME_COMMITCURRENTAUTOCORRECTION,
-                scrubbedTypedWord, scrubbedAutoCorrection, separatorString);
-    }
-
-    private boolean isExpectingCommitText = false;
-
-    /**
-     * Log a call to RichInputConnection.commitText().
-     *
-     * SystemResponse: The IME is committing text.  This happens after the user has typed a word
-     * and then a space or punctuation key.
-     */
-    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTIONCOMMITTEXT =
-            new LogStatement("RichInputConnectionCommitText", true, false, "newCursorPosition");
-    public static void richInputConnection_commitText(final String committedWord,
-            final int newCursorPosition, final boolean isBatchMode) {
-        final ResearchLogger researchLogger = getInstance();
-        // Only include opening and closing logSegments if private data is included
-        final String scrubbedWord = scrubDigitsFromString(committedWord);
-        if (!researchLogger.isExpectingCommitText) {
-            researchLogger.enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTIONCOMMITTEXT,
-                    newCursorPosition);
-            researchLogger.commitCurrentLogUnitAsWord(scrubbedWord, Long.MAX_VALUE, isBatchMode);
-        }
-        researchLogger.isExpectingCommitText = false;
-    }
-
-    /**
-     * Shared events for logging committed text.
-     *
-     * The "CommitTextEventHappened" LogStatement is written to the log even if privacy rules
-     * indicate that the word contents should not be logged.  It has no contents, and only serves to
-     * record the event and thereby make it easier to calculate word-level statistics even when the
-     * word contents are unknown.
-     */
-    private static final LogStatement LOGSTATEMENT_COMMITTEXT =
-            new LogStatement("CommitText", true /* isPotentiallyPrivate */,
-                    false /* isPotentiallyRevealing */, "committedText", "isBatchMode");
-    private static final LogStatement LOGSTATEMENT_COMMITTEXT_EVENT_HAPPENED =
-            new LogStatement("CommitTextEventHappened", false /* isPotentiallyPrivate */,
-                    false /* isPotentiallyRevealing */);
-    private void enqueueCommitText(final String word, final boolean isBatchMode) {
-        // Event containing the word; will be published only if privacy checks pass
-        enqueueEvent(LOGSTATEMENT_COMMITTEXT, word, isBatchMode);
-        // Event not containing the word; will always be published
-        enqueueEvent(LOGSTATEMENT_COMMITTEXT_EVENT_HAPPENED);
-    }
-
-    /**
-     * Log a call to RichInputConnection.deleteSurroundingText().
-     *
-     * SystemResponse: The IME has deleted text.
-     */
-    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_DELETESURROUNDINGTEXT =
-            new LogStatement("RichInputConnectionDeleteSurroundingText", true, false,
-                    "beforeLength", "afterLength");
-    public static void richInputConnection_deleteSurroundingText(final int beforeLength,
-            final int afterLength) {
-        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_DELETESURROUNDINGTEXT,
-                beforeLength, afterLength);
-    }
-
-    /**
-     * Log a call to RichInputConnection.finishComposingText().
-     *
-     * SystemResponse: The IME has left the composing text as-is.
-     */
-    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_FINISHCOMPOSINGTEXT =
-            new LogStatement("RichInputConnectionFinishComposingText", false, false);
-    public static void richInputConnection_finishComposingText() {
-        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_FINISHCOMPOSINGTEXT);
-    }
-
-    /**
-     * Log a call to RichInputConnection.performEditorAction().
-     *
-     * SystemResponse: The IME is invoking an action specific to the editor.
-     */
-    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_PERFORMEDITORACTION =
-            new LogStatement("RichInputConnectionPerformEditorAction", false, false,
-                    "imeActionId");
-    public static void richInputConnection_performEditorAction(final int imeActionId) {
-        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_PERFORMEDITORACTION,
-                imeActionId);
-    }
-
-    /**
-     * Log a call to RichInputConnection.sendKeyEvent().
-     *
-     * SystemResponse: The IME is telling the TextView that a key is being pressed through an
-     * alternate channel.
-     * TODO: only for hardware keys?
-     */
-    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_SENDKEYEVENT =
-            new LogStatement("RichInputConnectionSendKeyEvent", true, false, "eventTime", "action",
-                    "code");
-    public static void richInputConnection_sendKeyEvent(final KeyEvent keyEvent) {
-        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_SENDKEYEVENT,
-                keyEvent.getEventTime(), keyEvent.getAction(), keyEvent.getKeyCode());
-    }
-
-    /**
-     * Log a call to RichInputConnection.setComposingText().
-     *
-     * SystemResponse: The IME is setting the composing text.  Happens each time a character is
-     * entered.
-     */
-    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_SETCOMPOSINGTEXT =
-            new LogStatement("RichInputConnectionSetComposingText", true, true, "text",
-                    "newCursorPosition");
-    public static void richInputConnection_setComposingText(final CharSequence text,
-            final int newCursorPosition) {
-        if (text == null) {
-            throw new RuntimeException("setComposingText is null");
-        }
-        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_SETCOMPOSINGTEXT, text,
-                newCursorPosition);
-    }
-
-    /**
-     * Log a call to RichInputConnection.setSelection().
-     *
-     * SystemResponse: The IME is requesting that the selection change.  User-initiated selection-
-     * change requests do not go through this method -- it's only when the system wants to change
-     * the selection.
-     */
-    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_SETSELECTION =
-            new LogStatement("RichInputConnectionSetSelection", true, false, "from", "to");
-    public static void richInputConnection_setSelection(final int from, final int to) {
-        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_SETSELECTION, from, to);
-    }
-
-    /**
-     * Log a call to SuddenJumpingTouchEventHandler.onTouchEvent().
-     *
-     * SystemResponse: The IME has filtered input events in case of an erroneous sensor reading.
-     */
-    private static final LogStatement LOGSTATEMENT_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT =
-            new LogStatement("SuddenJumpingTouchEventHandlerOnTouchEvent", true, false,
-                    "motionEvent");
-    public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) {
-        if (me != null) {
-            getInstance().enqueueEvent(LOGSTATEMENT_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT,
-                    MotionEvent.obtain(me));
-        }
-    }
-
-    /**
-     * Log a call to SuggestionsView.setSuggestions().
-     *
-     * SystemResponse: The IME is setting the suggestions in the suggestion strip.
-     */
-    private static final LogStatement LOGSTATEMENT_SUGGESTIONSTRIPVIEW_SETSUGGESTIONS =
-            new LogStatement("SuggestionStripViewSetSuggestions", true, true, "suggestedWords");
-    public static void suggestionStripView_setSuggestions(final SuggestedWords suggestedWords) {
-        if (suggestedWords != null) {
-            getInstance().enqueueEvent(LOGSTATEMENT_SUGGESTIONSTRIPVIEW_SETSUGGESTIONS,
-                    suggestedWords);
-        }
-    }
-
-    /**
-     * The user has indicated a particular point in the log that is of interest.
-     *
-     * UserAction: From direct menu invocation.
-     */
-    private static final LogStatement LOGSTATEMENT_USER_TIMESTAMP =
-            new LogStatement("UserTimestamp", false, false);
-    public void userTimestamp() {
-        getInstance().enqueueEvent(LOGSTATEMENT_USER_TIMESTAMP);
-    }
-
-    /**
-     * Log a call to LatinIME.onEndBatchInput().
-     *
-     * SystemResponse: The system has completed a gesture.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_ONENDBATCHINPUT =
-            new LogStatement("LatinIMEOnEndBatchInput", true, false, "enteredText",
-                    "enteredWordPos", "suggestedWords");
-    public static void latinIME_onEndBatchInput(final CharSequence enteredText,
-            final int enteredWordPos, final SuggestedWords suggestedWords) {
-        final ResearchLogger researchLogger = getInstance();
-        if (!TextUtils.isEmpty(enteredText) && hasLetters(enteredText.toString())) {
-            researchLogger.mCurrentLogUnit.setWords(enteredText.toString());
-        }
-        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONENDBATCHINPUT, enteredText,
-                enteredWordPos, suggestedWords);
-        researchLogger.mCurrentLogUnit.initializeSuggestions(suggestedWords);
-        researchLogger.mStatistics.recordGestureInput(enteredText.length(),
-                SystemClock.uptimeMillis());
-    }
-
-    private static final LogStatement LOGSTATEMENT_LATINIME_HANDLEBACKSPACE =
-            new LogStatement("LatinIMEHandleBackspace", true, false, "numCharacters");
-    /**
-     * Log a call to LatinIME.handleBackspace() that is not a batch delete.
-     *
-     * UserInput: The user is deleting one or more characters by hitting the backspace key once.
-     * The covers single character deletes as well as deleting selections.
-     *
-     * @param numCharacters how many characters the backspace operation deleted
-     * @param shouldUncommitLogUnit whether to uncommit the last {@code LogUnit} in the
-     * {@code LogBuffer}
-     */
-    public static void latinIME_handleBackspace(final int numCharacters,
-            final boolean shouldUncommitLogUnit) {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_HANDLEBACKSPACE, numCharacters);
-        if (shouldUncommitLogUnit) {
-            ResearchLogger.getInstance().uncommitCurrentLogUnit(
-                    null, true /* dumpCurrentLogUnit */);
-        }
-    }
-
-    /**
-     * Log a call to LatinIME.handleBackspace() that is a batch delete.
-     *
-     * UserInput: The user is deleting a gestured word by hitting the backspace key once.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_HANDLEBACKSPACE_BATCH =
-            new LogStatement("LatinIMEHandleBackspaceBatch", true, false, "deletedText",
-                    "numCharacters");
-    public static void latinIME_handleBackspace_batch(final CharSequence deletedText,
-            final int numCharacters) {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_HANDLEBACKSPACE_BATCH, deletedText,
-                numCharacters);
-        researchLogger.mStatistics.recordGestureDelete(deletedText.length(),
-                SystemClock.uptimeMillis());
-        researchLogger.uncommitCurrentLogUnit(deletedText.toString(),
-                false /* dumpCurrentLogUnit */);
-    }
-
-    /**
-     * Log a long interval between user operation.
-     *
-     * UserInput: The user has not done anything for a while.
-     */
-    private static final LogStatement LOGSTATEMENT_ONUSERPAUSE = new LogStatement("OnUserPause",
-            false, false, "intervalInMs");
-    public static void onUserPause(final long interval) {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.enqueueEvent(LOGSTATEMENT_ONUSERPAUSE, interval);
-    }
-
-    /**
-     * Record the current time in case the LogUnit is later split.
-     *
-     * If the current logUnit is split, then tapping, motion events, etc. before this time should
-     * be assigned to one LogUnit, and events after this time should go into the following LogUnit.
-     */
-    public static void recordTimeForLogUnitSplit() {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.setSavedDownEventTime(SystemClock.uptimeMillis());
-        researchLogger.mSavedDownEventTime = Long.MAX_VALUE;
-    }
-
-    /**
-     * Log a call to LatinIME.handleSeparator()
-     *
-     * SystemResponse: The system is inserting a separator character, possibly performing auto-
-     * correction or other actions appropriate at the end of a word.
-     */
-    private static final LogStatement LOGSTATEMENT_LATINIME_HANDLESEPARATOR =
-            new LogStatement("LatinIMEHandleSeparator", false, false, "primaryCode",
-                    "isComposingWord");
-    public static void latinIME_handleSeparator(final int primaryCode,
-            final boolean isComposingWord) {
-        final ResearchLogger researchLogger = getInstance();
-        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_HANDLESEPARATOR, primaryCode,
-                isComposingWord);
-    }
-
-    /**
-     * Call this method when the logging system has attempted publication of an n-gram.
-     *
-     * Statistics are gathered about the success or failure.
-     *
-     * @param publishabilityResultCode a result code as defined by
-     * {@code MainLogBuffer.PUBLISHABILITY_*}
-     */
-    static void recordPublishabilityResultCode(final int publishabilityResultCode) {
-        final ResearchLogger researchLogger = getInstance();
-        final Statistics statistics = researchLogger.mStatistics;
-        statistics.recordPublishabilityResultCode(publishabilityResultCode);
-    }
-
-    /**
-     * Log statistics.
-     *
-     * ContextualData, recorded at the end of a session.
-     */
-    private static final LogStatement LOGSTATEMENT_STATISTICS =
-            new LogStatement("Statistics", false, false, "charCount", "letterCount", "numberCount",
-                    "spaceCount", "deleteOpsCount", "wordCount", "isEmptyUponStarting",
-                    "isEmptinessStateKnown", "averageTimeBetweenKeys", "averageTimeBeforeDelete",
-                    "averageTimeDuringRepeatedDelete", "averageTimeAfterDelete",
-                    "dictionaryWordCount", "splitWordsCount", "gestureInputCount",
-                    "gestureCharsCount", "gesturesDeletedCount", "manualSuggestionsCount",
-                    "revertCommitsCount", "correctedWordsCount", "autoCorrectionsCount",
-                    "publishableCount", "unpublishableStoppingCount",
-                    "unpublishableIncorrectWordCount", "unpublishableSampledTooRecentlyCount",
-                    "unpublishableDictionaryUnavailableCount", "unpublishableMayContainDigitCount",
-                    "unpublishableNotInDictionaryCount");
-    private static void logStatistics() {
-        final ResearchLogger researchLogger = getInstance();
-        final Statistics statistics = researchLogger.mStatistics;
-        researchLogger.enqueueEvent(LOGSTATEMENT_STATISTICS, statistics.mCharCount,
-                statistics.mLetterCount, statistics.mNumberCount, statistics.mSpaceCount,
-                statistics.mDeleteKeyCount, statistics.mWordCount, statistics.mIsEmptyUponStarting,
-                statistics.mIsEmptinessStateKnown, statistics.mKeyCounter.getAverageTime(),
-                statistics.mBeforeDeleteKeyCounter.getAverageTime(),
-                statistics.mDuringRepeatedDeleteKeysCounter.getAverageTime(),
-                statistics.mAfterDeleteKeyCounter.getAverageTime(),
-                statistics.mDictionaryWordCount, statistics.mSplitWordsCount,
-                statistics.mGesturesInputCount, statistics.mGesturesCharsCount,
-                statistics.mGesturesDeletedCount, statistics.mManualSuggestionsCount,
-                statistics.mRevertCommitsCount, statistics.mCorrectedWordsCount,
-                statistics.mAutoCorrectionsCount, statistics.mPublishableCount,
-                statistics.mUnpublishableStoppingCount, statistics.mUnpublishableIncorrectWordCount,
-                statistics.mUnpublishableSampledTooRecently,
-                statistics.mUnpublishableDictionaryUnavailable,
-                statistics.mUnpublishableMayContainDigit, statistics.mUnpublishableNotInDictionary);
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/ResearchSettings.java b/java/src/com/android/inputmethod/research/ResearchSettings.java
deleted file mode 100644
index c0bc03f..0000000
--- a/java/src/com/android/inputmethod/research/ResearchSettings.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2013 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.research;
-
-import android.content.SharedPreferences;
-
-import java.util.UUID;
-
-public final class ResearchSettings {
-    public static final String PREF_RESEARCH_LOGGER_UUID = "pref_research_logger_uuid";
-    public static final String PREF_RESEARCH_LOGGER_ENABLED_FLAG =
-            "pref_research_logger_enabled_flag";
-    public static final String PREF_RESEARCH_LOGGER_HAS_SEEN_SPLASH =
-            "pref_research_logger_has_seen_splash";
-    public static final String PREF_RESEARCH_LAST_DIR_CLEANUP_TIME =
-            "pref_research_last_dir_cleanup_time";
-
-    private ResearchSettings() {
-        // Intentional empty constructor for singleton.
-    }
-
-    public static String readResearchLoggerUuid(final SharedPreferences prefs) {
-        if (prefs.contains(PREF_RESEARCH_LOGGER_UUID)) {
-            return prefs.getString(PREF_RESEARCH_LOGGER_UUID, null);
-        }
-        // Generate a random string as uuid if not yet set
-        final String newUuid = UUID.randomUUID().toString();
-        prefs.edit().putString(PREF_RESEARCH_LOGGER_UUID, newUuid).apply();
-        return newUuid;
-    }
-
-    public static boolean readResearchLoggerEnabledFlag(final SharedPreferences prefs) {
-        return prefs.getBoolean(PREF_RESEARCH_LOGGER_ENABLED_FLAG, false);
-    }
-
-    public static void writeResearchLoggerEnabledFlag(final SharedPreferences prefs,
-            final boolean isEnabled) {
-        prefs.edit().putBoolean(PREF_RESEARCH_LOGGER_ENABLED_FLAG, isEnabled).apply();
-    }
-
-    public static boolean readHasSeenSplash(final SharedPreferences prefs) {
-        return prefs.getBoolean(PREF_RESEARCH_LOGGER_HAS_SEEN_SPLASH, false);
-    }
-
-    public static void writeHasSeenSplash(final SharedPreferences prefs,
-            final boolean hasSeenSplash) {
-        prefs.edit().putBoolean(PREF_RESEARCH_LOGGER_HAS_SEEN_SPLASH, hasSeenSplash).apply();
-    }
-
-    public static long readResearchLastDirCleanupTime(final SharedPreferences prefs) {
-        return prefs.getLong(PREF_RESEARCH_LAST_DIR_CLEANUP_TIME, 0L);
-    }
-
-    public static void writeResearchLastDirCleanupTime(final SharedPreferences prefs,
-            final long lastDirCleanupTime) {
-        prefs.edit().putLong(PREF_RESEARCH_LAST_DIR_CLEANUP_TIME, lastDirCleanupTime).apply();
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/Statistics.java b/java/src/com/android/inputmethod/research/Statistics.java
deleted file mode 100644
index fd323a1..0000000
--- a/java/src/com/android/inputmethod/research/Statistics.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.util.Log;
-
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.define.ProductionFlag;
-
-import java.util.concurrent.TimeUnit;
-
-public class Statistics {
-    private static final String TAG = Statistics.class.getSimpleName();
-    private static final boolean DEBUG = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-
-    // TODO: Cleanup comments to only including those giving meaningful information.
-    // Number of characters entered during a typing session
-    int mCharCount;
-    // Number of letter characters entered during a typing session
-    int mLetterCount;
-    // Number of number characters entered
-    int mNumberCount;
-    // Number of space characters entered
-    int mSpaceCount;
-    // Number of delete operations entered (taps on the backspace key)
-    int mDeleteKeyCount;
-    // Number of words entered during a session.
-    int mWordCount;
-    // Number of words found in the dictionary.
-    int mDictionaryWordCount;
-    // Number of words split and spaces automatically entered.
-    int mSplitWordsCount;
-    // Number of words entered during a session.
-    int mCorrectedWordsCount;
-    // Number of gestures that were input.
-    int mGesturesInputCount;
-    // Number of gestures that were deleted.
-    int mGesturesDeletedCount;
-    // Total number of characters in words entered by gesture.
-    int mGesturesCharsCount;
-    // Number of manual suggestions chosen.
-    int mManualSuggestionsCount;
-    // Number of times that autocorrection was invoked.
-    int mAutoCorrectionsCount;
-    // Number of times a commit was reverted in this session.
-    int mRevertCommitsCount;
-    // Whether the text field was empty upon editing
-    boolean mIsEmptyUponStarting;
-    boolean mIsEmptinessStateKnown;
-
-    // Counts of how often an n-gram is collected or not, and the reasons for the decision.
-    // Keep consistent with publishability result code list in MainLogBuffer
-    int mPublishableCount;
-    int mUnpublishableStoppingCount;
-    int mUnpublishableIncorrectWordCount;
-    int mUnpublishableSampledTooRecently;
-    int mUnpublishableDictionaryUnavailable;
-    int mUnpublishableMayContainDigit;
-    int mUnpublishableNotInDictionary;
-
-    // Timers to count average time to enter a key, first press a delete key,
-    // between delete keys, and then to return typing after a delete key.
-    final AverageTimeCounter mKeyCounter = new AverageTimeCounter();
-    final AverageTimeCounter mBeforeDeleteKeyCounter = new AverageTimeCounter();
-    final AverageTimeCounter mDuringRepeatedDeleteKeysCounter = new AverageTimeCounter();
-    final AverageTimeCounter mAfterDeleteKeyCounter = new AverageTimeCounter();
-
-    static class AverageTimeCounter {
-        int mCount;
-        int mTotalTime;
-
-        public void reset() {
-            mCount = 0;
-            mTotalTime = 0;
-        }
-
-        public void add(long deltaTime) {
-            mCount++;
-            mTotalTime += deltaTime;
-        }
-
-        public int getAverageTime() {
-            if (mCount == 0) {
-                return 0;
-            }
-            return mTotalTime / mCount;
-        }
-    }
-
-    // To account for the interruptions when the user's attention is directed elsewhere, times
-    // longer than MIN_TYPING_INTERMISSION are not counted when estimating this statistic.
-    public static final long MIN_TYPING_INTERMISSION = TimeUnit.SECONDS.toMillis(2);
-    public static final long MIN_DELETION_INTERMISSION = TimeUnit.SECONDS.toMillis(10);
-
-    // The last time that a tap was performed
-    private long mLastTapTime;
-    // The type of the last keypress (delete key or not)
-    boolean mIsLastKeyDeleteKey;
-
-    private static final Statistics sInstance = new Statistics();
-
-    public static Statistics getInstance() {
-        return sInstance;
-    }
-
-    private Statistics() {
-        reset();
-    }
-
-    public void reset() {
-        mCharCount = 0;
-        mLetterCount = 0;
-        mNumberCount = 0;
-        mSpaceCount = 0;
-        mDeleteKeyCount = 0;
-        mWordCount = 0;
-        mDictionaryWordCount = 0;
-        mSplitWordsCount = 0;
-        mCorrectedWordsCount = 0;
-        mGesturesInputCount = 0;
-        mGesturesDeletedCount = 0;
-        mManualSuggestionsCount = 0;
-        mRevertCommitsCount = 0;
-        mAutoCorrectionsCount = 0;
-        mIsEmptyUponStarting = true;
-        mIsEmptinessStateKnown = false;
-        mKeyCounter.reset();
-        mBeforeDeleteKeyCounter.reset();
-        mDuringRepeatedDeleteKeysCounter.reset();
-        mAfterDeleteKeyCounter.reset();
-        mGesturesCharsCount = 0;
-        mGesturesDeletedCount = 0;
-        mPublishableCount = 0;
-        mUnpublishableStoppingCount = 0;
-        mUnpublishableIncorrectWordCount = 0;
-        mUnpublishableSampledTooRecently = 0;
-        mUnpublishableDictionaryUnavailable = 0;
-        mUnpublishableMayContainDigit = 0;
-        mUnpublishableNotInDictionary = 0;
-
-        mLastTapTime = 0;
-        mIsLastKeyDeleteKey = false;
-    }
-
-    public void recordChar(int codePoint, long time) {
-        if (DEBUG) {
-            Log.d(TAG, "recordChar() called");
-        }
-        if (codePoint == Constants.CODE_DELETE) {
-            mDeleteKeyCount++;
-            recordUserAction(time, true /* isDeletion */);
-        } else {
-            mCharCount++;
-            if (Character.isDigit(codePoint)) {
-                mNumberCount++;
-            }
-            if (Character.isLetter(codePoint)) {
-                mLetterCount++;
-            }
-            if (Character.isSpaceChar(codePoint)) {
-                mSpaceCount++;
-            }
-            recordUserAction(time, false /* isDeletion */);
-        }
-    }
-
-    public void recordWordEntered(final boolean isDictionaryWord,
-            final boolean containsCorrection) {
-        mWordCount++;
-        if (isDictionaryWord) {
-            mDictionaryWordCount++;
-        }
-        if (containsCorrection) {
-            mCorrectedWordsCount++;
-        }
-    }
-
-    public void recordSplitWords() {
-        mSplitWordsCount++;
-    }
-
-    public void recordGestureInput(final int numCharsEntered, final long time) {
-        mGesturesInputCount++;
-        mGesturesCharsCount += numCharsEntered;
-        recordUserAction(time, false /* isDeletion */);
-    }
-
-    public void setIsEmptyUponStarting(final boolean isEmpty) {
-        mIsEmptyUponStarting = isEmpty;
-        mIsEmptinessStateKnown = true;
-    }
-
-    public void recordGestureDelete(final int length, final long time) {
-        mGesturesDeletedCount++;
-        recordUserAction(time, true /* isDeletion */);
-    }
-
-    public void recordManualSuggestion(final long time) {
-        mManualSuggestionsCount++;
-        recordUserAction(time, false /* isDeletion */);
-    }
-
-    public void recordAutoCorrection(final long time) {
-        mAutoCorrectionsCount++;
-        recordUserAction(time, false /* isDeletion */);
-    }
-
-    public void recordRevertCommit(final long time) {
-        mRevertCommitsCount++;
-        recordUserAction(time, true /* isDeletion */);
-    }
-
-    private void recordUserAction(final long time, final boolean isDeletion) {
-        final long delta = time - mLastTapTime;
-        if (isDeletion) {
-            if (delta < MIN_DELETION_INTERMISSION) {
-                if (mIsLastKeyDeleteKey) {
-                    mDuringRepeatedDeleteKeysCounter.add(delta);
-                } else {
-                    mBeforeDeleteKeyCounter.add(delta);
-                }
-            } else {
-                ResearchLogger.onUserPause(delta);
-            }
-        } else {
-            if (mIsLastKeyDeleteKey && delta < MIN_DELETION_INTERMISSION) {
-                mAfterDeleteKeyCounter.add(delta);
-            } else if (!mIsLastKeyDeleteKey && delta < MIN_TYPING_INTERMISSION) {
-                mKeyCounter.add(delta);
-            } else {
-                ResearchLogger.onUserPause(delta);
-            }
-        }
-        mIsLastKeyDeleteKey = isDeletion;
-        mLastTapTime = time;
-    }
-
-    public void recordPublishabilityResultCode(final int publishabilityResultCode) {
-        // Keep consistent with publishability result code list in MainLogBuffer
-        switch (publishabilityResultCode) {
-        case MainLogBuffer.PUBLISHABILITY_PUBLISHABLE:
-            mPublishableCount++;
-            break;
-        case MainLogBuffer.PUBLISHABILITY_UNPUBLISHABLE_STOPPING:
-            mUnpublishableStoppingCount++;
-            break;
-        case MainLogBuffer.PUBLISHABILITY_UNPUBLISHABLE_INCORRECT_WORD_COUNT:
-            mUnpublishableIncorrectWordCount++;
-            break;
-        case MainLogBuffer.PUBLISHABILITY_UNPUBLISHABLE_SAMPLED_TOO_RECENTLY:
-            mUnpublishableSampledTooRecently++;
-            break;
-        case MainLogBuffer.PUBLISHABILITY_UNPUBLISHABLE_DICTIONARY_UNAVAILABLE:
-            mUnpublishableDictionaryUnavailable++;
-            break;
-        case MainLogBuffer.PUBLISHABILITY_UNPUBLISHABLE_MAY_CONTAIN_DIGIT:
-            mUnpublishableMayContainDigit++;
-            break;
-        case MainLogBuffer.PUBLISHABILITY_UNPUBLISHABLE_NOT_IN_DICTIONARY:
-            mUnpublishableNotInDictionary++;
-            break;
-        }
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/Uploader.java b/java/src/com/android/inputmethod/research/Uploader.java
deleted file mode 100644
index c7ea3e6..0000000
--- a/java/src/com/android/inputmethod/research/Uploader.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2013 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.research;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.BatteryManager;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.define.ProductionFlag;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/**
- * Manages the uploading of ResearchLog files.
- */
-public final class Uploader {
-    private static final String TAG = Uploader.class.getSimpleName();
-    private static final boolean DEBUG = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-    // Set IS_INHIBITING_AUTO_UPLOAD to true for local testing
-    private static final boolean IS_INHIBITING_UPLOAD = false
-            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
-    private static final int BUF_SIZE = 1024 * 8;
-
-    private final Context mContext;
-    private final ResearchLogDirectory mResearchLogDirectory;
-    private final URL mUrl;
-
-    public Uploader(final Context context) {
-        mContext = context;
-        mResearchLogDirectory = new ResearchLogDirectory(context);
-
-        final String urlString = context.getString(R.string.research_logger_upload_url);
-        if (TextUtils.isEmpty(urlString)) {
-            mUrl = null;
-            return;
-        }
-        URL url = null;
-        try {
-            url = new URL(urlString);
-        } catch (final MalformedURLException e) {
-            Log.e(TAG, "Bad URL for uploading", e);
-        }
-        mUrl = url;
-    }
-
-    public boolean isPossibleToUpload() {
-        return hasUploadingPermission() && mUrl != null && !IS_INHIBITING_UPLOAD;
-    }
-
-    private boolean hasUploadingPermission() {
-        final PackageManager packageManager = mContext.getPackageManager();
-        return packageManager.checkPermission(Manifest.permission.INTERNET,
-                mContext.getPackageName()) == PackageManager.PERMISSION_GRANTED;
-    }
-
-    public boolean isConvenientToUpload() {
-        return isExternallyPowered() && hasWifiConnection();
-    }
-
-    private boolean isExternallyPowered() {
-        final Intent intent = mContext.registerReceiver(null, new IntentFilter(
-                Intent.ACTION_BATTERY_CHANGED));
-        final int pluggedState = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
-        return pluggedState == BatteryManager.BATTERY_PLUGGED_AC
-                || pluggedState == BatteryManager.BATTERY_PLUGGED_USB;
-    }
-
-    private boolean hasWifiConnection() {
-        final ConnectivityManager manager =
-                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-        final NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
-        return wifiInfo.isConnected();
-    }
-
-    public void doUpload() {
-        final File[] files = mResearchLogDirectory.getUploadableLogFiles();
-        if (files == null) return;
-        for (final File file : files) {
-            uploadFile(file);
-        }
-    }
-
-    private void uploadFile(final File file) {
-        if (DEBUG) {
-            Log.d(TAG, "attempting upload of " + file.getAbsolutePath());
-        }
-        final int contentLength = (int) file.length();
-        HttpURLConnection connection = null;
-        InputStream fileInputStream = null;
-        try {
-            fileInputStream = new FileInputStream(file);
-            connection = (HttpURLConnection) mUrl.openConnection();
-            connection.setRequestMethod("PUT");
-            connection.setDoOutput(true);
-            connection.setFixedLengthStreamingMode(contentLength);
-            final OutputStream outputStream = connection.getOutputStream();
-            uploadContents(fileInputStream, outputStream);
-            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
-                Log.d(TAG, "upload failed: " + connection.getResponseCode());
-                final InputStream netInputStream = connection.getInputStream();
-                final BufferedReader reader = new BufferedReader(new InputStreamReader(
-                        netInputStream));
-                String line;
-                while ((line = reader.readLine()) != null) {
-                    Log.d(TAG, "| " + reader.readLine());
-                }
-                reader.close();
-                return;
-            }
-            file.delete();
-            if (DEBUG) {
-                Log.d(TAG, "upload successful");
-            }
-        } catch (final IOException e) {
-            Log.e(TAG, "Exception uploading file", e);
-        } finally {
-            if (fileInputStream != null) {
-                try {
-                    fileInputStream.close();
-                } catch (final IOException e) {
-                    Log.e(TAG, "Exception closing uploaded file", e);
-                }
-            }
-            if (connection != null) {
-                connection.disconnect();
-            }
-        }
-    }
-
-    private static void uploadContents(final InputStream is, final OutputStream os)
-            throws IOException {
-        // TODO: Switch to NIO.
-        final byte[] buf = new byte[BUF_SIZE];
-        int numBytesRead;
-        while ((numBytesRead = is.read(buf)) != -1) {
-            os.write(buf, 0, numBytesRead);
-        }
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/UploaderService.java b/java/src/com/android/inputmethod/research/UploaderService.java
deleted file mode 100644
index fd3f2f6..0000000
--- a/java/src/com/android/inputmethod/research/UploaderService.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2012 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.research;
-
-import android.app.AlarmManager;
-import android.app.IntentService;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.SystemClock;
-
-/**
- * Service to invoke the uploader.
- *
- * Can be regularly invoked, invoked on boot, etc.
- */
-public final class UploaderService extends IntentService {
-    private static final String TAG = UploaderService.class.getSimpleName();
-    public static final long RUN_INTERVAL = AlarmManager.INTERVAL_HOUR;
-    public static final String EXTRA_UPLOAD_UNCONDITIONALLY = UploaderService.class.getName()
-            + ".extra.UPLOAD_UNCONDITIONALLY";
-
-    public UploaderService() {
-        super("Research Uploader Service");
-    }
-
-    @Override
-    protected void onHandleIntent(final Intent intent) {
-        // We may reach this point either because the alarm fired, or because the system explicitly
-        // requested that an Upload occur.  In the latter case, we want to cancel the alarm in case
-        // it's about to fire.
-        cancelAndRescheduleUploadingService(this, false /* needsRescheduling */);
-
-        final Uploader uploader = new Uploader(this);
-        if (!uploader.isPossibleToUpload()) return;
-        if (isUploadingUnconditionally(intent.getExtras()) || uploader.isConvenientToUpload()) {
-            uploader.doUpload();
-        }
-        cancelAndRescheduleUploadingService(this, true /* needsRescheduling */);
-    }
-
-    private boolean isUploadingUnconditionally(final Bundle bundle) {
-        if (bundle == null) return false;
-        if (bundle.containsKey(EXTRA_UPLOAD_UNCONDITIONALLY)) {
-            return bundle.getBoolean(EXTRA_UPLOAD_UNCONDITIONALLY);
-        }
-        return false;
-    }
-
-    /**
-     * Arrange for the UploaderService to be run on a regular basis.
-     *
-     * Any existing scheduled invocation of UploaderService is removed and optionally rescheduled.
-     * This may cause problems if this method is called so often that no scheduled invocation is
-     * ever run.  But if the delay is short enough that it will go off when the user is sleeping,
-     * then there should be no starvation.
-     *
-     * @param context {@link Context} object
-     * @param needsRescheduling whether to schedule a future intent to be delivered to this service
-     */
-    public static void cancelAndRescheduleUploadingService(final Context context,
-            final boolean needsRescheduling) {
-        final Intent intent = new Intent(context, UploaderService.class);
-        final PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
-        final AlarmManager alarmManager = (AlarmManager) context.getSystemService(
-                Context.ALARM_SERVICE);
-        alarmManager.cancel(pendingIntent);
-        if (needsRescheduling) {
-            alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()
-                    + UploaderService.RUN_INTERVAL, pendingIntent);
-        }
-    }
-}
diff --git a/java/src/com/android/inputmethod/research/ui/SplashScreen.java b/java/src/com/android/inputmethod/research/ui/SplashScreen.java
deleted file mode 100644
index 78ed668..0000000
--- a/java/src/com/android/inputmethod/research/ui/SplashScreen.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2013 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.research.ui;
-
-import android.app.AlertDialog.Builder;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.Intent;
-import android.inputmethodservice.InputMethodService;
-import android.net.Uri;
-import android.os.IBinder;
-import android.view.Window;
-import android.view.WindowManager.LayoutParams;
-
-import com.android.inputmethod.latin.R.string;
-
-/**
- * Show a dialog when the user first opens the keyboard.
- *
- * The splash screen is a modal dialog box presented when the user opens this keyboard for the first
- * time.  It is useful for giving specific warnings that must be shown to the user before use.
- *
- * While the splash screen does share with the setup wizard the common goal of presenting
- * information to the user before use, they are presented at different times and with different
- * capabilities.  The setup wizard is launched by tapping on the icon, and walks the user through
- * the setup process.  It can, however, be bypassed by enabling the keyboard from Settings directly.
- * The splash screen cannot be bypassed, and is therefore more appropriate for obtaining user
- * consent.
- */
-public class SplashScreen {
-    public interface UserConsentListener {
-        public void onSplashScreenUserClickedOk();
-    }
-
-    final UserConsentListener mListener;
-    final Dialog mSplashDialog;
-
-    public SplashScreen(final InputMethodService inputMethodService,
-            final UserConsentListener listener) {
-        mListener = listener;
-        final Builder builder = new Builder(inputMethodService)
-                .setTitle(string.research_splash_title)
-                .setMessage(string.research_splash_content)
-                .setPositiveButton(android.R.string.yes,
-                        new DialogInterface.OnClickListener() {
-                            @Override
-                            public void onClick(DialogInterface dialog, int which) {
-                                mListener.onSplashScreenUserClickedOk();
-                                mSplashDialog.dismiss();
-                            }
-                })
-                .setNegativeButton(android.R.string.no,
-                        new DialogInterface.OnClickListener() {
-                            @Override
-                            public void onClick(DialogInterface dialog, int which) {
-                                final String packageName = inputMethodService.getPackageName();
-                                final Uri packageUri = Uri.parse("package:" + packageName);
-                                final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE,
-                                        packageUri);
-                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                                inputMethodService.startActivity(intent);
-                            }
-                })
-                .setCancelable(true)
-                .setOnCancelListener(
-                        new OnCancelListener() {
-                            @Override
-                            public void onCancel(DialogInterface dialog) {
-                                inputMethodService.requestHideSelf(0);
-                            }
-                });
-        mSplashDialog = builder.create();
-    }
-
-    /**
-     * Show the splash screen.
-     *
-     * The user must consent to the terms presented in the SplashScreen before they can use the
-     * keyboard.  If they cancel instead, they are given the option to uninstall the keybard.
-     *
-     * @param windowToken {@link IBinder} to attach dialog to
-     */
-    public void showSplashScreen(final IBinder windowToken) {
-        final Window window = mSplashDialog.getWindow();
-        final LayoutParams lp = window.getAttributes();
-        lp.token = windowToken;
-        lp.type = LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
-        window.setAttributes(lp);
-        window.addFlags(LayoutParams.FLAG_ALT_FOCUSABLE_IM);
-        mSplashDialog.show();
-    }
-
-    public boolean isShowing() {
-        return mSplashDialog.isShowing();
-    }
-}
diff --git a/tests/src/com/android/inputmethod/research/MotionEventReaderTests.java b/tests/src/com/android/inputmethod/research/MotionEventReaderTests.java
deleted file mode 100644
index 28a9f3d..0000000
--- a/tests/src/com/android/inputmethod/research/MotionEventReaderTests.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2013 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.research;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.JsonReader;
-
-import com.android.inputmethod.research.MotionEventReader.ReplayData;
-
-import java.io.IOException;
-import java.io.StringReader;
-
-@SmallTest
-public class MotionEventReaderTests extends AndroidTestCase {
-    private MotionEventReader mMotionEventReader = new MotionEventReader();
-    private ReplayData mReplayData;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mReplayData = new ReplayData();
-    }
-
-    private JsonReader jsonReaderForString(final String s) {
-        return new JsonReader(new StringReader(s));
-    }
-
-    public void testTopLevelDataVariant() {
-        final JsonReader jsonReader = jsonReaderForString(
-                "{"
-                + "\"_ct\": 1359590400000,"
-                + "\"_ut\": 4381933,"
-                + "\"_ty\": \"MotionEvent\","
-                + "\"action\": \"UP\","
-                + "\"isLoggingRelated\": false,"
-                + "\"x\": 100.0,"
-                + "\"y\": 200.0"
-                + "}"
-                );
-        try {
-            mMotionEventReader.readLogStatement(jsonReader, mReplayData);
-        } catch (IOException e) {
-            e.printStackTrace();
-            fail("IOException thrown");
-        }
-        assertEquals("x set correctly", (int) mReplayData.mPointerCoordsArrays.get(0)[0].x, 100);
-        assertEquals("y set correctly", (int) mReplayData.mPointerCoordsArrays.get(0)[0].y, 200);
-        assertEquals("only one pointer", mReplayData.mPointerCoordsArrays.get(0).length, 1);
-        assertEquals("only one MotionEvent", mReplayData.mPointerCoordsArrays.size(), 1);
-    }
-
-    public void testNestedDataVariant() {
-        final JsonReader jsonReader = jsonReaderForString(
-                "{"
-                + "  \"_ct\": 135959040000,"
-                + "  \"_ut\": 4382702,"
-                + "  \"_ty\": \"MotionEvent\","
-                + "  \"action\": \"MOVE\","
-                + "  \"isLoggingRelated\": false,"
-                + "  \"motionEvent\": {"
-                + "    \"pointerIds\": ["
-                + "      0"
-                + "    ],"
-                + "    \"xyt\": ["
-                + "      {"
-                + "        \"t\": 4382551,"
-                + "        \"d\": ["
-                + "          {"
-                + "            \"x\": 100.0,"
-                + "            \"y\": 200.0,"
-                + "            \"toma\": 999.0,"
-                + "            \"tomi\": 999.0,"
-                + "            \"o\": 0.0"
-                + "          }"
-                + "        ]"
-                + "      },"
-                + "      {"
-                + "        \"t\": 4382559,"
-                + "        \"d\": ["
-                + "          {"
-                + "            \"x\": 300.0,"
-                + "            \"y\": 400.0,"
-                + "            \"toma\": 999.0,"
-                + "            \"tomi\": 999.0,"
-                + "            \"o\": 0.0"
-                + "          }"
-                + "        ]"
-                + "      }"
-                + "    ]"
-                + "  }"
-                + "}"
-                );
-        try {
-            mMotionEventReader.readLogStatement(jsonReader, mReplayData);
-        } catch (IOException e) {
-            e.printStackTrace();
-            fail("IOException thrown");
-        }
-        assertEquals("x1 set correctly", (int) mReplayData.mPointerCoordsArrays.get(0)[0].x, 100);
-        assertEquals("y1 set correctly", (int) mReplayData.mPointerCoordsArrays.get(0)[0].y, 200);
-        assertEquals("x2 set correctly", (int) mReplayData.mPointerCoordsArrays.get(1)[0].x, 300);
-        assertEquals("y2 set correctly", (int) mReplayData.mPointerCoordsArrays.get(1)[0].y, 400);
-        assertEquals("only one pointer", mReplayData.mPointerCoordsArrays.get(0).length, 1);
-        assertEquals("two MotionEvents", mReplayData.mPointerCoordsArrays.size(), 2);
-    }
-
-    public void testNestedDataVariantMultiPointer() {
-        final JsonReader jsonReader = jsonReaderForString(
-                "{"
-                + "  \"_ct\": 135959040000,"
-                + "  \"_ut\": 4382702,"
-                + "  \"_ty\": \"MotionEvent\","
-                + "  \"action\": \"MOVE\","
-                + "  \"isLoggingRelated\": false,"
-                + "  \"motionEvent\": {"
-                + "    \"pointerIds\": ["
-                + "      1"
-                + "    ],"
-                + "    \"xyt\": ["
-                + "      {"
-                + "        \"t\": 4382551,"
-                + "        \"d\": ["
-                + "          {"
-                + "            \"x\": 100.0,"
-                + "            \"y\": 200.0,"
-                + "            \"toma\": 999.0,"
-                + "            \"tomi\": 999.0,"
-                + "            \"o\": 0.0"
-                + "          },"
-                + "          {"
-                + "            \"x\": 300.0,"
-                + "            \"y\": 400.0,"
-                + "            \"toma\": 999.0,"
-                + "            \"tomi\": 999.0,"
-                + "            \"o\": 0.0"
-                + "          }"
-                + "        ]"
-                + "      }"
-                + "    ]"
-                + "  }"
-                + "}"
-                );
-        try {
-            mMotionEventReader.readLogStatement(jsonReader, mReplayData);
-        } catch (IOException e) {
-            e.printStackTrace();
-            fail("IOException thrown");
-        }
-        assertEquals("x1 set correctly", (int) mReplayData.mPointerCoordsArrays.get(0)[0].x, 100);
-        assertEquals("y1 set correctly", (int) mReplayData.mPointerCoordsArrays.get(0)[0].y, 200);
-        assertEquals("x2 set correctly", (int) mReplayData.mPointerCoordsArrays.get(0)[1].x, 300);
-        assertEquals("y2 set correctly", (int) mReplayData.mPointerCoordsArrays.get(0)[1].y, 400);
-        assertEquals("two pointers", mReplayData.mPointerCoordsArrays.get(0).length, 2);
-        assertEquals("one MotionEvent", mReplayData.mPointerCoordsArrays.size(), 1);
-    }
-}