Merge "Add VERSION4_TEST for testing."
diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml
index ed387e5..ff0b403 100644
--- a/java/res/layout/input_view.xml
+++ b/java/res/layout/input_view.xml
@@ -43,8 +43,6 @@
             android:layout_width="match_parent"
             android:layout_height="@dimen/config_suggestions_strip_height"
             android:gravity="center_vertical"
-            android:paddingRight="@dimen/config_suggestions_strip_horizontal_padding"
-            android:paddingLeft="@dimen/config_suggestions_strip_horizontal_padding"
             style="?attr/suggestionStripViewStyle" />
 
         <!-- To ensure that key preview popup is correctly placed when the current system locale is
diff --git a/java/res/layout/suggestions_strip.xml b/java/res/layout/suggestions_strip.xml
index 0b61499..bff9a1e 100644
--- a/java/res/layout/suggestions_strip.xml
+++ b/java/res/layout/suggestions_strip.xml
@@ -24,12 +24,16 @@
         android:id="@+id/suggestions_strip"
         android:orientation="horizontal"
         android:layout_width="match_parent"
-        android:layout_height="match_parent" />
+        android:layout_height="match_parent"
+        android:layout_marginLeft="@dimen/config_suggestions_strip_horizontal_margin"
+        android:layout_marginRight="@dimen/config_suggestions_strip_horizontal_margin" />
     <LinearLayout
         android:id="@+id/add_to_dictionary_strip"
         android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
+        android:layout_marginLeft="@dimen/config_suggestions_strip_horizontal_margin"
+        android:layout_marginRight="@dimen/config_suggestions_strip_horizontal_margin"
         android:visibility="invisible">
         <TextView
             android:id="@+id/word_to_save"
@@ -49,7 +53,9 @@
         android:id="@+id/important_notice_strip"
         android:orientation="horizontal"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        android:layout_height="match_parent"
+        android:layout_marginLeft="@dimen/config_suggestions_strip_horizontal_margin"
+        android:layout_marginRight="@dimen/config_suggestions_strip_horizontal_margin">
         <TextView
             android:id="@+id/important_notice_title"
             android:layout_width="match_parent"
diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml
index 4d7de93..519aa44 100644
--- a/java/res/values-km-rKH/strings.xml
+++ b/java/res/values-km-rKH/strings.xml
@@ -29,7 +29,7 @@
     <string name="popup_on_keypress" msgid="123894815723512944">"លេច​ឡើង​នៅ​​ពេល​ចុច​គ្រាប់​ចុច"</string>
     <string name="general_category" msgid="1859088467017573195">"ទូទៅ"</string>
     <string name="correction_category" msgid="2236750915056607613">"ការ​កែ​អត្ថបទ"</string>
-    <string name="gesture_typing_category" msgid="497263612130532630">"បញ្ចូល​ដោយ​ប្រើ​កាយវិការ​"</string>
+    <string name="gesture_typing_category" msgid="497263612130532630">"បញ្ចូល​ដោយ​ប្រើ​កាយវិការ"</string>
     <string name="misc_category" msgid="6894192814868233453">"ជម្រើស​ផ្សេងទៀត"</string>
     <string name="advanced_settings" msgid="362895144495591463">"ការ​កំណត់​កម្រិត​ខ្ពស់"</string>
     <string name="advanced_settings_summary" msgid="4487980456152830271">"ជម្រើស​សម្រាប់​អ្នក​ជំនាញ"</string>
@@ -39,7 +39,7 @@
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"បង្ហាញ​នៅ​ពេល​ដែល​បើក​ភាសា​បញ្ចូល​ច្រើន"</string>
     <string name="sliding_key_input_preview" msgid="6604262359510068370">"បង្ហាញ​ទ្រនិច​បង្ហាញ​ស្លាយ"</string>
     <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"បង្ហាញ​​សញ្ញា​មើល​​ឃើញ​ខណៈ​ពេល​ដែល​រុញ​ពី​ឆ្វេង ឬ​​គ្រាប់​ចុច​​និមិត្ត​សញ្ញា"</string>
-    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"​សោ​លេចឡើង​បោះបង់​ការ​​ពន្យារពេល​"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"​សោ​លេចឡើង​បោះបង់​ការ​​ពន្យារពេល"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"គ្មាន​ការ​ពន្យារពេល"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"លំនាំដើម"</string>
     <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> មិល្លី​វិនាទី"</string>
@@ -49,7 +49,7 @@
     <string name="use_personalized_dicts" msgid="5167396352105467626">"ការ​ស្នើ​ផ្ទាល់​ខ្លួន"</string>
     <string name="use_double_space_period" msgid="8781529969425082860">"រយៈ​ពេល​ចុច​ដកឃ្លា​ពីរដង"</string>
     <string name="use_double_space_period_summary" msgid="6532892187247952799">"ប៉ះ​ដកឃ្លា​ពីរ​​ដង​បញ្ចូល​​​រយៈ​ពេល​ដែល​អនុវត្ត​តាម​ដកឃ្លា"</string>
-    <string name="auto_cap" msgid="1719746674854628252">"ការ​សរសេរ​ជា​អក្សរ​ធំ​​ស្វ័យប្រវត្តិ​"</string>
+    <string name="auto_cap" msgid="1719746674854628252">"ការ​សរសេរ​ជា​អក្សរ​ធំ​​ស្វ័យប្រវត្តិ"</string>
     <string name="auto_cap_summary" msgid="7934452761022946874">"សរសេរ​ពាក្យ​ដំបូង​​​ជា​អក្សរ​ធំ​​នៃ​ប្រយោគ​នីមួយ​ៗ"</string>
     <string name="edit_personal_dictionary" msgid="3996910038952940420">"វចនានុក្រម​ផ្ទាល់ខ្លួន"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"ផ្នែក​បន្ថែម​វចនានុក្រម"</string>
@@ -60,7 +60,7 @@
     <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"បង្ហាញ​នៅ​ក្នុង​របៀប​បញ្ឈរ"</string>
     <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"លាក់​ជានិច្ច"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"ទប់ស្កាត់​​ពាក្យ​​បំពាន"</string>
-    <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"កុំ​ស្នើ​ឲ្យ​ពាក្យ​បំពាន​មាន​សក្ដានុពល​"</string>
+    <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"កុំ​ស្នើ​ឲ្យ​ពាក្យ​បំពាន​មាន​សក្ដានុពល"</string>
     <string name="auto_correction" msgid="7630720885194996950">"ការ​កែ​​​ស្វ័យប្រវត្តិ"</string>
     <string name="auto_correction_summary" msgid="5625751551134658006">"ចន្លោះ​មិន​ឃើញ ​និង​សញ្ញា​​វណ្ណយុត្ត​កែ​ពាក្យ​ដែល​បាន​វាយ​ខុស​ស្វ័យប្រវត្តិ"</string>
     <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"បិទ"</string>
@@ -123,7 +123,7 @@
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"ថិរវេលា​​ញ័រ​​ពេល​ចុច​គ្រាប់ចុច"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"កម្រិត​សំឡេង​ពេល​ចុច​គ្រាប់​ចុច"</string>
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"អាន​ឯកសារ​វចនានុក្រម​ខាង​ក្រៅ"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"គ្មាន​ឯកសារ​វចនានុក្រម​នៅ​ក្នុង​ថត​ទាញ​យក​​"</string>
+    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"គ្មាន​ឯកសារ​វចនានុក្រម​នៅ​ក្នុង​ថត​ទាញ​យក"</string>
     <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"ជ្រើស​ឯកសារ​វចនានុក្រម​ ដើម្បី​ដំឡើង"</string>
     <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"ពិត​ជា​ដំឡើង​ឯកសារ​នេះ​សម្រាប់ <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
     <string name="error" msgid="8940763624668513648">"មាន​កំហុស"</string>
@@ -154,7 +154,7 @@
     <string name="dictionary_provider_name" msgid="3027315045397363079">"កម្មវិធី​ផ្ដល់​វចនានុក្រម"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"សេវាកម្ម​​វចនានុក្រម"</string>
     <string name="download_description" msgid="6014835283119198591">"ព័ត៌មាន​បច្ចុប្បន្នភាព​វចនានុក្រម"</string>
-    <string name="dictionary_settings_title" msgid="8091417676045693313">"ផ្នែក​បន្ថែម​វចនានុក្រម​​"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"ផ្នែក​បន្ថែម​វចនានុក្រម"</string>
     <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"វចនានុក្រម​​​​​អាច​ប្រើ​បាន"</string>
     <string name="dictionary_settings_summary" msgid="5305694987799824349">"ការ​កំណត់​សម្រាប់​វចនានុក្រម"</string>
     <string name="user_dictionaries" msgid="3582332055892252845">"វចនានុក្រម​​​អ្នក​ប្រើ"</string>
@@ -170,10 +170,10 @@
     <string name="message_updating" msgid="4457761393932375219">"ពិនិត្យមើល​បច្ចុប្បន្នភាព"</string>
     <string name="message_loading" msgid="5638680861387748936">"កំពុង​ផ្ទុក..."</string>
     <string name="main_dict_description" msgid="3072821352793492143">"វចនានុក្រម​ចម្បង"</string>
-    <string name="cancel" msgid="6830980399865683324">"បោះ​បង់​"</string>
+    <string name="cancel" msgid="6830980399865683324">"បោះ​បង់"</string>
     <string name="go_to_settings" msgid="3876892339342569259">"ការ​កំណត់"</string>
     <string name="install_dict" msgid="180852772562189365">"ដំឡើង"</string>
-    <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់​"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់"</string>
     <string name="delete_dict" msgid="756853268088330054">"លុប"</string>
     <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"ភាសា​ដែល​បាន​ជ្រើស​នៅ​លើ​ឧបករណ៍​ចល័ត​មាន​វចនានុក្រម​អាច​ប្រើ​បាន។&lt;br/&gt; យើង​ផ្ដល់​អនុសាសន៍​ឲ្យ &lt;b&gt;ទាញ​យក&lt;/b&gt; វចនានុក្រម​ភាសា <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> ដើម្បី​បង្កើន​បទពិសោធន៍​វាយ​បញ្ចូល​របស់​អ្នក។&lt;br/&gt; &lt;br/&gt; ការ​ទាញ​យក​អាច​ចំណាយ​ពេល​ប្រហែល​ពីរ​នាទី​នៅ​តាម 3G។ ការ​គិត​ថ្លៃ​អាច​អនុវត្ត​ប្រសិន​បើ​អ្នក​មិន​ប្រើ &lt;b&gt;ផែនការ​ទិន្នន័យ​គ្មាន​ដែន​កំណត់&lt;/b&gt;.&lt;br/&gt; បើ​អ្នក​មិន​ប្រាកដ​​ថា​ផែនការ​ណា​មួយ​ដែល​អ្នក​មាន យើង​ផ្ដល់​អនុសាសន៍​ឲ្យ​​ភ្ជាប់​វ៉ាយហ្វាយ ដើម្បី​ចាប់ផ្ដើម​ទាញ​យក​ដោយ​ស្វ័យ​ប្រវត្តិ។&lt;br/&gt; &lt;br/&gt; ជំនួយ៖ អ្នក​អាច​ទាញ​យក និង​លុប​វចនានុក្រម​ដោយ​ចូល​ទៅ​ &lt;b&gt;ភាសា &amp; ការ​បញ្ចូល&lt;/b&gt; នៅ​ក្នុង​ម៉ឺនុយ &lt;b&gt;ការ​កំណត់&lt;/b&gt; សម្រាប់​ឧបករណ៍​ចល័ត។"</string>
     <string name="download_over_metered" msgid="1643065851159409546">"ទាញ​យក​ឥឡូវ​នេះ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> មេកាបៃ)"</string>
@@ -191,7 +191,7 @@
     <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"ពាក្យ៖"</string>
     <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"ផ្លូវកាត់​៖"</string>
     <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"ភាសា៖"</string>
-    <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"វាយ​បញ្ចូល​ពាក្យ​"</string>
+    <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"វាយ​បញ្ចូល​ពាក្យ"</string>
     <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"ផ្លូវកាត់​ជា​ជម្រើស"</string>
     <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"កែ​ពាក្យ"</string>
     <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"កែ"</string>
diff --git a/java/res/values-land/config.xml b/java/res/values-land/config.xml
index 43ae068..f72d64f 100644
--- a/java/res/values-land/config.xml
+++ b/java/res/values-land/config.xml
@@ -58,6 +58,7 @@
     <fraction name="config_key_shifted_letter_hint_ratio_5row">48%</fraction>
 
     <dimen name="config_suggestions_strip_height">36dp</dimen>
+    <dimen name="config_suggestions_strip_horizontal_margin">54dp</dimen>
     <dimen name="config_more_suggestions_row_height">36dp</dimen>
     <integer name="config_max_more_suggestions_row">2</integer>
     <fraction name="config_min_more_suggestions_width">60%</fraction>
diff --git a/java/res/values-sw600dp-land/config.xml b/java/res/values-sw600dp-land/config.xml
index 00edde1..8789e72 100644
--- a/java/res/values-sw600dp-land/config.xml
+++ b/java/res/values-sw600dp-land/config.xml
@@ -48,7 +48,8 @@
     <fraction name="config_key_letter_ratio_5row">62%</fraction>
     <fraction name="config_key_shifted_letter_hint_ratio_5row">36%</fraction>
 
-    <dimen name="config_suggestions_strip_horizontal_padding">252.0dp</dimen>
+    <dimen name="config_suggestions_strip_height">44dp</dimen>
+    <dimen name="config_suggestions_strip_horizontal_margin">180.0dp</dimen>
     <integer name="config_max_more_suggestions_row">5</integer>
     <fraction name="config_min_more_suggestions_width">50%</fraction>
 
diff --git a/java/res/values-sw600dp/config.xml b/java/res/values-sw600dp/config.xml
index 3bd8439..12e9832 100644
--- a/java/res/values-sw600dp/config.xml
+++ b/java/res/values-sw600dp/config.xml
@@ -63,12 +63,12 @@
     <fraction name="config_key_shifted_letter_hint_ratio_5row">27%</fraction>
 
     <dimen name="config_suggestions_strip_height">44dp</dimen>
+    <dimen name="config_suggestions_strip_horizontal_margin">0dp</dimen>
     <dimen name="config_more_suggestions_row_height">44dp</dimen>
     <integer name="config_max_more_suggestions_row">6</integer>
     <fraction name="config_min_more_suggestions_width">90%</fraction>
-    <dimen name="config_suggestions_strip_horizontal_padding">94.5dp</dimen>
     <dimen name="config_suggestion_min_width">48.0dp</dimen>
-    <dimen name="config_suggestion_text_horizontal_padding">12dp</dimen>
+    <dimen name="config_suggestion_text_horizontal_padding">10dp</dimen>
     <dimen name="config_suggestion_text_size">22dp</dimen>
     <dimen name="config_more_suggestions_hint_text_size">33dp</dimen>
 
diff --git a/java/res/values-sw768dp-land/config.xml b/java/res/values-sw768dp-land/config.xml
index 3878a9e..17733f0 100644
--- a/java/res/values-sw768dp-land/config.xml
+++ b/java/res/values-sw768dp-land/config.xml
@@ -49,7 +49,8 @@
     <fraction name="config_key_letter_ratio_5row">53%</fraction>
     <fraction name="config_key_shifted_letter_hint_ratio_5row">30%</fraction>
 
-    <dimen name="config_suggestions_strip_horizontal_padding">252.0dp</dimen>
+    <dimen name="config_suggestions_strip_height">44dp</dimen>
+    <dimen name="config_suggestions_strip_horizontal_margin">340dp</dimen>
     <fraction name="config_min_more_suggestions_width">50%</fraction>
 
     <!-- Gesture floating preview text parameters -->
diff --git a/java/res/values-sw768dp/config.xml b/java/res/values-sw768dp/config.xml
index 34eec38..647cca9 100644
--- a/java/res/values-sw768dp/config.xml
+++ b/java/res/values-sw768dp/config.xml
@@ -61,12 +61,12 @@
     <fraction name="config_key_shifted_letter_hint_ratio_5row">33%</fraction>
 
     <dimen name="config_suggestions_strip_height">44dp</dimen>
+    <dimen name="config_suggestions_strip_horizontal_margin">100dp</dimen>
     <dimen name="config_more_suggestions_row_height">44dp</dimen>
     <integer name="config_max_more_suggestions_row">6</integer>
     <fraction name="config_min_more_suggestions_width">90%</fraction>
-    <dimen name="config_suggestions_strip_horizontal_padding">94.5dp</dimen>
     <dimen name="config_suggestion_min_width">46dp</dimen>
-    <dimen name="config_suggestion_text_horizontal_padding">8dp</dimen>
+    <dimen name="config_suggestion_text_horizontal_padding">10dp</dimen>
     <dimen name="config_suggestion_text_size">22dp</dimen>
     <dimen name="config_more_suggestions_hint_text_size">33dp</dimen>
 
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 45ea483..1ab4927 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -64,10 +64,10 @@
     <fraction name="config_key_shifted_letter_hint_ratio_5row">41%</fraction>
 
     <dimen name="config_suggestions_strip_height">40dp</dimen>
+    <dimen name="config_suggestions_strip_horizontal_margin">0dp</dimen>
     <dimen name="config_more_suggestions_row_height">40dp</dimen>
     <integer name="config_max_more_suggestions_row">6</integer>
     <fraction name="config_min_more_suggestions_width">90%</fraction>
-    <dimen name="config_suggestions_strip_horizontal_padding">0dp</dimen>
     <dimen name="config_suggestion_min_width">44dp</dimen>
     <dimen name="config_suggestion_text_horizontal_padding">6dp</dimen>
     <dimen name="config_suggestion_text_size">18dp</dimen>
diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml
index eb6cdd9..76abb10 100644
--- a/java/res/values/themes-common.xml
+++ b/java/res/values/themes-common.xml
@@ -120,12 +120,7 @@
         name="MoreKeysKeyboardView"
         parent="MainKeyboardView" />
     <style name="MoreKeysKeyboardContainer" />
-    <style name="SuggestionStripView">
-        <item name="suggestionsCountInStrip">@integer/config_suggestions_count_in_strip</item>
-        <item name="centerSuggestionPercentile">@fraction/config_center_suggestion_percentile</item>
-        <item name="maxMoreSuggestionsRow">@integer/config_max_more_suggestions_row</item>
-        <item name="minMoreSuggestionsWidth">@fraction/config_min_more_suggestions_width</item>
-    </style>
+    <style name="SuggestionStripView" />
     <style name="SuggestionWord">
         <item name="android:minWidth">@dimen/config_suggestion_min_width</item>
         <item name="android:textSize">@dimen/config_suggestion_text_size</item>
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index 720eda9..616dbd8 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -109,8 +109,12 @@
     </style>
     <style
         name="SuggestionStripView.ICS"
-        parent="SuggestionStripView"
+        parent="KeyboardView.ICS"
     >
+        <item name="suggestionsCountInStrip">@integer/config_suggestions_count_in_strip</item>
+        <item name="centerSuggestionPercentile">@fraction/config_center_suggestion_percentile</item>
+        <item name="maxMoreSuggestionsRow">@integer/config_max_more_suggestions_row</item>
+        <item name="minMoreSuggestionsWidth">@fraction/config_min_more_suggestions_width</item>
         <item name="android:background">@drawable/keyboard_suggest_strip_holo</item>
         <item name="suggestionStripOptions">autoCorrectBold|validTypedWordBold</item>
         <item name="colorValidTypedWord">@color/typed_word_color_ics</item>
diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml
index 8305271..9bb3d79 100644
--- a/java/res/values/themes-klp.xml
+++ b/java/res/values/themes-klp.xml
@@ -109,8 +109,12 @@
     </style>
     <style
         name="SuggestionStripView.KLP"
-        parent="SuggestionStripView"
+        parent="KeyboardView.KLP"
     >
+        <item name="suggestionsCountInStrip">@integer/config_suggestions_count_in_strip</item>
+        <item name="centerSuggestionPercentile">@fraction/config_center_suggestion_percentile</item>
+        <item name="maxMoreSuggestionsRow">@integer/config_max_more_suggestions_row</item>
+        <item name="minMoreSuggestionsWidth">@fraction/config_min_more_suggestions_width</item>
         <item name="android:background">@drawable/keyboard_suggest_strip_holo</item>
         <item name="suggestionStripOptions">autoCorrectBold|validTypedWordBold</item>
         <item name="colorValidTypedWord">@color/typed_word_color_klp</item>
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
index 0f9645e..7e6181a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
@@ -1067,33 +1067,33 @@
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
         /* morekeys_a */ "\u00E0,\u00E1,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101",
+        // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
         // 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
-        /* morekeys_o */ "\u00F4,\u00F6,\u00F2,\u00F3,\u0153,\u00F8,\u014D,\u00F5",
+        /* morekeys_o */ "\u00F3,\u00F4,\u00F6,\u00F2,\u0153,\u00F8,\u014D,\u00F5",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // 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
-        /* morekeys_u */ "\u00FB,\u00FC,\u00F9,\u00FA,\u016B",
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        /* morekeys_u */ "\u00FA,\u00FB,\u00FC,\u00F9,\u016B",
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
         // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        /* morekeys_e */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0113",
+        /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0113",
+        // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // 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
-        /* morekeys_i */ "\u00EE,\u00EF,\u00ED,\u012B,\u00EC",
+        /* morekeys_i */ "\u00ED,\u00EE,\u00EF,\u012B,\u00EC",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* morekeys_c */ "\u00E7",
         /* double_quotes */ null,
@@ -3588,33 +3588,33 @@
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
         /* morekeys_a */ "\u00E0,\u00E1,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101",
+        // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
         // 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
-        /* morekeys_o */ "\u00F4,\u00F6,\u00F2,\u00F3,\u0153,\u00F8,\u014D,\u00F5",
+        /* morekeys_o */ "\u00F3,\u00F4,\u00F6,\u00F2,\u0153,\u00F8,\u014D,\u00F5",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // 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
-        /* morekeys_u */ "\u00FB,\u00FC,\u00F9,\u00FA,\u016B",
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        /* morekeys_u */ "\u00FA,\u00FB,\u00FC,\u00F9,\u016B",
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
         // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        /* morekeys_e */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0113",
+        /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0113",
+        // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // 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
-        /* morekeys_i */ "\u00EE,\u00EF,\u00ED,\u012B,\u00EC",
+        /* morekeys_i */ "\u00ED,\u00EE,\u00EF,\u012B,\u00EC",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* morekeys_c */ "\u00E7",
         /* double_quotes */ null,
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 7ab9088..94a1e36 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -373,8 +373,7 @@
         return getProbabilityNative(mNativeDict, codePoints);
     }
 
-    // TODO: Add a batch process version (isValidBigramMultiple?) to avoid excessive numbers of jni
-    // calls when checking for changes in an entire dictionary.
+    @UsedForTesting
     public boolean isValidBigram(final String word0, final String word1) {
         return getBigramProbability(word0, word1) != NOT_A_PROBABILITY;
     }
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 9bc01a2..e04fcda 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -31,9 +31,12 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.personalization.AccountUtils;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+import com.android.inputmethod.latin.utils.ExecutorUtils;
 import com.android.inputmethod.latin.utils.StringUtils;
 
 import java.io.File;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 
@@ -60,7 +63,10 @@
     private static final int INDEX_NAME = 1;
 
     /** The number of contacts in the most recent dictionary rebuild. */
-    static private int sContactCountAtLastRebuild = 0;
+    private int mContactCountAtLastRebuild = 0;
+
+    /** The hash code of ArrayList of contacts names in the most recent dictionary rebuild. */
+    private int mHashCodeAtLastRebuild = 0;
 
     private ContentObserver mObserver;
 
@@ -96,7 +102,14 @@
                 new ContentObserver(null) {
                     @Override
                     public void onChange(boolean self) {
-                        setNeedsToReload();
+                        ExecutorUtils.getExecutor("Check Contacts").execute(new Runnable() {
+                            @Override
+                            public void run() {
+                                if (haveContentsChanged()) {
+                                    setNeedsToRecreate();
+                                }
+                            }
+                        });
                     }
                 });
     }
@@ -143,7 +156,7 @@
                 return;
             }
             if (cursor.moveToFirst()) {
-                sContactCountAtLastRebuild = getContactCount();
+                mContactCountAtLastRebuild = getContactCount();
                 addWordsLocked(cursor);
             }
         } catch (final SQLiteException e) {
@@ -167,9 +180,11 @@
 
     private void addWordsLocked(final Cursor cursor) {
         int count = 0;
+        final ArrayList<String> names = CollectionUtils.newArrayList();
         while (!cursor.isAfterLast() && count < MAX_CONTACT_COUNT) {
             String name = cursor.getString(INDEX_NAME);
             if (isValidName(name)) {
+                names.add(name);
                 addNameLocked(name);
                 ++count;
             } else {
@@ -179,6 +194,7 @@
             }
             cursor.moveToNext();
         }
+        mHashCodeAtLastRebuild = names.hashCode();
     }
 
     private int getContactCount() {
@@ -258,8 +274,7 @@
         return end;
     }
 
-    @Override
-    protected boolean haveContentsChanged() {
+    private boolean haveContentsChanged() {
         final long startTime = SystemClock.uptimeMillis();
         final int contactCount = getContactCount();
         if (contactCount > MAX_CONTACT_COUNT) {
@@ -268,9 +283,9 @@
             // TODO: Sort and check only the MAX_CONTACT_COUNT most recent contacts?
             return false;
         }
-        if (contactCount != sContactCountAtLastRebuild) {
+        if (contactCount != mContactCountAtLastRebuild) {
             if (DEBUG) {
-                Log.d(TAG, "Contact count changed: " + sContactCountAtLastRebuild + " to "
+                Log.d(TAG, "Contact count changed: " + mContactCountAtLastRebuild + " to "
                         + contactCount);
             }
             return true;
@@ -283,20 +298,20 @@
         if (null == cursor) {
             return false;
         }
+        final ArrayList<String> names = CollectionUtils.newArrayList();
         try {
             if (cursor.moveToFirst()) {
                 while (!cursor.isAfterLast()) {
                     String name = cursor.getString(INDEX_NAME);
-                    if (isValidName(name) && !isNameInDictionaryLocked(name)) {
-                        if (DEBUG) {
-                            Log.d(TAG, "Contact name missing: " + name + " (runtime = "
-                                    + (SystemClock.uptimeMillis() - startTime) + " ms)");
-                        }
-                        return true;
+                    if (isValidName(name)) {
+                        names.add(name);
                     }
                     cursor.moveToNext();
                 }
             }
+            if (names.hashCode() != mHashCodeAtLastRebuild) {
+                return true;
+            }
         } finally {
             cursor.close();
         }
@@ -313,33 +328,4 @@
         }
         return false;
     }
-
-    /**
-     * Checks if the words in a name are in the current binary dictionary.
-     */
-    private boolean isNameInDictionaryLocked(final String name) {
-        int len = StringUtils.codePointCount(name);
-        String prevWord = null;
-        for (int i = 0; i < len; i++) {
-            if (Character.isLetter(name.codePointAt(i))) {
-                int end = getWordEndPosition(name, len, i);
-                String word = name.substring(i, end);
-                i = end - 1;
-                final int wordLen = StringUtils.codePointCount(word);
-                if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
-                    if (!TextUtils.isEmpty(prevWord) && mUseFirstLastBigrams) {
-                        if (!isValidBigramLocked(prevWord, word)) {
-                            return false;
-                        }
-                    } else {
-                        if (!isValidWordLocked(word)) {
-                            return false;
-                        }
-                    }
-                    prevWord = word;
-                }
-            }
-        }
-        return true;
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index 627793f..9735645 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -234,6 +234,7 @@
         synchronized (mLock) {
             oldDictionaries = mDictionaries;
             mDictionaries = newDictionaries;
+            mIsUserDictEnabled = UserBinaryDictionary.isEnabled(context);
             if (reloadMainDictionary) {
                 asyncReloadMainDictionary(context, newLocale, listener);
             }
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 2aa9ca3..6818c15 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -92,8 +92,8 @@
     /** Indicates whether a task for reloading the dictionary has been scheduled. */
     private final AtomicBoolean mIsReloading;
 
-    /** Indicates whether the current dictionary needs to be reloaded. */
-    private boolean mNeedsToReload;
+    /** Indicates whether the current dictionary needs to be recreated. */
+    private boolean mNeedsToRecreate;
 
     private final ReentrantReadWriteLock mLock;
 
@@ -107,13 +107,6 @@
      */
     protected abstract void loadInitialContentsLocked();
 
-    /**
-     * Indicates that the source dictionary contents have changed and a rebuild of the binary file
-     * is required. If it returns false, the next reload will only read the current binary
-     * dictionary from file.
-     */
-    protected abstract boolean haveContentsChanged();
-
     private boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) {
         return formatVersion == FormatSpec.VERSION4;
     }
@@ -148,7 +141,7 @@
         mDictFile = getDictFile(context, dictName, dictFile);
         mBinaryDictionary = null;
         mIsReloading = new AtomicBoolean();
-        mNeedsToReload = false;
+        mNeedsToRecreate = false;
         mLock = new ReentrantReadWriteLock();
     }
 
@@ -490,11 +483,11 @@
     }
 
     /**
-     * Marks that the dictionary needs to be reloaded.
+     * Marks that the dictionary needs to be recreated.
      *
      */
-    protected void setNeedsToReload() {
-        mNeedsToReload = true;
+    protected void setNeedsToRecreate() {
+        mNeedsToRecreate = true;
     }
 
     /**
@@ -512,7 +505,7 @@
      * Returns whether a dictionary reload is required.
      */
     private boolean isReloadRequired() {
-        return mBinaryDictionary == null || mNeedsToReload;
+        return mBinaryDictionary == null || mNeedsToRecreate;
     }
 
     /**
@@ -524,8 +517,7 @@
                 @Override
                 public void run() {
                     try {
-                        // TODO: Quit checking contents in ExpandableBinaryDictionary.
-                        if (!mDictFile.exists() || (mNeedsToReload && haveContentsChanged())) {
+                        if (!mDictFile.exists() || mNeedsToRecreate) {
                             // If the dictionary file does not exist or contents have been updated,
                             // generate a new one.
                             createNewDictionaryLocked();
@@ -537,12 +529,12 @@
                                     && matchesExpectedBinaryDictFormatVersionForThisType(
                                             mBinaryDictionary.getFormatVersion()))) {
                                 // Binary dictionary or its format version is not valid. Regenerate
-                                // the dictionary file. writeBinaryDictionary will remove the
+                                // the dictionary file. createNewDictionaryLocked will remove the
                                 // existing files if appropriate.
                                 createNewDictionaryLocked();
                             }
                         }
-                        mNeedsToReload = false;
+                        mNeedsToRecreate = false;
                     } finally {
                         mIsReloading.set(false);
                     }
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index e1cda69..c8ffbe4 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -98,7 +98,7 @@
             // devices. On older versions of the platform, the hook above will be called instead.
             @Override
             public void onChange(final boolean self, final Uri uri) {
-                setNeedsToReload();
+                setNeedsToRecreate();
             }
         };
         cres.registerContentObserver(Words.CONTENT_URI, true, mObserver);
@@ -272,9 +272,4 @@
             }
         }
     }
-
-    @Override
-    protected boolean haveContentsChanged() {
-        return true;
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 38c28a7..06bdba0 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -74,11 +74,6 @@
     }
 
     @Override
-    protected boolean haveContentsChanged() {
-        return false;
-    }
-
-    @Override
     protected void loadInitialContentsLocked() {
         // No initial contents.
     }
diff --git a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java
index de2744f..221bb9a 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java
@@ -61,6 +61,7 @@
         final String action = intent.getAction();
         if (action.equals(DICTIONARY_DECAY_INTENT_ACTION)) {
             PersonalizationHelper.runGCOnAllOpenedUserHistoryDictionaries();
+            PersonalizationHelper.runGCOnAllOpenedPersonalizationDictionaries();
         }
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
index 7c43182..afacd08 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
@@ -16,7 +16,6 @@
 
 package com.android.inputmethod.latin.personalization;
 
-import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.utils.CollectionUtils;
 import com.android.inputmethod.latin.utils.FileUtils;
 
@@ -66,8 +65,8 @@
         if (TimeUnit.MILLISECONDS.toSeconds(
                 DictionaryDecayBroadcastReciever.DICTIONARY_DECAY_INTERVAL)
                         < currentTimestamp - sCurrentTimestampForTesting) {
-            // TODO: Run GC for both PersonalizationDictionary and UserHistoryDictionary.
             runGCOnAllOpenedUserHistoryDictionaries();
+            runGCOnAllOpenedPersonalizationDictionaries();
         }
     }
 
@@ -75,7 +74,6 @@
         runGCOnAllDictionariesIfRequired(sLangUserHistoryDictCache);
     }
 
-    @UsedForTesting
     public static void runGCOnAllOpenedPersonalizationDictionaries() {
         runGCOnAllDictionariesIfRequired(sLangPersonalizationDictCache);
     }
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index 1d84bb5..8bfa63c 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -309,9 +309,8 @@
 
         setupWordViewsTextAndColor(suggestedWords, mSuggestionsCountInStrip);
         final TextView centerWordView = mWordViews.get(mCenterPositionInStrip);
-        final int availableStripWidth = placerView.getWidth()
-                - placerView.getPaddingRight() - placerView.getPaddingLeft();
-        final int centerWidth = getSuggestionWidth(mCenterPositionInStrip, availableStripWidth);
+        final int stripWidth = stripView.getWidth();
+        final int centerWidth = getSuggestionWidth(mCenterPositionInStrip, stripWidth);
         final int countInStrip;
         if (suggestedWords.size() == 1 || getTextScaleX(centerWordView.getText(), centerWidth,
                 centerWordView.getPaint()) < MIN_TEXT_XSCALE) {
@@ -319,11 +318,11 @@
             // by consolidating all slots in the strip.
             countInStrip = 1;
             mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
-            layoutWord(mCenterPositionInStrip, availableStripWidth - mPadding);
+            layoutWord(mCenterPositionInStrip, stripWidth - mPadding);
             stripView.addView(centerWordView);
             setLayoutWeight(centerWordView, 1.0f, ViewGroup.LayoutParams.MATCH_PARENT);
             if (SuggestionStripView.DBG) {
-                layoutDebugInfo(mCenterPositionInStrip, placerView, availableStripWidth);
+                layoutDebugInfo(mCenterPositionInStrip, placerView, stripWidth);
             }
         } else {
             countInStrip = mSuggestionsCountInStrip;
@@ -337,7 +336,7 @@
                     x += divider.getMeasuredWidth();
                 }
 
-                final int width = getSuggestionWidth(positionInStrip, availableStripWidth);
+                final int width = getSuggestionWidth(positionInStrip, stripWidth);
                 final TextView wordView = layoutWord(positionInStrip, width);
                 stripView.addView(wordView);
                 setLayoutWeight(wordView, getSuggestionWeight(positionInStrip),
@@ -474,8 +473,8 @@
         return countInStrip;
     }
 
-    public void layoutAddToDictionaryHint(final String word, final ViewGroup addToDictionaryStrip,
-            final int stripWidth) {
+    public void layoutAddToDictionaryHint(final String word, final ViewGroup addToDictionaryStrip) {
+        final int stripWidth = addToDictionaryStrip.getWidth();
         final int width = stripWidth - mDividerWidth - mPadding * 2;
 
         final TextView wordView = (TextView)addToDictionaryStrip.findViewById(R.id.word_to_save);
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index a0793b1..a578fa4 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -209,7 +209,7 @@
     }
 
     public void showAddToDictionaryHint(final String word) {
-        mLayoutHelper.layoutAddToDictionaryHint(word, mAddToDictionaryStrip, getWidth());
+        mLayoutHelper.layoutAddToDictionaryHint(word, mAddToDictionaryStrip);
         // {@link TextView#setTag()} is used to hold the word to be added to dictionary. The word
         // will be extracted at {@link #onClick(View)}.
         mAddToDictionaryStrip.setTag(word);
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
index f2a1e52..48e43d6 100644
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
+++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
@@ -40,7 +40,7 @@
         mKeyboard = keyboard;
     }
 
-    public boolean isDistractorToWordsInDictionaries(final String prevWord,
+    public boolean isDistracterToWordsInDictionaries(final String prevWord,
             final String targetWord) {
         // TODO: to be implemented
         return false;
diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
index 5ce977d..55061f4 100644
--- a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
+++ b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
@@ -80,7 +80,8 @@
     public static ArrayList<LanguageModelParam> createLanguageModelParamsFrom(
             final ArrayList<String> tokens, final int timestamp,
             final DictionaryFacilitatorForSuggest dictionaryFacilitator,
-            final SpacingAndPunctuations spacingAndPunctuations) {
+            final SpacingAndPunctuations spacingAndPunctuations,
+            final DistracterFilter distracterFilter) {
         final ArrayList<LanguageModelParam> languageModelParams =
                 CollectionUtils.newArrayList();
         final int N = tokens.size();
@@ -109,7 +110,8 @@
             }
             final LanguageModelParam languageModelParam =
                     detectWhetherVaildWordOrNotAndGetLanguageModelParam(
-                            prevWord, tempWord, timestamp, dictionaryFacilitator);
+                            prevWord, tempWord, timestamp, dictionaryFacilitator,
+                            distracterFilter);
             if (languageModelParam == null) {
                 continue;
             }
@@ -121,27 +123,33 @@
 
     private static LanguageModelParam detectWhetherVaildWordOrNotAndGetLanguageModelParam(
             final String prevWord, final String targetWord, final int timestamp,
-            final DictionaryFacilitatorForSuggest dictionaryFacilitator) {
+            final DictionaryFacilitatorForSuggest dictionaryFacilitator,
+            final DistracterFilter distracterFilter) {
         final Locale locale = dictionaryFacilitator.getLocale();
         if (locale == null) {
             return null;
         }
-        if (!dictionaryFacilitator.isValidWord(targetWord, true /* ignoreCase */)) {
-            // OOV word.
-            return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp,
-                    false /* isValidWord */, locale);
-        }
         if (dictionaryFacilitator.isValidWord(targetWord, false /* ignoreCase */)) {
             return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp,
                     true /* isValidWord */, locale);
         }
+
         final String lowerCaseTargetWord = targetWord.toLowerCase(locale);
         if (dictionaryFacilitator.isValidWord(lowerCaseTargetWord, false /* ignoreCase */)) {
             // Add the lower-cased word.
             return createAndGetLanguageModelParamOfWord(prevWord, lowerCaseTargetWord,
                     timestamp, true /* isValidWord */, locale);
         }
-        // Treat the word as an OOV word.
+
+        // Treat the word as an OOV word. The following statement checks whether this OOV
+        // is a distracter to words in dictionaries. Being a distracter means the OOV word is
+        // too close to a common word in dictionaries (e.g., the OOV "mot" is very close to "not").
+        // Adding such a word to dictonaries would interfere with entering in-dictionary words. For
+        // example, adding "mot" to dictionaries might interfere with entering "not".
+        // This kind of OOV should be filtered out.
+        if (distracterFilter.isDistracterToWordsInDictionaries(prevWord, targetWord)) {
+            return null;
+        }
         return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp,
                 false /* isValidWord */, locale);
     }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h b/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
index 23cbe3a..a2e88a4 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
@@ -37,13 +37,13 @@
     BufferWithExtendableBuffer(uint8_t *const originalBuffer, const int originalBufferSize,
             const int maxAdditionalBufferSize)
             : mOriginalBuffer(originalBuffer), mOriginalBufferSize(originalBufferSize),
-              mAdditionalBuffer(EXTEND_ADDITIONAL_BUFFER_SIZE_STEP), mUsedAdditionalBufferSize(0),
+              mAdditionalBuffer(0), mUsedAdditionalBufferSize(0),
               mMaxAdditionalBufferSize(maxAdditionalBufferSize) {}
 
     // Without original buffer.
     BufferWithExtendableBuffer(const int maxAdditionalBufferSize)
             : mOriginalBuffer(0), mOriginalBufferSize(0),
-              mAdditionalBuffer(EXTEND_ADDITIONAL_BUFFER_SIZE_STEP), mUsedAdditionalBufferSize(0),
+              mAdditionalBuffer(0), mUsedAdditionalBufferSize(0),
               mMaxAdditionalBufferSize(maxAdditionalBufferSize) {}
 
     AK_FORCE_INLINE int getTailPosition() const {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/EnglishCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/EnglishCustomizer.java
index 29264ff..3e82f65 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/EnglishCustomizer.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/EnglishCustomizer.java
@@ -27,34 +27,34 @@
     @Override
     public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
         return builder
-                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
                 // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
                 // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
                 // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
                 // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                .setMoreKeysOf("e", "\u00E8", "\u00E9", "\u00EA", "\u00EB", "\u0113")
+                .setMoreKeysOf("e", "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0113")
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
                 // 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
-                .setMoreKeysOf("u", "\u00FB", "\u00FC", "\u00F9", "\u00FA", "\u016B")
+                .setMoreKeysOf("u", "\u00FA", "\u00FB", "\u00FC", "\u00F9", "\u016B")
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
                 // 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
-                .setMoreKeysOf("i", "\u00EE", "\u00EF", "\u00ED", "\u012B", "\u00EC")
+                .setMoreKeysOf("i", "\u00ED", "\u00EE", "\u00EF", "\u012B", "\u00EC")
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
                 // 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
                 .setMoreKeysOf("o",
-                        "\u00F4", "\u00F6", "\u00F2", "\u00F3", "\u0153", "\u00F8", "\u014D",
+                        "\u00F3", "\u00F4", "\u00F6", "\u00F2", "\u0153", "\u00F8", "\u014D",
                         "\u00F5")
                 // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
                 // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
diff --git a/tools/make-keyboard-text/res/values-en/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-en/donottranslate-more-keys.xml
index 7998bf1..c22edba 100644
--- a/tools/make-keyboard-text/res/values-en/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-en/donottranslate-more-keys.xml
@@ -27,33 +27,33 @@
          U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
          U+0101: "ā" LATIN SMALL LETTER A WITH MACRON -->
     <string name="morekeys_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+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+         U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
          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="morekeys_e">&#x00E8;,&#x00E9;,&#x00EA;,&#x00EB;,&#x0113;</string>
-    <!-- U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+    <string name="morekeys_e">&#x00E9;,&#x00E8;,&#x00EA;,&#x00EB;,&#x0113;</string>
+    <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+         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="morekeys_i">&#x00EE;,&#x00EF;,&#x00ED;,&#x012B;,&#x00EC;</string>
-    <!-- U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+    <string name="morekeys_i">&#x00ED;,&#x00EE;,&#x00EF;,&#x012B;,&#x00EC;</string>
+    <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+         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="morekeys_o">&#x00F4;,&#x00F6;,&#x00F2;,&#x00F3;,&#x0153;,&#x00F8;,&#x014D;,&#x00F5;</string>
-    <!-- U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+    <string name="morekeys_o">&#x00F3;,&#x00F4;,&#x00F6;,&#x00F2;,&#x0153;,&#x00F8;,&#x014D;,&#x00F5;</string>
+    <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+         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="morekeys_u">&#x00FB;,&#x00FC;,&#x00F9;,&#x00FA;,&#x016B;</string>
+    <string name="morekeys_u">&#x00FA;,&#x00FB;,&#x00FC;,&#x00F9;,&#x016B;</string>
     <!-- U+00DF: "ß" LATIN SMALL LETTER SHARP S -->
     <string name="morekeys_s">&#x00DF;</string>
     <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE -->
diff --git a/tools/make-keyboard-text/res/values-zu/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-zu/donottranslate-more-keys.xml
index f9150f3..2c5df0c 100644
--- a/tools/make-keyboard-text/res/values-zu/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-zu/donottranslate-more-keys.xml
@@ -28,33 +28,33 @@
          U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
          U+0101: "ā" LATIN SMALL LETTER A WITH MACRON -->
     <string name="morekeys_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+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+         U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
          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="morekeys_e">&#x00E8;,&#x00E9;,&#x00EA;,&#x00EB;,&#x0113;</string>
-    <!-- U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+    <string name="morekeys_e">&#x00E9;,&#x00E8;,&#x00EA;,&#x00EB;,&#x0113;</string>
+    <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+         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="morekeys_i">&#x00EE;,&#x00EF;,&#x00ED;,&#x012B;,&#x00EC;</string>
-    <!-- U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+    <string name="morekeys_i">&#x00ED;,&#x00EE;,&#x00EF;,&#x012B;,&#x00EC;</string>
+    <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+         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="morekeys_o">&#x00F4;,&#x00F6;,&#x00F2;,&#x00F3;,&#x0153;,&#x00F8;,&#x014D;,&#x00F5;</string>
-    <!-- U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+    <string name="morekeys_o">&#x00F3;,&#x00F4;,&#x00F6;,&#x00F2;,&#x0153;,&#x00F8;,&#x014D;,&#x00F5;</string>
+    <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+         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="morekeys_u">&#x00FB;,&#x00FC;,&#x00F9;,&#x00FA;,&#x016B;</string>
+    <string name="morekeys_u">&#x00FA;,&#x00FB;,&#x00FC;,&#x00F9;,&#x016B;</string>
     <!-- U+00DF: "ß" LATIN SMALL LETTER SHARP S -->
     <string name="morekeys_s">&#x00DF;</string>
     <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE -->