Merge "Add read support for string shortcuts for makedict."
diff --git a/java/res/values-en/donottranslate-more-keys.xml b/java/res/values-en/donottranslate-more-keys.xml
index 9073d3b..6e43e86 100644
--- a/java/res/values-en/donottranslate-more-keys.xml
+++ b/java/res/values-en/donottranslate-more-keys.xml
@@ -18,12 +18,46 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="more_keys_for_a">à,á,â,ä,æ,ã,å,ā</string>
-    <string name="more_keys_for_e">è,é,ê,ë,ē</string>
-    <string name="more_keys_for_i">î,ï,í,ī,ì</string>
-    <string name="more_keys_for_o">ô,ö,ò,ó,œ,ø,ō,õ</string>
-    <string name="more_keys_for_s">ß</string>
-    <string name="more_keys_for_u">û,ü,ù,ú,ū</string>
-    <string name="more_keys_for_n">ñ</string>
-    <string name="more_keys_for_c">ç</string>
+    <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+         U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+         U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+         U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+         U+00E6: "æ" LATIN SMALL LETTER AE
+         U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+         U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+         U+0101: "ā" LATIN SMALL LETTER A WITH MACRON -->
+    <string name="more_keys_for_a">&#x00E0;,&#x00E1;,&#x00E2;,&#x00E4;,&#x00E6;,&#x00E3;,&#x00E5;,&#x0101;</string>
+    <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+         U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+         U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+         U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+         U+0113: "ē" LATIN SMALL LETTER E WITH MACRON -->
+    <string name="more_keys_for_e">&#x00E8;,&#x00E9;,&#x00EA;,&#x00EB;,&#x0103;</string>
+    <!-- U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+         U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+         U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+         U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+         U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE -->
+    <string name="more_keys_for_i">&#x00EE;,&#x00EF;,&#x00ED;,&#x012B;,&#x00EC;</string>
+    <!-- U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+         U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+         U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+         U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+         U+0153: "œ" LATIN SMALL LIGATURE OE
+         U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+         U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+         U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE -->
+    <string name="more_keys_for_o">&#x00F4;,&#x00F6;,&#x00F2;,&#x00F3;,&#x0153;,&#x00F8;&#x014D;,&#x00F5;</string>
+    <!-- U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+         U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+         U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+         U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+         U+016B: "ū" LATIN SMALL LETTER U WITH MACRON -->
+    <string name="more_keys_for_u">&#x00FB;,&#x00FC;,&#x00F9;,&#x00FA;,&#x016B;</string>
+    <!-- U+00DF: "ß" LATIN SMALL LETTER SHARP S -->
+    <string name="more_keys_for_s">&#x00DF;</string>
+    <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE -->
+    <string name="more_keys_for_n">&#x00F1;</string>
+    <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA -->
+    <string name="more_keys_for_c">&#x00E7;</string>
 </resources>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index 5197308..4456f08 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -109,11 +109,11 @@
     <string name="voice_listening" msgid="467518160751321844">"Ucapkan sekarang"</string>
     <string name="voice_working" msgid="6666937792815731889">"Bekerja"</string>
     <string name="voice_initializing" msgid="661962047129906646"></string>
-    <string name="voice_error" msgid="5140896300312186162">"Galat: Coba lagi."</string>
+    <string name="voice_error" msgid="5140896300312186162">"Kesalahan: Coba lagi."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Tidak dapat menyambung"</string>
-    <string name="voice_too_much_speech" msgid="5746973620134227376">"Galat, terlalu banyak ucapan."</string>
+    <string name="voice_too_much_speech" msgid="5746973620134227376">"Kesalahan, terlalu banyak ucapan."</string>
     <string name="voice_audio_error" msgid="5072707727016414454">"Masalah audio"</string>
-    <string name="voice_server_error" msgid="7807129913977261644">"Galat server"</string>
+    <string name="voice_server_error" msgid="7807129913977261644">"Kesalahan server"</string>
     <string name="voice_speech_timeout" msgid="8461817525075498795">"Tidak terdengar ucapan"</string>
     <string name="voice_no_match" msgid="4285117547030179174">"Tak ditemukan yang cocok"</string>
     <string name="voice_not_installed" msgid="5552450909753842415">"Penelusuran suara tidak terpasang"</string>
diff --git a/java/res/values-is/donottranslate-more-keys.xml b/java/res/values-is/donottranslate-more-keys.xml
new file mode 100644
index 0000000..2c3fa1e
--- /dev/null
+++ b/java/res/values-is/donottranslate-more-keys.xml
@@ -0,0 +1,73 @@
+<?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">
+    <!-- U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+         U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+         U+00E6: "æ" LATIN SMALL LETTER AE
+         U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+         U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+         U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+         U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+         U+0101: "ā" LATIN SMALL LETTER A WITH MACRON -->
+    <string name="more_keys_for_a">&#x00E1;,&#x00E4;,&#x00E6;,&#x00E5;,&#x00E0;,&#x00E2;,&#x00E3;,&#x0101;</string>
+    <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+         U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+         U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+         U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+         U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+         U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+         U+0113: "ē" LATIN SMALL LETTER E WITH MACRON -->
+    <string name="more_keys_for_e">&#x00E9;,&#x00EB;,&#x00E8;,&#x00EA;,&#x0119;,&#x0117;,&#x0113;</string>
+    <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+         U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+         U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+         U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+         U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+         U+012B: "ī" LATIN SMALL LETTER I WITH MACRON -->
+    <string name="more_keys_for_i">&#x00ED;,&#x00EF;,&#x00EE;,&#x00EC;,&#x012F;,&#x012B;</string>
+    <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+         U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+         U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+         U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+         U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+         U+0153: "œ" LATIN SMALL LIGATURE OE
+         U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+         U+014D: "ō" LATIN SMALL LETTER O WITH MACRON -->
+    <string name="more_keys_for_o">&#x00F3;,&#x00F6;,&#x00F4;,&#x00F2;,&#x00F5;,&#x0153;,&#x00F8;,&#x014D;</string>
+    <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+         U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+         U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+         U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+         U+016B: "ū" LATIN SMALL LETTER U WITH MACRON -->
+    <string name="more_keys_for_u">&#x00FA;,&#x00FC;,&#x00FB;,&#x00F9;,&#x016B;</string>
+    <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+         U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS -->
+    <string name="more_keys_for_y">&#x00FD;,&#x00FF;</string>
+    <!-- U+00F0: "ð" LATIN SMALL LETTER ETH -->
+    <string name="more_keys_for_d">&#x00F0;</string>
+    <!-- U+00FE: "þ" LATIN SMALL LETTER THORN -->
+    <string name="more_keys_for_t">&#x00FE;</string>
+    <!-- U+00F0: "ð" LATIN SMALL LETTER ETH -->
+    <string name="keylabel_for_scandinavia_row1_11">&#x00F0;</string>
+    <!-- U+00E6: "æ" LATIN SMALL LETTER AE -->
+    <string name="keylabel_for_scandinavia_row2_10">&#x00E6;</string>
+    <!-- U+00FE: "þ" LATIN SMALL LETTER THORN -->
+    <string name="keylabel_for_scandinavia_row2_11">&#x00FE;</string>
+</resources>
diff --git a/java/res/values-sw600dp/dimens.xml b/java/res/values-sw600dp/dimens.xml
index f03ce29..cb2a861 100644
--- a/java/res/values-sw600dp/dimens.xml
+++ b/java/res/values-sw600dp/dimens.xml
@@ -22,7 +22,7 @@
     <!-- Preferable keyboard height in absolute scale: 48.0mm -->
     <!-- This keyboardHeight value should match with keyboard-heights.xml -->
     <dimen name="keyboardHeight">302.4dp</dimen>
-    <fraction name="maxKeyboardHeight">50%p</fraction>
+    <fraction name="maxKeyboardHeight">46%p</fraction>
     <fraction name="minKeyboardHeight">-35.0%p</fraction>
 
     <dimen name="popup_key_height">63.0dp</dimen>
diff --git a/java/res/values-sw768dp/dimens.xml b/java/res/values-sw768dp/dimens.xml
index 0a362fd..01e2284 100644
--- a/java/res/values-sw768dp/dimens.xml
+++ b/java/res/values-sw768dp/dimens.xml
@@ -22,7 +22,7 @@
     <!-- Preferable keyboard height in absolute scale: 48.0mm -->
     <!-- This keyboardHeight value should match with keyboard-heights.xml -->
     <dimen name="keyboardHeight">302.4dp</dimen>
-    <fraction name="maxKeyboardHeight">50%p</fraction>
+    <fraction name="maxKeyboardHeight">46%p</fraction>
     <fraction name="minKeyboardHeight">-35.0%p</fraction>
 
     <fraction name="keyboard_top_padding">2.291%p</fraction>
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index 1889758..7eb57c3 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -22,7 +22,7 @@
     <!-- Preferable keyboard height in absolute scale: 1.285in -->
     <!-- This keyboardHeight value should match with keyboard-heights.xml -->
     <dimen name="keyboardHeight">205.6dp</dimen>
-    <fraction name="maxKeyboardHeight">50%p</fraction>
+    <fraction name="maxKeyboardHeight">46%p</fraction>
     <fraction name="minKeyboardHeight">-61.8%p</fraction>
 
     <dimen name="popup_key_height">52.8dp</dimen>
diff --git a/java/res/xml-is/keyboard_set.xml b/java/res/xml-is/keyboard_set.xml
new file mode 100644
index 0000000..077bc6b
--- /dev/null
+++ b/java/res/xml-is/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?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.
+*/
+-->
+
+<KeyboardSet
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+    latin:keyboardLocale="is">
+    <Element
+        latin:elementName="alphabet"
+        latin:elementKeyboard="@xml/kbd_nordic" />
+    <Element
+        latin:elementName="symbols"
+        latin:elementKeyboard="@xml/kbd_symbols" />
+    <Element
+        latin:elementName="symbolsShifted"
+        latin:elementKeyboard="@xml/kbd_symbols_shift" />
+    <Element
+        latin:elementName="phone"
+        latin:elementKeyboard="@xml/kbd_phone" />
+    <Element
+        latin:elementName="phoneSymbols"
+        latin:elementKeyboard="@xml/kbd_phone_symbols" />
+    <Element
+        latin:elementName="number"
+        latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-sw600dp-land/kbd_thai.xml b/java/res/xml-sw600dp-land/kbd_thai.xml
index ac36ea5..b75980f 100644
--- a/java/res/xml-sw600dp-land/kbd_thai.xml
+++ b/java/res/xml-sw600dp-land/kbd_thai.xml
@@ -22,6 +22,7 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
     latin:rowHeight="20%p"
     latin:verticalGap="3.20%p"
+    latin:touchPositionCorrectionData="@null"
 >
     <include
         latin:keyboardLayout="@xml/rows_thai" />
diff --git a/java/res/xml-sw600dp/kbd_thai.xml b/java/res/xml-sw600dp/kbd_thai.xml
index ac36ea5..b75980f 100644
--- a/java/res/xml-sw600dp/kbd_thai.xml
+++ b/java/res/xml-sw600dp/kbd_thai.xml
@@ -22,6 +22,7 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
     latin:rowHeight="20%p"
     latin:verticalGap="3.20%p"
+    latin:touchPositionCorrectionData="@null"
 >
     <include
         latin:keyboardLayout="@xml/rows_thai" />
diff --git a/java/res/xml-sw768dp-land/kbd_thai.xml b/java/res/xml-sw768dp-land/kbd_thai.xml
index 4bfc9cb..b2cdbc3 100644
--- a/java/res/xml-sw768dp-land/kbd_thai.xml
+++ b/java/res/xml-sw768dp-land/kbd_thai.xml
@@ -22,6 +22,7 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
     latin:rowHeight="20%p"
     latin:verticalGap="2.65%p"
+    latin:touchPositionCorrectionData="@null"
 >
     <include
         latin:keyboardLayout="@xml/rows_thai" />
diff --git a/java/res/xml-sw768dp-land/kbd_thai_symbols.xml b/java/res/xml-sw768dp-land/kbd_thai_symbols.xml
index a3feeaa..1531458 100644
--- a/java/res/xml-sw768dp-land/kbd_thai_symbols.xml
+++ b/java/res/xml-sw768dp-land/kbd_thai_symbols.xml
@@ -22,6 +22,7 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
     latin:rowHeight="20%p"
     latin:verticalGap="2.65%p"
+    latin:touchPositionCorrectionData="@null"
 >
     <include
         latin:keyboardLayout="@xml/rows_thai_symbols" />
diff --git a/java/res/xml-sw768dp-land/kbd_thai_symbols_shift.xml b/java/res/xml-sw768dp-land/kbd_thai_symbols_shift.xml
index 8b4a8ea..fa30f24 100644
--- a/java/res/xml-sw768dp-land/kbd_thai_symbols_shift.xml
+++ b/java/res/xml-sw768dp-land/kbd_thai_symbols_shift.xml
@@ -22,6 +22,7 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
     latin:rowHeight="20%p"
     latin:verticalGap="2.65%p"
+    latin:touchPositionCorrectionData="@null"
 >
     <include
         latin:keyboardLayout="@xml/rows_thai_symbols_shift" />
diff --git a/java/res/xml-sw768dp/kbd_thai.xml b/java/res/xml-sw768dp/kbd_thai.xml
index dd0ac36..593ccbd 100644
--- a/java/res/xml-sw768dp/kbd_thai.xml
+++ b/java/res/xml-sw768dp/kbd_thai.xml
@@ -22,6 +22,7 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
     latin:rowHeight="20%p"
     latin:verticalGap="2.95%p"
+    latin:touchPositionCorrectionData="@null"
 >
     <include
         latin:keyboardLayout="@xml/rows_thai" />
diff --git a/java/res/xml-sw768dp/kbd_thai_symbols.xml b/java/res/xml-sw768dp/kbd_thai_symbols.xml
index 91cf808..e2e5f5d 100644
--- a/java/res/xml-sw768dp/kbd_thai_symbols.xml
+++ b/java/res/xml-sw768dp/kbd_thai_symbols.xml
@@ -22,6 +22,7 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
     latin:rowHeight="20%p"
     latin:verticalGap="2.95%p"
+    latin:touchPositionCorrectionData="@null"
 >
     <include
         latin:keyboardLayout="@xml/rows_thai_symbols" />
diff --git a/java/res/xml-sw768dp/kbd_thai_symbols_shift.xml b/java/res/xml-sw768dp/kbd_thai_symbols_shift.xml
index 85745ac..a1358d4 100644
--- a/java/res/xml-sw768dp/kbd_thai_symbols_shift.xml
+++ b/java/res/xml-sw768dp/kbd_thai_symbols_shift.xml
@@ -22,6 +22,7 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
     latin:rowHeight="20%p"
     latin:verticalGap="2.95%p"
+    latin:touchPositionCorrectionData="@null"
 >
     <include
         latin:keyboardLayout="@xml/rows_thai_symbols_shift" />
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 544f3fd..d6ded66 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -41,6 +41,7 @@
     hi: Hindi/hindi
     hr: Croatian/qwertz
     hu: Hungarian/qwertz
+    is: Icelandic/qwerty
     it: Italian/qwerty
     iw: Hebrew/hebrew
     ka: Georgian/georgian
@@ -73,230 +74,224 @@
             android:label="@string/subtype_en_US"
             android:imeSubtypeLocale="en_US"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection,EnabledWhenDefaultIsNotAsciiCapable"
+            android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,EnabledWhenDefaultIsNotAsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_en_GB"
             android:imeSubtypeLocale="en_GB"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="ar"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="be"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="bg"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="cs"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="da"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="de"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic_qwerty"
             android:imeSubtypeLocale="de"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,KeyboardLocale=de_ZZ,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable,KeyboardLocale=de_ZZ"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="el"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="es"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="et"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="fa"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="fi"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="fr"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="fr_CA"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="fr_CH"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="hi"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="hr"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="hu"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
+    />
+    <subtype android:icon="@drawable/ic_subtype_keyboard"
+            android:label="@string/subtype_generic"
+            android:imeSubtypeLocale="is"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="it"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <!-- Java uses the deprecated "iw" code instead of the standard "he" code for Hebrew. -->
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="iw"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="ka"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="ky"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="lt"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="lv"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="mk"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="nb"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="nl"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="pl"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="pt"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="ro"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="ru"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="sk"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="sl"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="sr"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="sv"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="tr"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
@@ -308,12 +303,11 @@
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="uk"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="vi"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
+            android:imeSubtypeExtraValue="AsciiCapable"
     />
 </input-method>
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index e82d914..a9e4840 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -48,21 +48,30 @@
             Context.class, Locale.class, String[].class, int.class, Class.class };
     private static final Constructor<?> CONSTRUCTOR_SuggestionSpan = CompatUtils
             .getConstructor(CLASS_SuggestionSpan, INPUT_TYPE_SuggestionSpan);
-    public static final Field FIELD_FLAG_AUTO_CORRECTION
-            = CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_AUTO_CORRECTION");
+    public static final Field FIELD_FLAG_EASY_CORRECT =
+            CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_EASY_CORRECT");
+    public static final Field FIELD_FLAG_MISSPELLED =
+            CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_MISSPELLED");
+    public static final Field FIELD_FLAG_AUTO_CORRECTION =
+            CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_AUTO_CORRECTION");
     public static final Field FIELD_SUGGESTIONS_MAX_SIZE
             = CompatUtils.getField(CLASS_SuggestionSpan, "SUGGESTIONS_MAX_SIZE");
+    public static final Integer OBJ_FLAG_EASY_CORRECT = (Integer) CompatUtils
+            .getFieldValue(null, null, FIELD_FLAG_EASY_CORRECT);
+    public static final Integer OBJ_FLAG_MISSPELLED = (Integer) CompatUtils
+            .getFieldValue(null, null, FIELD_FLAG_MISSPELLED);
     public static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils
-            .getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION);;
+            .getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION);
     public static final Integer OBJ_SUGGESTIONS_MAX_SIZE = (Integer) CompatUtils
-            .getFieldValue(null, null, FIELD_SUGGESTIONS_MAX_SIZE);;
+            .getFieldValue(null, null, FIELD_SUGGESTIONS_MAX_SIZE);
 
     static {
         SUGGESTION_SPAN_IS_SUPPORTED =
                 CLASS_SuggestionSpan != null && CONSTRUCTOR_SuggestionSpan != null;
         if (LatinImeLogger.sDBG) {
             if (SUGGESTION_SPAN_IS_SUPPORTED
-                    && (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null)) {
+                    && (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null
+                            || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null)) {
                 throw new RuntimeException("Field is accidentially null.");
             }
         }
@@ -71,7 +80,8 @@
     public static CharSequence getTextWithAutoCorrectionIndicatorUnderline(
             Context context, CharSequence text) {
         if (TextUtils.isEmpty(text) || CONSTRUCTOR_SuggestionSpan == null
-                || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null) {
+                || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null
+                || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null) {
             return text;
         }
         final Spannable spannable = text instanceof Spannable
@@ -104,6 +114,7 @@
             spannable = new SpannableString(pickedWord);
         }
         final ArrayList<String> suggestionsList = new ArrayList<String>();
+        boolean sameAsTyped = false;
         for (int i = 0; i < suggestedWords.size(); ++i) {
             if (suggestionsList.size() >= OBJ_SUGGESTIONS_MAX_SIZE) {
                 break;
@@ -111,11 +122,18 @@
             final CharSequence word = suggestedWords.getWord(i);
             if (!TextUtils.equals(pickedWord, word)) {
                 suggestionsList.add(word.toString());
+            } else if (i == 0) {
+                sameAsTyped = true;
             }
         }
+        // TODO: Share the implementation for checking typed word validity between the IME
+        // and the spell checker.
+        final int flag = (sameAsTyped && !suggestedWords.mTypedWordValid)
+                ? ((int)OBJ_FLAG_EASY_CORRECT | (int)OBJ_FLAG_MISSPELLED)
+                : 0;
 
         final Object[] args =
-                { context, null, suggestionsList.toArray(new String[suggestionsList.size()]), 0,
+                { context, null, suggestionsList.toArray(new String[suggestionsList.size()]), flag,
                         (Class<?>) SuggestionSpanPickedNotificationReceiver.class };
         final Object ss = CompatUtils.newInstance(CONSTRUCTOR_SuggestionSpan, args);
         if (ss == null) {
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 9623790..bc48b85 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -278,6 +278,7 @@
                 }
             }
 
+            // TODO: Remove this method.
             public void setEnabled(boolean enabled) {
                 mEnabled = enabled;
             }
@@ -616,29 +617,10 @@
 
             mParams = params;
 
-            setTouchPositionCorrectionData(context, params);
-
             params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
             params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
         }
 
-        private static void setTouchPositionCorrectionData(Context context, Params params) {
-            final TypedArray a = context.obtainStyledAttributes(
-                    null, R.styleable.Keyboard, R.attr.keyboardStyle, 0);
-            params.mThemeId = a.getInt(R.styleable.Keyboard_themeId, 0);
-            final int resourceId = a.getResourceId(
-                    R.styleable.Keyboard_touchPositionCorrectionData, 0);
-            a.recycle();
-            if (resourceId == 0) {
-                if (LatinImeLogger.sDBG)
-                    Log.e(BUILDER_TAG, "touchPositionCorrectionData is not defined");
-                return;
-            }
-
-            final String[] data = context.getResources().getStringArray(resourceId);
-            params.mTouchPositionCorrection.load(data);
-        }
-
         public void setAutoGenerate(KeyboardSet.KeysCache keysCache) {
             mParams.mKeysCache = keysCache;
         }
@@ -660,6 +642,7 @@
             return this;
         }
 
+        // TODO: Remove this method.
         public void setTouchPositionCorrectionEnabled(boolean enabled) {
             mParams.mTouchPositionCorrection.setEnabled(enabled);
         }
@@ -771,6 +754,15 @@
                         R.styleable.Keyboard_Key_maxMoreKeysColumn, 5);
 
                 params.mIconsSet.loadIcons(keyboardAttr);
+
+                params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0);
+                final int resourceId = keyboardAttr.getResourceId(
+                        R.styleable.Keyboard_touchPositionCorrectionData, 0);
+                params.mTouchPositionCorrection.setEnabled(resourceId != 0);
+                if (resourceId != 0) {
+                    final String[] data = mResources.getStringArray(resourceId);
+                    params.mTouchPositionCorrection.load(data);
+                }
             } finally {
                 keyAttr.recycle();
                 keyboardAttr.recycle();
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
index 52096c8..bb11a9b 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
@@ -63,8 +63,6 @@
             new HashMap<KeyboardId, SoftReference<Keyboard>>();
     private static final KeysCache sKeysCache = new KeysCache();
 
-    private static final EditorInfo EMPTY_EDITOR_INFO = new EditorInfo();
-
     public static class KeyboardSetException extends RuntimeException {
         public final KeyboardId mKeyboardId;
         public KeyboardSetException(Throwable cause, KeyboardId keyboardId) {
@@ -209,6 +207,8 @@
 
         private final Params mParams = new Params();
 
+        private static final EditorInfo EMPTY_EDITOR_INFO = new EditorInfo();
+
         public Builder(Context context, EditorInfo editorInfo) {
             mContext = context;
             mPackageName = context.getPackageName();
@@ -229,15 +229,13 @@
         }
 
         // TODO: Use InputMethodSubtype object as argument.
-        public Builder setSubtype(Locale inputLocale, boolean asciiCapable,
-                boolean touchPositionCorrectionEnabled) {
+        public Builder setSubtype(Locale inputLocale, boolean asciiCapable) {
             final boolean deprecatedForceAscii = StringUtils.inPrivateImeOptions(
                     mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo);
             final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(
                     mParams.mEditorInfo.imeOptions)
                     || deprecatedForceAscii;
             mParams.mLocale = (forceAscii && !asciiCapable) ? Locale.US : inputLocale;
-            mParams.mTouchPositionCorrectionEnabled = touchPositionCorrectionEnabled;
             return this;
         }
 
@@ -255,6 +253,10 @@
             return this;
         }
 
+        public void setTouchPositionCorrectionEnabled(boolean enabled) {
+            mParams.mTouchPositionCorrectionEnabled = enabled;
+        }
+
         public KeyboardSet build() {
             if (mParams.mOrientation == Configuration.ORIENTATION_UNDEFINED)
                 throw new RuntimeException("Screen geometry is not specified");
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 42dd620..93d8704 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -140,9 +140,7 @@
         builder.setSubtype(
                 mSubtypeSwitcher.getInputLocale(),
                 mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
-                        LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE),
-                mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
-                        LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION));
+                        LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE));
         builder.setOptions(
                 settingsValues.isVoiceKeyEnabled(editorInfo),
                 settingsValues.isVoiceKeyOnMain(),
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 24eb759..c1d11a0 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -124,6 +124,7 @@
     /** The canvas for the above mutable keyboard bitmap */
     private Canvas mCanvas;
     private final Paint mPaint = new Paint();
+    private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();
     // This map caches key label text height in pixel as value and key label text size as map key.
     private static final HashMap<Integer, Float> sTextHeightCache =
             new HashMap<Integer, Float>();
@@ -659,13 +660,14 @@
                 // The hint label is placed at top-right corner of the key. Used mainly on tablet.
                 hintX = keyWidth - params.mKeyShiftedLetterHintPadding
                         - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
-                hintY = -paint.ascent();
+                paint.getFontMetrics(mFontMetrics);
+                hintY = -mFontMetrics.top + params.mKeyShiftedLetterHintPadding;
                 paint.setTextAlign(Align.CENTER);
             } else { // key.hasHintLetter()
                 // The hint label is placed at top-right corner of the key. Used mainly on phone.
                 hintX = keyWidth - params.mKeyHintLetterPadding
                         - getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint) / 2;
-                hintY = -paint.ascent();
+                hintY = -paint.ascent() + params.mKeyHintLetterPadding;
                 paint.setTextAlign(Align.CENTER);
             }
             canvas.drawText(hint, 0, hint.length(), hintX, hintY, paint);
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 3f6c374..7194cce 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -52,6 +52,7 @@
 import com.android.inputmethod.latin.SubtypeUtils;
 import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils;
+import com.android.inputmethod.latin.define.ProductionFlag;
 
 import java.util.Locale;
 import java.util.WeakHashMap;
@@ -694,15 +695,17 @@
                         + size + "," + pressure);
             }
         }
-        if (ResearchLogger.sIsLogging) {
-            // TODO: remove redundant calculations of size and pressure by
-            // removing UsabilityStudyLog code once the ResearchLogger is mature enough
-            final float size = me.getSize(index);
-            final float pressure = me.getPressure(index);
-            if (action != MotionEvent.ACTION_MOVE) {
-                // Skip ACTION_MOVE events as they are logged below
-                ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x,
-                        y, size, pressure);
+        if (ProductionFlag.IS_EXPERIMENTAL) {
+            if (ResearchLogger.sIsLogging) {
+                // TODO: remove redundant calculations of size and pressure by
+                // removing UsabilityStudyLog code once the ResearchLogger is mature enough
+                final float size = me.getSize(index);
+                final float pressure = me.getPressure(index);
+                if (action != MotionEvent.ACTION_MOVE) {
+                    // Skip ACTION_MOVE events as they are logged below
+                    ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, y,
+                            size, pressure);
+                }
             }
         }
 
@@ -770,12 +773,14 @@
                             + pointerId + "," + px + "," + py + ","
                             + pointerSize + "," + pointerPressure);
                 }
-                if (ResearchLogger.sIsLogging) {
-                    // TODO: earlier comment about redundant calculations applies here too
-                    final float pointerSize = me.getSize(i);
-                    final float pointerPressure = me.getPressure(i);
-                    ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId,
-                            px, py, pointerSize, pointerPressure);
+                if (ProductionFlag.IS_EXPERIMENTAL) {
+                    if (ResearchLogger.sIsLogging) {
+                        // TODO: earlier comment about redundant calculations applies here too
+                        final float pointerSize = me.getSize(i);
+                        final float pointerPressure = me.getPressure(i);
+                        ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId,
+                                px, py, pointerSize, pointerPressure);
+                    }
                 }
             }
         } else {
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index a9df1ce..c43683f 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -40,14 +40,13 @@
     public static final int MAX_WORDS = 18;
 
     private static final String TAG = "BinaryDictionary";
-    private static final int MAX_PROXIMITY_CHARS_SIZE = ProximityInfo.MAX_PROXIMITY_CHARS_SIZE;
     private static final int MAX_BIGRAMS = 60;
 
     private static final int TYPED_LETTER_MULTIPLIER = 2;
 
     private int mDicTypeId;
     private long mNativeDict;
-    private final int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_PROXIMITY_CHARS_SIZE];
+    private final int[] mInputCodes = new int[MAX_WORD_LENGTH];
     private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS];
     private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS];
     private final int[] mScores = new int[MAX_WORDS];
@@ -111,8 +110,7 @@
     }
 
     private native long openNative(String sourceDir, long dictOffset, long dictSize,
-            int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength,
-            int maxWords, int maxAlternatives);
+            int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords);
     private native void closeNative(long dict);
     private native boolean isValidWordNative(long dict, char[] word, int wordLength);
     private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates,
@@ -120,7 +118,7 @@
             int[] scores);
     private native int getBigramsNative(long dict, char[] prevWord, int prevWordLength,
             int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores,
-            int maxWordLength, int maxBigrams, int maxAlternatives);
+            int maxWordLength, int maxBigrams);
     private static native double calcNormalizedScoreNative(
             char[] before, int beforeLength, char[] after, int afterLength, int score);
     private static native int editDistanceNative(
@@ -128,8 +126,7 @@
 
     private final void loadDictionary(String path, long startOffset, long length) {
         mNativeDict = openNative(path, startOffset, length,
-                    TYPED_LETTER_MULTIPLIER, FULL_WORD_SCORE_MULTIPLIER,
-                    MAX_WORD_LENGTH, MAX_WORDS, MAX_PROXIMITY_CHARS_SIZE);
+                TYPED_LETTER_MULTIPLIER, FULL_WORD_SCORE_MULTIPLIER, MAX_WORD_LENGTH, MAX_WORDS);
     }
 
     @Override
@@ -144,14 +141,11 @@
         int codesSize = codes.size();
         Arrays.fill(mInputCodes, -1);
         if (codesSize > 0) {
-            int[] alternatives = codes.getCodesAt(0);
-            System.arraycopy(alternatives, 0, mInputCodes, 0,
-                    Math.min(alternatives.length, MAX_PROXIMITY_CHARS_SIZE));
+            mInputCodes[0] = codes.getCodeAt(0);
         }
 
         int count = getBigramsNative(mNativeDict, chars, chars.length, mInputCodes, codesSize,
-                mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS,
-                MAX_PROXIMITY_CHARS_SIZE);
+                mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS);
         if (count > MAX_BIGRAMS) {
             count = MAX_BIGRAMS;
         }
@@ -205,11 +199,7 @@
 
         Arrays.fill(mInputCodes, WordComposer.NOT_A_CODE);
         for (int i = 0; i < codesSize; i++) {
-            final int[] alternatives = codes.getCodesAt(i);
-            if (alternatives == null || alternatives.length < 1) {
-                continue;
-            }
-            mInputCodes[i] = alternatives[0];
+            mInputCodes[i] = codes.getCodeAt(i);
         }
         Arrays.fill(outputChars, (char) 0);
         Arrays.fill(scores, 0);
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index 8e8adc1..098913b 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -28,17 +28,12 @@
  * be searched for suggestions and valid words.
  */
 public class ExpandableDictionary extends Dictionary {
-    /**
-     * There is difference between what java and native code can handle.
-     * It uses 32 because Java stack overflows when greater value is used.
-     */
-    protected static final int MAX_WORD_LENGTH = 32;
 
     // Bigram frequency is a fixed point number with 1 meaning 1.2 and 255 meaning 1.8.
     protected static final int BIGRAM_MAX_FREQUENCY = 255;
 
     private Context mContext;
-    private char[] mWordBuilder = new char[MAX_WORD_LENGTH];
+    private char[] mWordBuilder = new char[BinaryDictionary.MAX_WORD_LENGTH];
     private int mDicTypeId;
     private int mMaxDepth;
     private int mInputLength;
@@ -113,7 +108,7 @@
     public ExpandableDictionary(Context context, int dicTypeId) {
         mContext = context;
         clearDictionary();
-        mCodes = new int[MAX_WORD_LENGTH][];
+        mCodes = new int[BinaryDictionary.MAX_WORD_LENGTH][];
         mDicTypeId = dicTypeId;
     }
 
@@ -151,10 +146,13 @@
     }
 
     public int getMaxWordLength() {
-        return MAX_WORD_LENGTH;
+        return BinaryDictionary.MAX_WORD_LENGTH;
     }
 
     public void addWord(String word, int frequency) {
+        if (word.length() >= BinaryDictionary.MAX_WORD_LENGTH) {
+            return;
+        }
         addWordRec(mRoots, word, 0, frequency, null);
     }
 
@@ -201,6 +199,9 @@
             // Currently updating contacts, don't return any results.
             if (mUpdatingDictionary) return;
         }
+        if (codes.size() >= BinaryDictionary.MAX_WORD_LENGTH) {
+            return;
+        }
         getWordsInner(codes, callback, proximityInfo);
     }
 
@@ -210,7 +211,11 @@
         if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
         // Cache the codes so that we don't have to lookup an array list
         for (int i = 0; i < mInputLength; i++) {
-            mCodes[i] = codes.getCodesAt(i);
+            // TODO: Calculate proximity info here.
+            if (mCodes[i] == null || mCodes[i].length < 1) {
+                mCodes[i] = new int[1];
+            }
+            mCodes[i][0] = codes.getCodeAt(i);
         }
         mMaxDepth = mInputLength * 3;
         getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, callback);
@@ -319,7 +324,7 @@
                 }
             } else {
                 // Don't use alternatives if we're looking for missing characters
-                final int alternativesSize = skipPos >= 0? 1 : currentChars.length;
+                final int alternativesSize = skipPos >= 0 ? 1 : currentChars.length;
                 for (int j = 0; j < alternativesSize; j++) {
                     final int addedAttenuation = (j > 0 ? 1 : 2);
                     final int currentChar = currentChars[j];
@@ -484,7 +489,7 @@
     }
 
     // Local to reverseLookUp, but do not allocate each time.
-    private final char[] mLookedUpString = new char[MAX_WORD_LENGTH];
+    private final char[] mLookedUpString = new char[BinaryDictionary.MAX_WORD_LENGTH];
 
     /**
      * reverseLookUp retrieves the full word given a list of terminal nodes and adds those words
@@ -498,15 +503,15 @@
         for (NextWord nextWord : terminalNodes) {
             node = nextWord.mWord;
             freq = nextWord.getFrequency();
-            int index = MAX_WORD_LENGTH;
+            int index = BinaryDictionary.MAX_WORD_LENGTH;
             do {
                 --index;
                 mLookedUpString[index] = node.mCode;
                 node = node.mParent;
             } while (node != null);
 
-            callback.addWord(mLookedUpString, index, MAX_WORD_LENGTH - index, freq, mDicTypeId,
-                    Dictionary.BIGRAM);
+            callback.addWord(mLookedUpString, index, BinaryDictionary.MAX_WORD_LENGTH - index,
+                    freq, mDicTypeId, Dictionary.BIGRAM);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java
index bc07924..af0ef4b 100644
--- a/java/src/com/android/inputmethod/latin/LastComposedWord.java
+++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java
@@ -18,8 +18,6 @@
 
 import android.text.TextUtils;
 
-import java.util.ArrayList;
-
 /**
  * This class encapsulates data about a word previously composed, but that has been
  * committed already. This is used for resuming suggestion, and cancel auto-correction.
@@ -42,7 +40,7 @@
 
     public static final int NOT_A_SEPARATOR = -1;
 
-    public final ArrayList<int[]> mCodes;
+    public final int[] mPrimaryKeyCodes;
     public final int[] mXCoordinates;
     public final int[] mYCoordinates;
     public final String mTypedWord;
@@ -56,10 +54,10 @@
 
     // Warning: this is using the passed objects as is and fully expects them to be
     // immutable. Do not fiddle with their contents after you passed them to this constructor.
-    public LastComposedWord(final ArrayList<int[]> codes, final int[] xCoordinates,
+    public LastComposedWord(final int[] primaryKeyCodes, final int[] xCoordinates,
             final int[] yCoordinates, final String typedWord, final String committedWord,
             final int separatorCode) {
-        mCodes = codes;
+        mPrimaryKeyCodes = primaryKeyCodes;
         mXCoordinates = xCoordinates;
         mYCoordinates = yCoordinates;
         mTypedWord = typedWord;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 7272006..86c1539 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -69,6 +69,7 @@
 import com.android.inputmethod.keyboard.KeyboardView;
 import com.android.inputmethod.keyboard.LatinKeyboardView;
 import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils;
+import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.suggestions.SuggestionsView;
 
 import java.io.FileDescriptor;
@@ -124,12 +125,6 @@
     public static final String SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable";
 
     /**
-     * The subtype extra value used to indicate that the subtype keyboard layout supports touch
-     * position correction.
-     */
-    public static final String SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION =
-            "SupportTouchPositionCorrection";
-    /**
      * The subtype extra value used to indicate that the subtype keyboard layout should be loaded
      * from the specified locale.
      */
@@ -439,7 +434,9 @@
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
         mPrefs = prefs;
         LatinImeLogger.init(this, prefs);
-        ResearchLogger.init(this, prefs);
+        if (ProductionFlag.IS_EXPERIMENTAL) {
+            ResearchLogger.init(this, prefs);
+        }
         LanguageSwitcherProxy.init(this, prefs);
         InputMethodManagerCompatWrapper.init(this);
         SubtypeSwitcher.init(this);
@@ -1264,8 +1261,10 @@
         }
         mLastKeyTime = when;
 
-        if (ResearchLogger.sIsLogging) {
-            ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y);
+        if (ProductionFlag.IS_EXPERIMENTAL) {
+            if (ResearchLogger.sIsLogging) {
+                ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y);
+            }
         }
 
         final KeyboardSwitcher switcher = mKeyboardSwitcher;
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index 079f3b5..732efad 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -80,8 +80,4 @@
 
     public static void onPrintAllUsabilityStudyLogs() {
     }
-
-    public static boolean isResearcherPackage(Context context) {
-        return false;
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
index 3b110bd..0694ffe 100644
--- a/java/src/com/android/inputmethod/latin/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -41,7 +41,7 @@
  * 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.
+ * This functionality is off by default. See {@link ProductionFlag.IS_EXPERIMENTAL}.
  */
 public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String TAG = ResearchLogger.class.getSimpleName();
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 72391f3..1102648 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -46,6 +46,7 @@
 import com.android.inputmethod.compat.InputMethodServiceCompatWrapper;
 import com.android.inputmethod.compat.VibratorCompatWrapper;
 import com.android.inputmethod.deprecated.VoiceProxy;
+import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethodcommon.InputMethodSettingsActivity;
 
 import java.util.Locale;
@@ -238,17 +239,16 @@
             textCorrectionGroup.removePreference(dictionaryLink);
         }
 
-        final boolean isResearcherPackage = LatinImeLogger.isResearcherPackage(this);
         final boolean showUsabilityStudyModeOption =
                 res.getBoolean(R.bool.config_enable_usability_study_mode_option)
-                        || isResearcherPackage || ENABLE_EXPERIMENTAL_SETTINGS;
+                        || ProductionFlag.IS_EXPERIMENTAL || ENABLE_EXPERIMENTAL_SETTINGS;
         final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE);
         if (!showUsabilityStudyModeOption) {
             if (usabilityStudyPref != null) {
                 miscSettings.removePreference(usabilityStudyPref);
             }
         }
-        if (isResearcherPackage) {
+        if (ProductionFlag.IS_EXPERIMENTAL) {
             if (usabilityStudyPref instanceof CheckBoxPreference) {
                 CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref;
                 checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE, true));
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
index db2cdf9..62525c2 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
@@ -247,8 +247,8 @@
                     // to recursive lookup
                     if (null == word1) {
                         super.addWord(word2, frequency);
-                    } else if (word1.length() < MAX_WORD_LENGTH
-                            && word2.length() < MAX_WORD_LENGTH) {
+                    } else if (word1.length() < BinaryDictionary.MAX_WORD_LENGTH
+                            && word2.length() < BinaryDictionary.MAX_WORD_LENGTH) {
                         super.setBigram(word1, word2, frequency);
                     }
                     cursor.moveToNext();
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index be64c2f..0485c88 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -31,9 +31,7 @@
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.Log;
-import android.view.MotionEvent;
 
-import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 
 import java.io.BufferedReader;
@@ -112,7 +110,6 @@
         /* package */ static final int BUFSIZE = 20;
         private InputMethodService mContext;
         private boolean mEnabled = false;
-        private boolean mUsabilityStudy = false;
         private int mEnd = 0;
         /* package */ int mLength = 0;
         private char[] mCharBuf = new char[BUFSIZE];
@@ -129,7 +126,6 @@
                 boolean usabilityStudy) {
             sRingCharBuffer.mContext = context;
             sRingCharBuffer.mEnabled = enabled || usabilityStudy;
-            sRingCharBuffer.mUsabilityStudy = usabilityStudy;
             UsabilityStudyLogUtils.getInstance().init(context);
             return sRingCharBuffer;
         }
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index cabf680..555a49e 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -21,7 +21,6 @@
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardActionListener;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 
 /**
@@ -32,9 +31,9 @@
     public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE;
     public static final int NOT_A_COORDINATE = -1;
 
-    final static int N = BinaryDictionary.MAX_WORD_LENGTH;
+    private static final int N = BinaryDictionary.MAX_WORD_LENGTH;
 
-    private ArrayList<int[]> mCodes;
+    private int[] mPrimaryKeyCodes;
     private int[] mXCoordinates;
     private int[] mYCoordinates;
     private StringBuilder mTypedWord;
@@ -44,6 +43,7 @@
     private int mCapsCount;
     private boolean mAutoCapitalized;
     private int mTrailingSingleQuotesCount;
+    private int mCodePointSize;
 
     /**
      * Whether the user chose to capitalize the first char of the word.
@@ -51,12 +51,13 @@
     private boolean mIsFirstCharCapitalized;
 
     public WordComposer() {
-        mCodes = new ArrayList<int[]>(N);
+        mPrimaryKeyCodes = new int[N];
         mTypedWord = new StringBuilder(N);
         mXCoordinates = new int[N];
         mYCoordinates = new int[N];
         mAutoCorrection = null;
         mTrailingSingleQuotesCount = 0;
+        refreshSize();
     }
 
     public WordComposer(WordComposer source) {
@@ -64,7 +65,7 @@
     }
 
     public void init(WordComposer source) {
-        mCodes = new ArrayList<int[]>(source.mCodes);
+        mPrimaryKeyCodes = Arrays.copyOf(source.mPrimaryKeyCodes, source.mPrimaryKeyCodes.length);
         mTypedWord = new StringBuilder(source.mTypedWord);
         mXCoordinates = Arrays.copyOf(source.mXCoordinates, source.mXCoordinates.length);
         mYCoordinates = Arrays.copyOf(source.mYCoordinates, source.mYCoordinates.length);
@@ -72,18 +73,23 @@
         mIsFirstCharCapitalized = source.mIsFirstCharCapitalized;
         mAutoCapitalized = source.mAutoCapitalized;
         mTrailingSingleQuotesCount = source.mTrailingSingleQuotesCount;
+        refreshSize();
     }
 
     /**
      * Clear out the keys registered so far.
      */
     public void reset() {
-        mCodes.clear();
         mTypedWord.setLength(0);
         mAutoCorrection = null;
         mCapsCount = 0;
         mIsFirstCharCapitalized = false;
         mTrailingSingleQuotesCount = 0;
+        refreshSize();
+    }
+
+    public final void refreshSize() {
+        mCodePointSize = mTypedWord.codePointCount(0, mTypedWord.length());
     }
 
     /**
@@ -91,20 +97,19 @@
      * @return the number of keystrokes
      */
     public final int size() {
-        return mCodes.size();
+        return mCodePointSize;
     }
 
     public final boolean isComposingWord() {
-        return mCodes.size() > 0;
+        return size() > 0;
     }
 
-    /**
-     * Returns the codes at a particular position in the word.
-     * @param index the position in the word
-     * @return the unicode for the pressed and surrounding keys
-     */
-    public int[] getCodesAt(int index) {
-        return mCodes.get(index);
+    // TODO: make sure that the index should not exceed MAX_WORD_LENGTH
+    public int getCodeAt(int index) {
+        if (index >= BinaryDictionary.MAX_WORD_LENGTH) {
+            return -1;
+        }
+        return mPrimaryKeyCodes[index];
     }
 
     public int[] getXCoordinates() {
@@ -122,7 +127,6 @@
 
     // TODO: remove input keyDetector
     public void add(int primaryCode, int x, int y, KeyDetector keyDetector) {
-        final int[] codes;
         final int keyX;
         final int keyY;
         if (null == keyDetector
@@ -130,17 +134,13 @@
                 || y == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE
                 || x == KeyboardActionListener.NOT_A_TOUCH_COORDINATE
                 || y == KeyboardActionListener.NOT_A_TOUCH_COORDINATE) {
-            codes = new int[] { primaryCode };
             keyX = x;
             keyY = y;
         } else {
-            final Key key = keyDetector.detectHitKey(x, y);
-            // TODO: Pass an integer instead of an integer array
-            codes = new int[] { key != null ? key.mCode : NOT_A_CODE };
             keyX = keyDetector.getTouchX(x);
             keyY = keyDetector.getTouchY(y);
         }
-        add(primaryCode, codes, keyX, keyY);
+        add(primaryCode, keyX, keyY);
     }
 
     /**
@@ -148,11 +148,13 @@
      * the array containing unicode for adjacent keys, sorted by reducing probability/proximity.
      * @param codes the array of unicode values
      */
-    private void add(int primaryCode, int[] codes, int keyX, int keyY) {
-        final int newIndex = mCodes.size();
+    private void add(int primaryCode, int keyX, int keyY) {
+        final int newIndex = size();
         mTypedWord.appendCodePoint(primaryCode);
-        mCodes.add(codes);
+        refreshSize();
         if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) {
+            mPrimaryKeyCodes[newIndex] = primaryCode >= Keyboard.CODE_SPACE
+                    ? Character.toLowerCase(primaryCode) : primaryCode;
             mXCoordinates[newIndex] = keyX;
             mYCoordinates[newIndex] = keyY;
         }
@@ -175,13 +177,11 @@
             if (key.mCode == codePoint) {
                 final int x = key.mX + key.mWidth / 2;
                 final int y = key.mY + key.mHeight / 2;
-                // TODO: Pass an integer instead of an integer array
-                add(codePoint, new int[] { key.mCode }, x, y);
+                add(codePoint, x, y);
                 return;
             }
         }
-        add(codePoint, new int[] { codePoint },
-                WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
+        add(codePoint, WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
     }
 
     /**
@@ -201,9 +201,8 @@
      * Delete the last keystroke as a result of hitting backspace.
      */
     public void deleteLast() {
-        final int size = mCodes.size();
+        final int size = size();
         if (size > 0) {
-            mCodes.remove(size - 1);
             // Note: mTypedWord.length() and mCodes.length differ when there are surrogate pairs
             final int stringBuilderLength = mTypedWord.length();
             if (stringBuilderLength < size) {
@@ -217,9 +216,10 @@
                 mTypedWord.deleteCharAt(stringBuilderLength - 1);
             }
             if (Character.isUpperCase(lastChar)) mCapsCount--;
+            refreshSize();
         }
         // We may have deleted the last one.
-        if (0 == mCodes.size()) {
+        if (0 == size()) {
             mIsFirstCharCapitalized = false;
         }
         if (mTrailingSingleQuotesCount > 0) {
@@ -307,29 +307,31 @@
         // Note: currently, we come here whenever we commit a word. If it's a MANUAL_PICK
         // or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate
         // the last composed word to ensure this does not happen.
-        final ArrayList<int[]> codes = mCodes;
+        final int[] primaryKeyCodes = mPrimaryKeyCodes;
         final int[] xCoordinates = mXCoordinates;
         final int[] yCoordinates = mYCoordinates;
-        mCodes = new ArrayList<int[]>(N);
+        mPrimaryKeyCodes = new int[N];
         mXCoordinates = new int[N];
         mYCoordinates = new int[N];
-        final LastComposedWord lastComposedWord = new LastComposedWord(codes,
+        final LastComposedWord lastComposedWord = new LastComposedWord(primaryKeyCodes,
                 xCoordinates, yCoordinates, mTypedWord.toString(), committedWord, separatorCode);
         if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD
                 && type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) {
             lastComposedWord.deactivate();
         }
         mTypedWord.setLength(0);
+        refreshSize();
         mAutoCorrection = null;
         return lastComposedWord;
     }
 
     public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) {
-        mCodes = lastComposedWord.mCodes;
+        mPrimaryKeyCodes = lastComposedWord.mPrimaryKeyCodes;
         mXCoordinates = lastComposedWord.mXCoordinates;
         mYCoordinates = lastComposedWord.mYCoordinates;
         mTypedWord.setLength(0);
         mTypedWord.append(lastComposedWord.mTypedWord);
+        refreshSize();
         mAutoCorrection = null; // This will be filled by the next call to updateSuggestion.
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/define/JniLibName.java b/java/src/com/android/inputmethod/latin/define/JniLibName.java
index 3e94a3c..e23e1a9 100644
--- a/java/src/com/android/inputmethod/latin/define/JniLibName.java
+++ b/java/src/com/android/inputmethod/latin/define/JniLibName.java
@@ -16,6 +16,10 @@
 
 package com.android.inputmethod.latin.define;
 
-public class JniLibName {
+public final class JniLibName {
+    private JniLibName() {
+        // This class is not publicly instantiable.
+    }
+
     public static final String JNI_LIB_NAME = "jni_latinime";
 }
diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
index cfb1d09..de20576 100644
--- a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
+++ b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
@@ -16,6 +16,10 @@
 
 package com.android.inputmethod.latin.define;
 
-public class ProductionFlag {
+public final class ProductionFlag {
+    private ProductionFlag() {
+        // This class is not publicly instantiable.
+    }
+
     public static final boolean IS_EXPERIMENTAL = false;
 }
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index f2878ee..20e44c2 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -45,8 +45,7 @@
 
 static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object,
         jstring sourceDir, jlong dictOffset, jlong dictSize,
-        jint typedLetterMultiplier, jint fullWordMultiplier, jint maxWordLength, jint maxWords,
-        jint maxAlternatives) {
+        jint typedLetterMultiplier, jint fullWordMultiplier, jint maxWordLength, jint maxWords) {
     PROF_OPEN;
     PROF_START(66);
     const char *sourceDirChars = env->GetStringUTFChars(sourceDir, 0);
@@ -119,7 +118,7 @@
 #endif // USE_MMAP_FOR_DICTIONARY
     } else {
         dictionary = new Dictionary(dictBuf, dictSize, fd, adjust, typedLetterMultiplier,
-                fullWordMultiplier, maxWordLength, maxWords, maxAlternatives);
+                fullWordMultiplier, maxWordLength, maxWords);
     }
     PROF_END(66);
     PROF_CLOSE;
@@ -155,8 +154,7 @@
 
 static int latinime_BinaryDictionary_getBigrams(JNIEnv *env, jobject object, jlong dict,
         jcharArray prevWordArray, jint prevWordLength, jintArray inputArray, jint inputArraySize,
-        jcharArray outputArray, jintArray frequencyArray, jint maxWordLength, jint maxBigrams,
-        jint maxAlternatives) {
+        jcharArray outputArray, jintArray frequencyArray, jint maxWordLength, jint maxBigrams) {
     Dictionary *dictionary = (Dictionary*)dict;
     if (!dictionary) return 0;
 
@@ -166,8 +164,7 @@
     int *frequencies = env->GetIntArrayElements(frequencyArray, 0);
 
     int count = dictionary->getBigrams((unsigned short*) prevWord, prevWordLength, inputCodes,
-            inputArraySize, (unsigned short*) outputChars, frequencies, maxWordLength, maxBigrams,
-            maxAlternatives);
+            inputArraySize, (unsigned short*) outputChars, frequencies, maxWordLength, maxBigrams);
 
     env->ReleaseCharArrayElements(prevWordArray, prevWord, JNI_ABORT);
     env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
@@ -242,11 +239,11 @@
 }
 
 static JNINativeMethod sMethods[] = {
-    {"openNative", "(Ljava/lang/String;JJIIIII)J", (void*)latinime_BinaryDictionary_open},
+    {"openNative", "(Ljava/lang/String;JJIIII)J", (void*)latinime_BinaryDictionary_open},
     {"closeNative", "(J)V", (void*)latinime_BinaryDictionary_close},
     {"getSuggestionsNative", "(JJ[I[I[III[C[I)I", (void*)latinime_BinaryDictionary_getSuggestions},
     {"isValidWordNative", "(J[CI)Z", (void*)latinime_BinaryDictionary_isValidWord},
-    {"getBigramsNative", "(J[CI[II[C[IIII)I", (void*)latinime_BinaryDictionary_getBigrams},
+    {"getBigramsNative", "(J[CI[II[C[III)I", (void*)latinime_BinaryDictionary_getBigrams},
     {"calcNormalizedScoreNative", "([CI[CII)D",
             (void*)latinime_BinaryDictionary_calcNormalizedScore},
     {"editDistanceNative", "([CI[CI)I", (void*)latinime_BinaryDictionary_editDistance}
diff --git a/native/src/bigram_dictionary.cpp b/native/src/bigram_dictionary.cpp
index 3704c47..f7a3d3e 100644
--- a/native/src/bigram_dictionary.cpp
+++ b/native/src/bigram_dictionary.cpp
@@ -26,10 +26,10 @@
 namespace latinime {
 
 BigramDictionary::BigramDictionary(const unsigned char *dict, int maxWordLength,
-        int maxAlternatives, const bool isLatestDictVersion, const bool hasBigram,
+        const bool isLatestDictVersion, const bool hasBigram,
         Dictionary *parentDictionary)
     : DICT(dict), MAX_WORD_LENGTH(maxWordLength),
-    MAX_ALTERNATIVES(maxAlternatives), IS_LATEST_DICT_VERSION(isLatestDictVersion),
+    IS_LATEST_DICT_VERSION(isLatestDictVersion),
     HAS_BIGRAM(hasBigram), mParentDictionary(parentDictionary) {
     if (DEBUG_DICT) {
         AKLOGI("BigramDictionary - constructor");
@@ -92,7 +92,6 @@
  * bigramFreq: an array to output frequencies.
  * maxWordLength: the maximum size of a word.
  * maxBigrams: the maximum number of bigrams fitting in the bigramChars array.
- * maxAlteratives: unused.
  * This method returns the number of bigrams this word has, for backward compatibility.
  * Note: this is not the number of bigrams output in the array, which is the number of
  * bigrams this word has WHOSE first letter also matches the letter the user typed.
@@ -103,7 +102,7 @@
  */
 int BigramDictionary::getBigrams(unsigned short *prevWord, int prevWordLength, int *codes,
         int codesSize, unsigned short *bigramChars, int *bigramFreq, int maxWordLength,
-        int maxBigrams, int maxAlternatives) {
+        int maxBigrams) {
     // TODO: remove unused arguments, and refrain from storing stuff in members of this class
     // TODO: have "in" arguments before "out" ones, and make out args explicit in the name
     mBigramFreq = bigramFreq;
diff --git a/native/src/bigram_dictionary.h b/native/src/bigram_dictionary.h
index 585a186..8132fbc 100644
--- a/native/src/bigram_dictionary.h
+++ b/native/src/bigram_dictionary.h
@@ -22,11 +22,10 @@
 class Dictionary;
 class BigramDictionary {
  public:
-    BigramDictionary(const unsigned char *dict, int maxWordLength, int maxAlternatives,
+    BigramDictionary(const unsigned char *dict, int maxWordLength,
             const bool isLatestDictVersion, const bool hasBigram, Dictionary *parentDictionary);
     int getBigrams(unsigned short *word, int length, int *codes, int codesSize,
-            unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams,
-            int maxAlternatives);
+            unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams);
     ~BigramDictionary();
  private:
     bool addWordBigram(unsigned short *word, int length, int frequency);
@@ -39,7 +38,8 @@
 
     const unsigned char *DICT;
     const int MAX_WORD_LENGTH;
-    const int MAX_ALTERNATIVES;
+    // TODO: Re-implement proximity correction for bigram correction
+    static const int MAX_ALTERNATIVES = 1;
     const bool IS_LATEST_DICT_VERSION;
     const bool HAS_BIGRAM;
 
diff --git a/native/src/dictionary.cpp b/native/src/dictionary.cpp
index 8e252f7..981a983 100644
--- a/native/src/dictionary.cpp
+++ b/native/src/dictionary.cpp
@@ -27,7 +27,7 @@
 // TODO: Change the type of all keyCodes to uint32_t
 Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust,
         int typedLetterMultiplier, int fullWordMultiplier,
-        int maxWordLength, int maxWords, int maxAlternatives)
+        int maxWordLength, int maxWords)
     : mDict((unsigned char*) dict), mDictSize(dictSize),
     mMmapFd(mmapFd), mDictBufAdjust(dictBufAdjust),
     // Checks whether it has the latest dictionary or the old dictionary
@@ -44,8 +44,8 @@
             maxWords, SUB_QUEUE_MAX_WORDS, maxWordLength);
     const unsigned int headerSize = BinaryFormat::getHeaderSize(mDict);
     mUnigramDictionary = new UnigramDictionary(mDict + headerSize, typedLetterMultiplier,
-            fullWordMultiplier, maxWordLength, maxWords, maxAlternatives, IS_LATEST_DICT_VERSION);
-    mBigramDictionary = new BigramDictionary(mDict + headerSize, maxWordLength, maxAlternatives,
+            fullWordMultiplier, maxWordLength, maxWords, IS_LATEST_DICT_VERSION);
+    mBigramDictionary = new BigramDictionary(mDict + headerSize, maxWordLength,
             IS_LATEST_DICT_VERSION, true /* hasBigram */, this);
 }
 
diff --git a/native/src/dictionary.h b/native/src/dictionary.h
index 90d7148..139d3f0 100644
--- a/native/src/dictionary.h
+++ b/native/src/dictionary.h
@@ -30,7 +30,7 @@
 class Dictionary {
  public:
     Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultipler,
-            int fullWordMultiplier, int maxWordLength, int maxWords, int maxAlternatives);
+            int fullWordMultiplier, int maxWordLength, int maxWords);
 
     int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates,
             int *codes, int codesSize, int flags, unsigned short *outWords, int *frequencies) {
@@ -41,10 +41,9 @@
 
     // TODO: Call mBigramDictionary instead of mUnigramDictionary
     int getBigrams(unsigned short *word, int length, int *codes, int codesSize,
-            unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams,
-            int maxAlternatives) {
+            unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams) {
         return mBigramDictionary->getBigrams(word, length, codes, codesSize, outWords, frequencies,
-                maxWordLength, maxBigrams, maxAlternatives);
+                maxWordLength, maxBigrams);
     }
 
     bool isValidWord(unsigned short *word, int length);
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index d21413d..ed4c066 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -40,7 +40,7 @@
 
 // TODO: check the header
 UnigramDictionary::UnigramDictionary(const uint8_t* const streamStart, int typedLetterMultiplier,
-        int fullWordMultiplier, int maxWordLength, int maxWords, int maxProximityChars,
+        int fullWordMultiplier, int maxWordLength, int maxWords,
         const bool isLatestDictVersion)
     : DICT_ROOT(streamStart), MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords),
     IS_LATEST_DICT_VERSION(isLatestDictVersion),
diff --git a/native/src/unigram_dictionary.h b/native/src/unigram_dictionary.h
index 86bda77..c8f1556 100644
--- a/native/src/unigram_dictionary.h
+++ b/native/src/unigram_dictionary.h
@@ -74,7 +74,7 @@
     static const int MAX_ERRORS_FOR_TWO_WORDS = 1;
 
     UnigramDictionary(const uint8_t* const streamStart, int typedLetterMultipler,
-            int fullWordMultiplier, int maxWordLength, int maxWords, int maxProximityChars,
+            int fullWordMultiplier, int maxWordLength, int maxWords,
             const bool isLatestDictVersion);
     bool isValidWord(const uint16_t* const inWord, const int length) const;
     int getBigramPosition(int pos, unsigned short *word, int offset, int length) const;
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 2c63993..7d97eed 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -26,8 +26,8 @@
 import android.text.SpannableStringBuilder;
 import android.text.style.SuggestionSpan;
 import android.view.LayoutInflater;
-import android.view.ViewGroup;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.widget.FrameLayout;
@@ -37,9 +37,6 @@
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardActionListener;
 
-import java.util.Arrays;
-import java.util.HashMap;
-
 public class InputTestsBase extends ServiceTestCase<LatinIME> {
 
     private static final String PREF_DEBUG_MODE = "debug_mode";
@@ -192,8 +189,8 @@
             }
         }
         mLatinIME.onCodeInput(codePoint,
-                KeyboardActionListener.SPELL_CHECKER_COORDINATE,
-                KeyboardActionListener.SPELL_CHECKER_COORDINATE);
+                KeyboardActionListener.NOT_A_TOUCH_COORDINATE,
+                KeyboardActionListener.NOT_A_TOUCH_COORDINATE);
         //mLatinIME.onReleaseKey(codePoint, false);
     }
 
diff --git a/tests/src/com/android/inputmethod/latin/PunctuationTests.java b/tests/src/com/android/inputmethod/latin/PunctuationTests.java
index cc549bc..1b5b72f 100644
--- a/tests/src/com/android/inputmethod/latin/PunctuationTests.java
+++ b/tests/src/com/android/inputmethod/latin/PunctuationTests.java
@@ -16,8 +16,6 @@
 
 package com.android.inputmethod.latin;
 
-import com.android.inputmethod.keyboard.Keyboard;
-
 public class PunctuationTests extends InputTestsBase {
 
     public void testWordThenSpaceThenPunctuationFromStripTwice() {
diff --git a/tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java b/tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java
deleted file mode 100644
index 6ccc4f2..0000000
--- a/tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java
+++ /dev/null
@@ -1,156 +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.latin;
-
-import android.inputmethodservice.InputMethodService;
-import android.os.Handler;
-import android.util.Log;
-import android.view.MotionEvent;
-
-import com.android.inputmethod.latin.ResearchLogger.LogFileManager;
-
-import java.io.FileNotFoundException;
-
-public class ResearchLoggerTests extends InputTestsBase {
-
-    private static final String TAG = ResearchLoggerTests.class.getSimpleName();
-    private static final int TEST_INT = 0x12345678;
-    private static final long TEST_LONG = 0x1234567812345678L;
-
-    private static ResearchLogger sLogger;
-    private MockLogFileManager mMockLogFileManager;
-
-    @Override
-    protected void setUp() {
-        super.setUp();
-        sLogger = ResearchLogger.getInstance();
-        mMockLogFileManager = new MockLogFileManager();
-        sLogger.setLogFileManager(mMockLogFileManager);
-        ResearchLogger.sIsLogging = true;
-    }
-
-    public static class MockLogFileManager extends LogFileManager {
-        private final StringBuilder mContents = new StringBuilder();
-
-        @Override
-        public void init(InputMethodService ims) {
-        }
-
-        @Override
-        public synchronized void createLogFile() {
-            mContents.setLength(0);
-        }
-
-        @Override
-        public synchronized void createLogFile(String dir, String filename)
-                throws FileNotFoundException {
-            mContents.setLength(0);
-        }
-
-        @Override
-        public synchronized boolean append(String s) {
-            mContents.append(s);
-            return true;
-        }
-
-        @Override
-        public synchronized void reset() {
-            mContents.setLength(0);
-        }
-
-        @Override
-        public synchronized void close() {
-            mContents.setLength(0);
-        }
-
-        private String getAppendedString() {
-            return mContents.toString();
-        }
-    }
-
-    private void waitOnResearchLogger() {
-        // post another Runnable that notify()'s the test that it may proceed.
-        // assumes that the MessageQueue is processed in-order
-        Handler handler = sLogger.mLoggingHandler;
-        handler.post(new Runnable() {
-            @Override
-            public void run() {
-                synchronized (ResearchLoggerTests.this) {
-                    ResearchLoggerTests.this.notify();
-                }
-            }
-        });
-        synchronized (this) {
-            try {
-                wait();
-            } catch (InterruptedException e) {
-                Log.i(TAG, "interrupted when waiting for handler to finish.", e);
-            }
-        }
-    }
-
-    /*********************** Tests *********************/
-    public void testLogStartsEmpty() {
-        waitOnResearchLogger();
-        String result = mMockLogFileManager.getAppendedString();
-        assertEquals(result, "");
-    }
-
-    public void testMotionEvent() {
-        // verify that input values appear somewhere in output
-        sLogger.logMotionEvent(MotionEvent.ACTION_CANCEL,
-                TEST_LONG, TEST_INT, 1111, 3333, 5555, 7777);
-        waitOnResearchLogger();
-        String output = mMockLogFileManager.getAppendedString();
-        assertTrue(output.matches("(?sui).*\\bcancel\\b.*"));
-        assertFalse(output.matches("(?sui).*\\bdown\\b.*"));
-        assertTrue(output.matches("(?s).*\\b" + TEST_LONG + "\\b.*"));
-        assertTrue(output.matches("(?s).*\\b" + TEST_INT + "\\b.*"));
-        assertTrue(output.matches("(?s).*\\b1111\\b.*"));
-        assertTrue(output.matches("(?s).*\\b3333\\b.*"));
-        assertTrue(output.matches("(?s).*\\b5555\\b.*"));
-        assertTrue(output.matches("(?s).*\\b7777\\b.*"));
-    }
-
-    public void testKeyEvent() {
-        type("abc");
-        waitOnResearchLogger();
-        String output = mMockLogFileManager.getAppendedString();
-        assertTrue(output.matches("(?s).*\\ba\\b.*"));
-        assertTrue(output.matches("(?s).*\\bb\\b.*"));
-        assertTrue(output.matches("(?s).*\\bc\\b.*"));
-    }
-
-    public void testCorrection() {
-        sLogger.logCorrection("aaaa", "thos", "this", 1);
-        waitOnResearchLogger();
-        String output = mMockLogFileManager.getAppendedString();
-        assertTrue(output.matches("(?sui).*\\baaaa\\b.*"));
-        assertTrue(output.matches("(?sui).*\\bthos\\b.*"));
-        assertTrue(output.matches("(?sui).*\\bthis\\b.*"));
-    }
-
-    public void testStateChange() {
-        sLogger.logStateChange("aaaa", "bbbb");
-        waitOnResearchLogger();
-        String output = mMockLogFileManager.getAppendedString();
-        assertTrue(output.matches("(?sui).*\\baaaa\\b.*"));
-        assertTrue(output.matches("(?sui).*\\bbbbb\\b.*"));
-    }
-
-    // TODO: add integration tests that start at point of event generation.
-}