Merge "Change constants in ResearchLogger"
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index fc0bec3..d70c05d 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"የድምፅ ግቤ ት"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"የፈገግታ ፊት"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"ተመለስ"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"ፍለጋ"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"ነጥብ"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"ቅያር ቁልፍ ነቅቷል"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"አቢያት ማድረጊያ ነቅቷል"</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index fa8d804..50b0b0a 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Stemmeinput"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Tilbage"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Søg"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Punktum"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Skift er aktiveret"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock er aktiveret"</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index 2c3cac7..216aac5 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Spracheingabe"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Eingabe"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Suchen"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Aufzählungspunkt"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Umschalttaste aktiviert"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Feststelltaste aktiviert"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 356f9d2..486346a 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Μικρόφωνο"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Πλήκτρο Return"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Αναζήτηση"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Κουκκίδα"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Το Shift ενεργοποιημένο"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Το Caps lock είναι ενεργοποιημένο"</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 43260b7..bcc327f 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -23,7 +23,7 @@
     <string name="english_ime_name" msgid="7252517407088836577">"Teclado de Android"</string>
     <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
     <string name="english_ime_settings" msgid="6661589557206947774">"Ajustes del teclado de Android"</string>
-    <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones introducción texto"</string>
+    <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones entrada texto"</string>
     <string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector de Android"</string>
     <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector de Android (AOSP)"</string>
     <string name="android_spell_checker_settings" msgid="5822324635435443689">"Ajustes del corrector ortográfico"</string>
@@ -37,7 +37,7 @@
     <string name="misc_category" msgid="6894192814868233453">"Otras opciones"</string>
     <string name="advanced_settings" msgid="362895144495591463">"Ajustes avanzados"</string>
     <string name="advanced_settings_summary" msgid="4487980456152830271">"Opciones para expertos"</string>
-    <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de introducción"</string>
+    <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de entrada"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma sirve también para otros métodos"</string>
     <string name="suppress_language_switch_key" msgid="8003788410354806368">"Quitar tecla de idioma"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso al ampliar tecla"</string>
@@ -110,13 +110,13 @@
     <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrófono en teclado principal"</string>
     <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micrófono en teclado de símbolos"</string>
     <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entrada de voz inhabilitada"</string>
-    <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de introducción"</string>
+    <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas"</string>
     <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toca otra vez para guardar."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Hay un diccionario disponible"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"Habilitar comentarios de usuarios"</string>
-    <string name="prefs_description_log" msgid="5827825607258246003">"Ayuda a mejorar este editor de método de introducción de texto enviando estadísticas de uso e informes de error a Google."</string>
+    <string name="prefs_description_log" msgid="5827825607258246003">"Ayuda a mejorar este editor de método de entrada de texto enviando estadísticas de uso e informes de error a Google."</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema de teclado"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"inglés (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"inglés (EE.UU.)"</string>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 4bf0e9e..285d222 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Saisie vocale"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Émoticône"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Entrée"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Rechercher"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Point"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Touche Maj activée"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Verrouillage des majuscules activé"</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 62aef99..2b18084 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"ध्‍वनि इनपुट"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"मुस्कुराता चेहरा"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"रिटर्न"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"खोजें"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"बिंदु"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift सक्षम किया गया"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock सक्षम किया गया"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 2426921..0eac1a9 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Hangbevitel"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Mosolygós arc"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Keresés"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Pont"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift bekapcsolva"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock bekapcsolva"</string>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index 49fba2e..e0e92b5 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Masukan suara"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Wajah tersenyum"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Kembali"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Telusuri"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Titik"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift diaktifkan"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock diaktifkan"</string>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index cf972a6..1929035 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Input vocale"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Smile"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Invio"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Ricerca"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Pallino"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Maiuscolo attivo"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Blocco maiuscole attivo"</string>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 3040fb0..536f06d 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"음성 입력"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"웃는 얼굴"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"리턴 키"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"검색"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"점"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift 사용"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock 사용"</string>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 7f68314..93727a8 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Balss ievade"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Smaidoša seja"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Ievadīšanas taustiņš"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Meklēt"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Punkts"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Pārslēgšanas režīms iespējots"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Burtslēgs iespējots"</string>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index 7912cd4..a7d499b 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Spraakinvoer"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley-gezichtje"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Zoeken"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Stip"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ingeschakeld"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock ingeschakeld"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 2926af5..ccb042e 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Entrada de voz"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Cara sorridente"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Pesquisar"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Ponto"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ativado"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock ativado"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index de5c174..75e80d4 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Röstinmatning"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Uttryckssymbol"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Retur"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Sök"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Punkt"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Skift är aktiverat"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock är aktiverat"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 52d81d7..82c867e 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Uingizaji sauti"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Uso wenye tabasamu"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Rudi"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Tafuta"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Nukta"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift imewezeshwa"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock imewezeshwa"</string>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index 5c4aeba..da20d66 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"การป้อนข้อมูลด้วยเสียง"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"หน้ายิ้ม"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"ค้นหา"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"เครื่องหมายจุด"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"เปิดใช้งาน Shift แล้ว"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"เปิดใช้งาน Caps Lock แล้ว"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index af4a02e..d3f80e4 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -93,8 +93,7 @@
     <string name="spoken_description_mic" msgid="615536748882611950">"Okungenayo kwezwi"</string>
     <string name="spoken_description_smiley" msgid="2256309826200113918">"Ubuso-obumomothekayo"</string>
     <string name="spoken_description_return" msgid="8178083177238315647">"Buyisela"</string>
-    <!-- no translation found for spoken_description_search (1247236163755920808) -->
-    <skip />
+    <string name="spoken_description_search" msgid="1247236163755920808">"Sesha"</string>
     <string name="spoken_description_dot" msgid="40711082435231673">"Icashazi"</string>
     <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"U-Shift uvunyelwe"</string>
     <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Ofeleba bavunyelwe"</string>
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
index 9986f6e..ba08c59 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
@@ -85,9 +85,20 @@
      */
     public void setView(KeyboardView keyboardView) {
         mKeyboardView = keyboardView;
-
-        assignVirtualViewIds();
         updateParentLocation();
+
+        // Since this class is constructed lazily, we might not get a subsequent
+        // call to setKeyboard() and therefore need to call it now.
+        setKeyboard(mKeyboardView.getKeyboard());
+    }
+
+    /**
+     * Sets the keyboard represented by this node provider.
+     *
+     * @param keyboard The keyboard to represent.
+     */
+    public void setKeyboard(Keyboard keyboard) {
+        assignVirtualViewIds();
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index 59f1eec..f6376d5 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -86,6 +86,12 @@
         }
     }
 
+    public void setKeyboard(Keyboard keyboard) {
+        if (mAccessibilityNodeProvider != null) {
+            mAccessibilityNodeProvider.setKeyboard(keyboard);
+        }
+    }
+
     /**
      * Proxy method for View.getAccessibilityNodeProvider(). This method is
      * called in SDK version 15 and higher to obtain the virtual node hierarchy
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index e917a81..383298d 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -468,6 +468,10 @@
         if (ProductionFlag.IS_EXPERIMENTAL) {
             ResearchLogger.latinKeyboardView_setKeyboard(keyboard);
         }
+
+        // This always needs to be set since the accessibility state can
+        // potentially change without the keyboard being set again.
+        AccessibleKeyboardViewProxy.getInstance().setKeyboard(keyboard);
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 98cf76c..7092b4e 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -982,7 +982,9 @@
         final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
         if (inputView == null || mSuggestionsContainer == null)
             return;
-        final int backingHeight = getAdjustedBackingViewHeight();
+        final int adjustedBackingHeight = getAdjustedBackingViewHeight();
+        final boolean backingGone = (mKeyPreviewBackingView.getVisibility() == View.GONE);
+        final int backingHeight = backingGone ? 0 : adjustedBackingHeight;
         // In fullscreen mode, the height of the extract area managed by InputMethodService should
         // be considered.
         // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}.
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
index 4994e59..673b545 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
@@ -20,12 +20,13 @@
 
 import com.android.inputmethod.keyboard.ProximityInfo;
 
+import java.util.Locale;
+
 public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryDictionary {
     private boolean mClosed;
 
-    public SynchronouslyLoadedContactsBinaryDictionary(final Context context) {
-        // TODO: add locale information.
-        super(context, Suggest.DIC_CONTACTS, null);
+    public SynchronouslyLoadedContactsBinaryDictionary(final Context context, final Locale locale) {
+        super(context, Suggest.DIC_CONTACTS, locale);
     }
 
     @Override
@@ -51,4 +52,4 @@
         mClosed = true;
         super.close();
     }
-}
\ No newline at end of file
+}
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
index c8ad40b..a6ff895 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
@@ -72,10 +72,10 @@
     private static final String FREQ_TABLE_NAME = "frequency";
     private static final String FREQ_COLUMN_ID = BaseColumns._ID;
     private static final String FREQ_COLUMN_PAIR_ID = "pair_id";
-    private static final String FREQ_COLUMN_FREQUENCY = "freq";
+    private static final String COLUMN_FORGETTING_CURVE_VALUE = "freq";
 
-    /** Locale for which this auto dictionary is storing words */
-    private String mLocale;
+    /** Locale for which this user history dictionary is storing words */
+    private final String mLocale;
 
     private UserHistoryDictionaryBigramList mBigramList =
             new UserHistoryDictionaryBigramList();
@@ -94,7 +94,7 @@
 
         sDictProjectionMap.put(FREQ_COLUMN_ID, FREQ_COLUMN_ID);
         sDictProjectionMap.put(FREQ_COLUMN_PAIR_ID, FREQ_COLUMN_PAIR_ID);
-        sDictProjectionMap.put(FREQ_COLUMN_FREQUENCY, FREQ_COLUMN_FREQUENCY);
+        sDictProjectionMap.put(COLUMN_FORGETTING_CURVE_VALUE, COLUMN_FORGETTING_CURVE_VALUE);
     }
 
     private static DatabaseHelper sOpenHelper = null;
@@ -214,25 +214,26 @@
             if (cursor.moveToFirst()) {
                 final int word1Index = cursor.getColumnIndex(MAIN_COLUMN_WORD1);
                 final int word2Index = cursor.getColumnIndex(MAIN_COLUMN_WORD2);
-                final int frequencyIndex = cursor.getColumnIndex(FREQ_COLUMN_FREQUENCY);
+                final int fcIndex = cursor.getColumnIndex(COLUMN_FORGETTING_CURVE_VALUE);
                 while (!cursor.isAfterLast()) {
                     final String word1 = cursor.getString(word1Index);
                     final String word2 = cursor.getString(word2Index);
-                    final int frequency = cursor.getInt(frequencyIndex);
+                    final int fc = cursor.getInt(fcIndex);
                     if (DBG_SAVE_RESTORE) {
-                        Log.d(TAG, "--- Load user history: " + word1 + ", " + word2);
+                        Log.d(TAG, "--- Load user history: " + word1 + ", " + word2 + ","
+                                + mLocale + "," + this);
                     }
                     // Safeguard against adding really long words. Stack may overflow due
                     // to recursive lookup
                     if (null == word1) {
-                        super.addWord(word2, null /* shortcut */, frequency);
+                        super.addWord(word2, null /* shortcut */, fc);
                     } else if (word1.length() < BinaryDictionary.MAX_WORD_LENGTH
                             && word2.length() < BinaryDictionary.MAX_WORD_LENGTH) {
                         super.setBigramAndGetFrequency(
-                                word1, word2, new ForgettingCurveParams(frequency, now, last));
+                                word1, word2, new ForgettingCurveParams(fc, now, last));
                     }
                     synchronized(mPendingWritesLock) {
-                        mBigramList.addBigram(word1, word2);
+                        mBigramList.addBigram(word1, word2, (byte)fc);
                     }
                     cursor.moveToNext();
                 }
@@ -259,7 +260,8 @@
         try {
             SQLiteDatabase db = sOpenHelper.getReadableDatabase();
             Cursor c = qb.query(db,
-                    new String[] { MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, FREQ_COLUMN_FREQUENCY },
+                    new String[] {
+                            MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, COLUMN_FORGETTING_CURVE_VALUE },
                     selection, selectionArgs, null, null, null);
             return c;
         } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) {
@@ -290,7 +292,7 @@
             db.execSQL("CREATE TABLE " + FREQ_TABLE_NAME + " ("
                     + FREQ_COLUMN_ID + " INTEGER PRIMARY KEY,"
                     + FREQ_COLUMN_PAIR_ID + " INTEGER,"
-                    + FREQ_COLUMN_FREQUENCY + " INTEGER,"
+                    + COLUMN_FORGETTING_CURVE_VALUE + " INTEGER,"
                     + "FOREIGN KEY(" + FREQ_COLUMN_PAIR_ID + ") REFERENCES " + MAIN_TABLE_NAME
                     + "(" + MAIN_COLUMN_ID + ")" + " ON DELETE CASCADE"
                     + ");");
@@ -378,10 +380,40 @@
 
             // Write all the entries to the db
             for (String word1 : mBigramList.keySet()) {
-                for (String word2 : mBigramList.getBigrams(word1)) {
+                final HashMap<String, Byte> word1Bigrams = mBigramList.getBigrams(word1);
+                for (String word2 : word1Bigrams.keySet()) {
+                    // Get new frequency. Do not insert shortcuts/bigrams which freq is "-1".
+                    final int freq; // -1, or 0~255
+                    if (word1 == null) {
+                        freq = FREQUENCY_FOR_TYPED;
+                    } else {
+                        final NextWord nw = mUserHistoryDictionary.getBigramWord(word1, word2);
+                        if (nw != null) {
+                            final ForgettingCurveParams fcp = nw.getFcParams();
+                            final byte prevFc = word1Bigrams.get(word2);
+                            final byte fc = (byte)fcp.getFc();
+                            final boolean isValid = fcp.isValid();
+                            if (prevFc > 0 && prevFc == fc) {
+                                // No need to update since we found no changes for this entry.
+                                // Just skip to the next entry.
+                                if (DBG_SAVE_RESTORE) {
+                                    Log.d(TAG, "Skip update user history: " + word1 + "," + word2
+                                            + "," + prevFc);
+                                }
+                                continue;
+                            } else if (UserHistoryForgettingCurveUtils.
+                                    needsToSave(fc, isValid, addLevel0Bigram)) {
+                                freq = fc;
+                            } else {
+                                freq = -1;
+                            }
+                        } else {
+                            freq = -1;
+                        }
+                    }
                     // TODO: this process of making a text search for each pair each time
                     // is terribly inefficient. Optimize this.
-                    // find pair id
+                    // Find pair id
                     Cursor c = null;
                     try {
                         if (null != word1) {
@@ -399,40 +431,22 @@
 
                         final int pairId;
                         if (c.moveToFirst()) {
-                            // existing pair
+                            // Delete existing pair
                             pairId = c.getInt(c.getColumnIndex(MAIN_COLUMN_ID));
                             db.delete(FREQ_TABLE_NAME, FREQ_COLUMN_PAIR_ID + "=?",
                                     new String[] { Integer.toString(pairId) });
                         } else {
-                            // new pair
+                            // Create new pair
                             Long pairIdLong = db.insert(MAIN_TABLE_NAME, null,
                                     getContentValues(word1, word2, mLocale));
                             pairId = pairIdLong.intValue();
                         }
-                        // insert new frequency
-                        final int freq;
-                        if (word1 == null) {
-                            freq = FREQUENCY_FOR_TYPED;
-                        } else {
-                            final NextWord nw = mUserHistoryDictionary.getBigramWord(word1, word2);
-                            if (nw != null) {
-                                final ForgettingCurveParams fcp = nw.getFcParams();
-                                final int tempFreq = fcp.getFc();
-                                final boolean isValid = fcp.isValid();
-                                if (UserHistoryForgettingCurveUtils.needsToSave(
-                                        (byte)tempFreq, isValid, addLevel0Bigram)) {
-                                    freq = tempFreq;
-                                } else {
-                                    freq = -1;
-                                }
-                            } else {
-                                freq = -1;
-                            }
-                        }
                         if (freq > 0) {
                             if (DBG_SAVE_RESTORE) {
-                                Log.d(TAG, "--- Save user history: " + word1 + ", " + word2);
+                                Log.d(TAG, "--- Save user history: " + word1 + ", " + word2
+                                        + mLocale + "," + this);
                             }
+                            // Insert new frequency
                             db.insert(FREQ_TABLE_NAME, null,
                                     getFrequencyContentValues(pairId, freq));
                         }
@@ -461,7 +475,7 @@
         private static ContentValues getFrequencyContentValues(int pairId, int frequency) {
            ContentValues values = new ContentValues(2);
            values.put(FREQ_COLUMN_PAIR_ID, pairId);
-           values.put(FREQ_COLUMN_FREQUENCY, frequency);
+           values.put(COLUMN_FORGETTING_CURVE_VALUE, frequency);
            return values;
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
index 409f921..96400dd 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
@@ -19,7 +19,6 @@
 import android.util.Log;
 
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Set;
 
 /**
@@ -28,10 +27,11 @@
  * bigrams when we write to the SQL DB.
  */
 public class UserHistoryDictionaryBigramList {
+    public static final byte FORGETTING_CURVE_INITIAL_VALUE = 0;
     private static final String TAG = UserHistoryDictionaryBigramList.class.getSimpleName();
-    private static final HashSet<String> EMPTY_STRING_SET = new HashSet<String>();
-    private final HashMap<String, HashSet<String>> mBigramMap =
-            new HashMap<String, HashSet<String>>();
+    private static final HashMap<String, Byte> EMPTY_BIGRAM_MAP = new HashMap<String, Byte>();
+    private final HashMap<String, HashMap<String, Byte>> mBigramMap =
+            new HashMap<String, HashMap<String, Byte>>();
     private int mSize = 0;
 
     public void evictAll() {
@@ -40,19 +40,23 @@
     }
 
     public void addBigram(String word1, String word2) {
+        addBigram(word1, word2, FORGETTING_CURVE_INITIAL_VALUE);
+    }
+
+    public void addBigram(String word1, String word2, byte fcValue) {
         if (UserHistoryDictionary.DBG_SAVE_RESTORE) {
             Log.d(TAG, "--- add bigram: " + word1 + ", " + word2);
         }
-        final HashSet<String> set;
+        final HashMap<String, Byte> map;
         if (mBigramMap.containsKey(word1)) {
-            set = mBigramMap.get(word1);
+            map = mBigramMap.get(word1);
         } else {
-            set = new HashSet<String>();
-            mBigramMap.put(word1, set);
+            map = new HashMap<String, Byte>();
+            mBigramMap.put(word1, map);
         }
-        if (!set.contains(word2)) {
+        if (!map.containsKey(word2)) {
             ++mSize;
-            set.add(word2);
+            map.put(word2, fcValue);
         }
     }
 
@@ -68,20 +72,20 @@
         return mBigramMap.keySet();
     }
 
-    public HashSet<String> getBigrams(String word1) {
+    public HashMap<String, Byte> getBigrams(String word1) {
         if (!mBigramMap.containsKey(word1)) {
-            return EMPTY_STRING_SET;
+            return EMPTY_BIGRAM_MAP;
         } else {
             return mBigramMap.get(word1);
         }
     }
 
     public boolean removeBigram(String word1, String word2) {
-        final HashSet<String> set = getBigrams(word1);
+        final HashMap<String, Byte> set = getBigrams(word1);
         if (set.isEmpty()) {
             return false;
         }
-        if (set.contains(word2)) {
+        if (set.containsKey(word2)) {
             set.remove(word2);
             --mSize;
             return true;
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 0e3bf80..8128779 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -99,11 +99,13 @@
         // List of the supported languages and their associated script. We won't check
         // words written in another script than the selected script, because we know we
         // don't have those in our dictionary so we will underline everything and we
-        // will never have any suggestions, so it makes no sense checking them.
+        // will never have any suggestions, so it makes no sense checking them, and this
+        // is done in {@link #shouldFilterOut}. Also, the script is used to choose which
+        // proximity to pass to the dictionary descent algorithm.
+        // IMPORTANT: this only contains languages - do not write countries in there.
+        // Only the language is searched from the map.
         mLanguageToScript = new TreeMap<String, Integer>();
         mLanguageToScript.put("en", SCRIPT_LATIN);
-        mLanguageToScript.put("en_US", SCRIPT_LATIN);
-        mLanguageToScript.put("en_GB", SCRIPT_LATIN);
         mLanguageToScript.put("fr", SCRIPT_LATIN);
         mLanguageToScript.put("de", SCRIPT_LATIN);
         mLanguageToScript.put("nl", SCRIPT_LATIN);
@@ -111,7 +113,7 @@
         mLanguageToScript.put("es", SCRIPT_LATIN);
         mLanguageToScript.put("it", SCRIPT_LATIN);
         mLanguageToScript.put("hr", SCRIPT_LATIN);
-        mLanguageToScript.put("pt_BR", SCRIPT_LATIN);
+        mLanguageToScript.put("pt", SCRIPT_LATIN);
         mLanguageToScript.put("ru", SCRIPT_CYRILLIC);
         // TODO: Make a persian proximity, and activate the Farsi subtype.
         // mLanguageToScript.put("fa", SCRIPT_PERSIAN);
@@ -152,7 +154,13 @@
 
     private void startUsingContactsDictionaryLocked() {
         if (null == mContactsDictionary) {
-            mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
+            if (LatinIME.USE_BINARY_CONTACTS_DICTIONARY) {
+                // TODO: use the right locale for each session
+                mContactsDictionary =
+                        new SynchronouslyLoadedContactsBinaryDictionary(this, Locale.getDefault());
+            } else {
+                mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
+            }
         }
         final Iterator<WeakReference<DictionaryCollection>> iterator =
                 mDictionaryCollectionsList.iterator();
@@ -430,7 +438,11 @@
                     // TODO: revert to the concrete type when USE_BINARY_CONTACTS_DICTIONARY is no
                     // longer needed
                     if (LatinIME.USE_BINARY_CONTACTS_DICTIONARY) {
-                        mContactsDictionary = new SynchronouslyLoadedContactsBinaryDictionary(this);
+                        // TODO: use the right locale. We can't do it right now because the
+                        // spell checker is reusing the contacts dictionary across sessions
+                        // without regard for their locale, so we need to fix that first.
+                        mContactsDictionary = new SynchronouslyLoadedContactsBinaryDictionary(this,
+                                Locale.getDefault());
                     } else {
                         mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
                     }