Merge "Stop building host native test in unbundled build"
diff --git a/java/src/com/android/inputmethod/annotations/ExternallyReferenced.java b/common/src/com/android/inputmethod/annotations/ExternallyReferenced.java
similarity index 100%
rename from java/src/com/android/inputmethod/annotations/ExternallyReferenced.java
rename to common/src/com/android/inputmethod/annotations/ExternallyReferenced.java
diff --git a/java/src/com/android/inputmethod/annotations/UsedForTesting.java b/common/src/com/android/inputmethod/annotations/UsedForTesting.java
similarity index 100%
rename from java/src/com/android/inputmethod/annotations/UsedForTesting.java
rename to common/src/com/android/inputmethod/annotations/UsedForTesting.java
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/common/src/com/android/inputmethod/latin/Constants.java
similarity index 97%
rename from java/src/com/android/inputmethod/latin/Constants.java
rename to common/src/com/android/inputmethod/latin/Constants.java
index fc7f95c..0fd5659 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/common/src/com/android/inputmethod/latin/Constants.java
@@ -233,8 +233,8 @@
 
     /**
      * Special keys code. Must be negative.
-     * These should be aligned with {@link KeyboardCodesSet#ID_TO_NAME},
-     * {@link KeyboardCodesSet#DEFAULT}, and {@link KeyboardCodesSet#RTL}.
+     * These should be aligned with constants in
+     * {@link com.android.inputmethod.keyboard.internal.KeyboardCodesSet}.
      */
     public static final int CODE_SHIFT = -1;
     public static final int CODE_CAPSLOCK = -2;
@@ -309,8 +309,8 @@
 
     /**
      * Default capacity of gesture points container.
-     * This constant is used by {@link BatchInputArbiter} and etc. to preallocate regions that
-     * contain gesture event points.
+     * This constant is used by {@link com.android.inputmethod.keyboard.internal.BatchInputArbiter}
+     * and etc. to preallocate regions that contain gesture event points.
      */
     public static final int DEFAULT_GESTURE_POINTS_CAPACITY = 128;
 
diff --git a/java-overridable/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java b/java-overridable/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java
index 21535e4..f5e56eb 100644
--- a/java-overridable/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java
+++ b/java-overridable/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java
@@ -18,6 +18,7 @@
 
 import android.content.pm.PackageInfo;
 
+@SuppressWarnings("unused")
 public class AppWorkaroundsHelper {
     private AppWorkaroundsHelper() {
         // This helper class is not publicly instantiable.
diff --git a/java-overridable/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java b/java-overridable/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java
index ed81765..d8951df 100644
--- a/java-overridable/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java
+++ b/java-overridable/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java
@@ -21,6 +21,7 @@
 /**
  * Helper to get the metadata URI from its base URI and the additional ID, if any.
  */
+@SuppressWarnings("unused")
 public class MetadataUriGetter {
     private MetadataUriGetter() {
         // This helper class is not instantiable.
diff --git a/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java b/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java
index e07a9f3..dcc64a2 100644
--- a/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java
@@ -40,6 +40,7 @@
      * @return an array of accounts. Empty (never null) if no accounts are available for login.
      */
     @Nonnull
+    @SuppressWarnings("unused")
     public static String[] getAccountsForLogin(final Context context) {
         return new String[0];
     }
diff --git a/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java b/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java
index 99b9589..f806256 100644
--- a/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java
+++ b/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java
@@ -24,7 +24,8 @@
     public static final boolean IS_HARDWARE_KEYBOARD_SUPPORTED = false;
 
     /**
-     * Include all suggestions from all dictionaries in {@link SuggestedWords#mRawSuggestions}.
+     * Include all suggestions from all dictionaries in
+     * {@link com.android.inputmethod.latin.SuggestedWords#mRawSuggestions}.
      */
     public static final boolean INCLUDE_RAW_SUGGESTIONS = false;
 
diff --git a/java-overridable/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java b/java-overridable/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java
index 7dc120e..fe1d846 100644
--- a/java-overridable/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java
+++ b/java-overridable/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.latin.DictionaryFacilitator;
 
+@SuppressWarnings("unused")
 public class ContextualDictionaryUpdater {
     public ContextualDictionaryUpdater(final Context context,
             final DictionaryFacilitator dictionaryFacilitator,
diff --git a/java-overridable/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java b/java-overridable/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java
index 8b66cff..64bace3 100644
--- a/java-overridable/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java
+++ b/java-overridable/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.latin.DictionaryFacilitator;
 
+@SuppressWarnings("unused")
 public class PersonalizationDictionaryUpdater {
     final Context mContext;
     final DictionaryFacilitator mDictionaryFacilitator;
diff --git a/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
index 1dfaf25..bd54238 100644
--- a/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
@@ -29,6 +29,7 @@
 /**
  * Utility class for managing additional features settings.
  */
+@SuppressWarnings("unused")
 public class AdditionalFeaturesSettingUtils {
     public static final int ADDITIONAL_FEATURES_SETTINGS_SIZE = 0;
 
diff --git a/java-overridable/src/com/android/inputmethod/latin/touchinputconsumer/GestureConsumer.java b/java-overridable/src/com/android/inputmethod/latin/touchinputconsumer/GestureConsumer.java
index 672d6d1..1d60e0c 100644
--- a/java-overridable/src/com/android/inputmethod/latin/touchinputconsumer/GestureConsumer.java
+++ b/java-overridable/src/com/android/inputmethod/latin/touchinputconsumer/GestureConsumer.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.latin.touchinputconsumer;
 
 import android.view.inputmethod.EditorInfo;
+
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.latin.InputPointers;
 import com.android.inputmethod.latin.SuggestedWords;
@@ -31,6 +32,7 @@
  * The methods of this class should only be called from a single thread, e.g.,
  * the UI Thread.
  */
+@SuppressWarnings("unused")
 public class GestureConsumer {
     public static final GestureConsumer NULL_GESTURE_CONSUMER =
             new GestureConsumer();
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/FeedbackUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/FeedbackUtils.java
index 0aed41e..67de8ba 100644
--- a/java-overridable/src/com/android/inputmethod/latin/utils/FeedbackUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/FeedbackUtils.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 
+@SuppressWarnings("unused")
 public class FeedbackUtils {
     public static boolean isHelpAndFeedbackFormSupported() {
         return false;
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java b/java-overridable/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java
index 9ad319d..97fb17d 100644
--- a/java-overridable/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java
@@ -23,6 +23,7 @@
 /**
  * Helper class to get the metadata URI and the additional ID.
  */
+@SuppressWarnings("unused")
 public class MetadataFileUriGetter {
     private MetadataFileUriGetter() {
         // This helper class is not instantiable.
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
index fcaeca8..0449702 100644
--- a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
@@ -22,6 +22,7 @@
 
 import javax.annotation.Nullable;
 
+@SuppressWarnings("unused")
 public final class StatsUtils {
 
     private StatsUtils() {
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java
index 138f70f..c99dbf6 100644
--- a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java
@@ -21,6 +21,7 @@
 
 import com.android.inputmethod.latin.settings.SettingsValues;
 
+@SuppressWarnings("unused")
 public class StatsUtilsManager {
 
     private static final StatsUtilsManager sInstance = new StatsUtilsManager();
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index da93a58..17615e5 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -78,7 +78,7 @@
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"No hi ha cap mètode d\'introducció activat. Comprova la configuració d\'Idioma i introducció de text."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configura mètodes d\'entrada"</string>
     <string name="language_selection_title" msgid="3666971864764478269">"Idiomes"</string>
-    <string name="help_and_feedback" msgid="5328219371839879161">"Ajuda i opinió"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Ajuda i suggeriments"</string>
     <string name="select_language" msgid="5709487854987078367">"Idiomes"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Torna a tocar per desar"</string>
     <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toca aquí per desar."</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 3739cdf..b8fcd81 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -74,7 +74,7 @@
     <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Näytä ehdotettu sana piirron aikana"</string>
     <string name="gesture_space_aware" msgid="2078291600664682496">"Ilmausele"</string>
     <string name="gesture_space_aware_summary" msgid="4371385818348528538">"Lisää välilyöntejä eleiden aikana liukumalla välilyöntinäppäim."</string>
-    <string name="voice_input" msgid="3583258583521397548">"Äänisyöteavain"</string>
+    <string name="voice_input" msgid="3583258583521397548">"Äänisyötenäppäin"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Äänen syöttötapoja ei ole otettu käyttöön. Tarkista Kieli ja syöttötapa -asetukset."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Määritä syöttötavat"</string>
     <string name="language_selection_title" msgid="3666971864764478269">"Kielet"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index 3c803a3..1f9590e 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -25,7 +25,7 @@
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Trình kiểm tra chính tả sử dụng các mục nhập từ danh sách liên hệ của bạn"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rung khi nhấn phím"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Âm thanh khi nhấn phím"</string>
-    <string name="popup_on_keypress" msgid="123894815723512944">"Cửa sổ bật lên khi nhấn phím"</string>
+    <string name="popup_on_keypress" msgid="123894815723512944">"Bật lên khi nhấn phím"</string>
     <string name="settings_screen_preferences" msgid="2696713156722014624">"Tùy chọn"</string>
     <string name="settings_screen_accounts" msgid="7570397912370223287">"Tài khoản và bảo mật"</string>
     <string name="settings_screen_appearance" msgid="9153102634339912029">"Giao diện và bố cục"</string>
@@ -48,8 +48,8 @@
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Sử dụng tên từ Danh bạ cho các đề xuất và chỉnh sửa"</string>
     <string name="use_personalized_dicts" msgid="5167396352105467626">"Đề xuất được cá nhân hóa"</string>
     <string name="enable_metrics_logging" msgid="5506372337118822837">"Cải thiện <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <string name="use_double_space_period" msgid="8781529969425082860">"Dấu cách đôi"</string>
-    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Nhấn đúp vào phím cách sẽ chèn thêm một dấu sau dấu cách"</string>
+    <string name="use_double_space_period" msgid="8781529969425082860">"Nhấn đúp phím cách chèn dấu chấm câu"</string>
+    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Nhấn đúp phím cách sẽ chèn thêm một dấu chấm câu, theo sau là dấu cách"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Tự động viết hoa"</string>
     <string name="auto_cap_summary" msgid="7934452761022946874">"Viết hoa chữ đầu tiên của mỗi câu"</string>
     <string name="edit_personal_dictionary" msgid="3996910038952940420">"Từ điển cá nhân"</string>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index be35d13..bf36337 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -43,15 +43,18 @@
     </declare-styleable>
 
     <declare-styleable name="KeyboardView">
-        <!-- Background image for the key. This image needs to be a {@link StateListDrawable},
-             with the following possible states: normal, pressed, checkable, checkable+pressed,
-             checkable+checked, checkable+checked+pressed. -->
+        <!-- Background image for the key. This image needs to be a
+            {@link android.graphics.drawable.StateListDrawable}, with the following possible states:
+             normal, pressed, checkable, checkable+pressed, checkable+checked,
+             checkable+checked+pressed. -->
         <attr name="keyBackground" format="reference" />
         <!-- Background image for the functional key. This image needs to be a
-             {@link StateListDrawable}, with the following possible states: normal, pressed. -->
+             {@link android.graphics.drawable.StateListDrawable}, with the following possible
+             states: normal, pressed. -->
         <attr name="functionalKeyBackground" format="reference" />
         <!-- Background image for the spacebar.  This image needs to be a
-             {@link StateListDrawable}, with the following possible states: normal, pressed. -->
+             {@link android.graphics.drawable.StateListDrawable}, with the following possible
+             states: normal, pressed. -->
         <attr name="spacebarBackground" format="reference" />
         <attr name="spacebarIconWidthRatio" format="float" />
         <!-- Right padding of hint letter to the edge of the key.-->
@@ -200,7 +203,8 @@
 
     <declare-styleable name="SuggestionStripView">
         <attr name="suggestionStripOptions" format="integer">
-            <!-- This should be aligned with SuggestionStripLayoutHelper.AUTO_CORRECT_* and etc. -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.latin.suggestions.SuggestionStripLayoutHelper.AUTO_CORRECT_BOLD} etc. -->
             <flag name="autoCorrectBold" value="0x01" />
             <flag name="autoCorrectUnderline" value="0x02" />
             <flag name="validTypedWordBold" value="0x04" />
@@ -218,7 +222,8 @@
 
     <declare-styleable name="Keyboard">
         <attr name="themeId" format="enum">
-            <!-- This should be aligned with KeyboardTheme.THEME_ID_*. -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.keyboard.KeyboardTheme#THEME_ID_ICS} etc. -->
             <enum name="ICS" value="0" />
             <enum name="KLP" value="2" />
             <enum name="LXXLight" value="3" />
@@ -240,8 +245,8 @@
         <attr name="verticalGap" format="fraction" />
         <!-- More keys keyboard layout template -->
         <attr name="moreKeysTemplate" format="reference" />
-        <!-- Icon set for key top and key preview.
-             These should be aligned with KeyboardIconsSet.NAMES_AND_ATTR_IDS[] -->
+        <!-- Icon set for key top and key preview. These should be aligned with
+             {@link com.android.inputmethod.keyboard.internal.KeyboardIconsSet#NAMES_AND_ATTR_IDS} -->
         <attr name="iconShiftKey" format="reference" />
         <attr name="iconDeleteKey" format="reference" />
         <attr name="iconSettingsKey" format="reference" />
@@ -287,7 +292,8 @@
         <!-- Maximum column of more keys keyboard -->
         <attr name="maxMoreKeysColumn" format="integer" />
         <attr name="backgroundType" format="enum">
-            <!-- This should be aligned with Key.BACKGROUND_TYPE_* -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.keyboard.Key#BACKGROUND_TYPE_NORMAL} etc. -->
             <enum name="empty" value="0" />
             <enum name="normal" value="1" />
             <enum name="functional" value="2" />
@@ -298,7 +304,8 @@
         </attr>
         <!-- The key action flags. -->
         <attr name="keyActionFlags" format="integer">
-            <!-- This should be aligned with Key.ACTION_FLAGS_* -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.keyboard.Key#ACTION_FLAGS_IS_REPEATABLE} etc. -->
             <flag name="isRepeatable" value="0x01" />
             <flag name="noKeyPreview" value="0x02" />
             <flag name="altCodeWhileTyping" value="0x04" />
@@ -312,7 +319,8 @@
         <attr name="keyHintLabelVerticalAdjustment" format="fraction" />
         <!-- The key label flags. -->
         <attr name="keyLabelFlags" format="integer">
-            <!-- This should be aligned with Key.LABEL_FLAGS__* -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.keyboard.Key#LABEL_FLAGS_FONT_NORMAL} etc. -->
             <flag name="alignHintLabelToBottom" value="0x02" />
             <flag name="alignIconToBottom" value="0x04" />
             <flag name="alignLabelOffCenter" value="0x08" />
@@ -357,7 +365,8 @@
         <!-- Width of the key, in the proportion of keyboard width.
              If the value is fillRight, the actual key width will be determined to fill out the
              area up to the right edge of the keyboard. -->
-        <!-- This should be aligned with KeyboardBuilder.Row.KEYWIDTH_* -->
+        <!-- This should be aligned with
+             {@link com.android.inputmethod.keyboard.internal.KeyboardRow#KEYWIDTH_FILL_RIGHT}. -->
         <attr name="keyWidth" format="fraction|enum">
             <enum name="fillRight" value="-1" />
         </attr>
@@ -368,7 +377,7 @@
 
         <!-- Key top visual attributes -->
         <attr name="keyTypeface" format="enum">
-            <!-- This should be aligned with Typeface.NORMAL etc. -->
+            <!-- This should be aligned with {@link android.graphics.Typeface#NORMAL} etc. -->
             <enum name="normal" value="0" />
             <enum name="bold" value="1" />
             <enum name="italic" value="2" />
@@ -391,11 +400,11 @@
         <attr name="keyShiftedLetterHintRatio" format="fraction" />
         <!-- The label's horizontal offset to the center of the key. Negative is to left and
              positive is to right. The value is in proportion of the width of
-             TypefaceUtils.KEY_LABEL_REFERENCE_CHAR. -->
+             {@link com.android.inputmethod.latin.utils.TypefaceUtils#KEY_LABEL_REFERENCE_CHAR}. -->
         <attr name="keyLabelOffCenterRatio" format="fraction" />
         <!-- The hint label's horizontal offset to the center of the key. Negative is to left and
              positive is to right. The value is in proportion of the width of
-             TypefaceUtils.KEY_LABEL_REFERENCE_CHAR. -->
+             {@link com.android.inputmethod.latin.utils.TypefaceUtils#KEY_LABEL_REFERENCE_CHAR}. -->
         <attr name="keyHintLabelOffCenterRatio" format="fraction" />
         <!-- Color to use for the label in a key. -->
         <attr name="keyTextColor" format="color" />
@@ -425,7 +434,8 @@
 
     <declare-styleable name="Keyboard_Case">
         <attr name="keyboardLayoutSet" format="string" />
-        <!-- This should be aligned with KeyboardLayoutSet_Element's elementName. -->
+        <!-- This should be aligned with
+             {@link com.android.inputmethod.keyboard.KeyboardId#ELEMENT_ALPHABET} etc. -->
         <attr name="keyboardLayoutSetElement" format="enum|string">
             <enum name="alphabet" value="0" />
             <enum name="alphabetManualShifted" value="1" />
@@ -445,14 +455,16 @@
             <enum name="emojiCategory5" value="15" />
             <enum name="emojiCategory6" value="16" />
         </attr>
-        <!-- This should be aligned with Keyboard.themeId and KeyboardTheme.THEME_ID_* -->
+        <!-- This should be aligned with Keyboard.themeId and
+             {@link com.android.inputmethod.keyboard.KeyboardTheme#THEME_ID_ICS} etc. -->
         <attr name="keyboardTheme" format="enum|string">
             <enum name="ICS" value="0" />
             <enum name="KLP" value="2" />
             <enum name="LXXLight" value="3" />
             <enum name="LXXDark" value="4" />
         </attr>
-        <!-- This should be aligned with KeyboardId.MODE_* -->
+        <!-- This should be aligned with
+             {@link com.android.inputmethod.keyboard.KeyboardId#MODE_TEXT} etc. -->
         <attr name="mode" format="enum|string">
             <enum name="text" value="0" />
             <enum name="url" value="1" />
@@ -469,7 +481,8 @@
         <attr name="languageSwitchKeyEnabled" format="boolean" />
         <attr name="isMultiLine" format="boolean" />
         <attr name="imeAction" format="enum">
-            <!-- This should be aligned with EditorInfo.IME_ACTION_* -->
+            <!-- This should be aligned with
+                 {@link android.view.inputmethod.EditorInfo#IME_ACTION_GO} etc. -->
             <enum name="actionUnspecified" value="0" />
             <enum name="actionNone" value="1" />
             <enum name="actionGo" value="2" />
@@ -478,7 +491,8 @@
             <enum name="actionNext" value="5" />
             <enum name="actionDone" value="6" />
             <enum name="actionPrevious" value="7" />
-            <!--  This should be aligned with KeyboardId.IME_ACTION_* -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.latin.utils.InputTypeUtils#IME_ACTION_CUSTOM_LABEL}. -->
             <enum name="actionCustomLabel" value="0x100" />
         </attr>
         <attr name="isIconDefined" format="string" />
@@ -495,7 +509,8 @@
     </declare-styleable>
 
     <declare-styleable name="KeyboardLayoutSet_Element">
-        <!-- This should be aligned with KeyboardId.ELEMENT_* -->
+        <!-- This should be aligned with
+             {@link com.android.inputmethod.keyboard.KeyboardId#ELEMENT_ALPHABET} etc. -->
         <attr name="elementName" format="enum">
             <enum name="alphabet" value="0" />
             <enum name="alphabetManualShifted" value="1" />
@@ -525,7 +540,8 @@
     </declare-styleable>
 
     <declare-styleable name="KeyboardLayoutSet_Feature">
-        <!-- This should be aligned with ScriptUtils.SCRIPT_* -->
+        <!-- This should be aligned with
+             {@link com.android.inputmethod.latin.utils.ScriptUtils#SCRIPT_ARABIC} etc. -->
         <attr name="supportedScript" format="enum">
             <enum name="arabic" value="0" />
             <enum name="armenian" value="1" />
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 959fe83..817bb51 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -19,7 +19,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- For backward compatibility.
-         See {@link SettingsValues#needsToShowVoiceInputKey(SharedPreferences,Resources)} -->
+         @see com.android.inputmethod.latin.settings.SettingsValues#needsToShowVoiceInputKey(android.content.SharedPreferences,android.content.res.Resources) -->
     <string name="voice_mode_main">0</string>
 
     <!-- Subtype locale display name exceptions.
diff --git a/java/res/values/keyboard-themes.xml b/java/res/values/keyboard-themes.xml
index b0bae96..26b2582 100644
--- a/java/res/values/keyboard-themes.xml
+++ b/java/res/values/keyboard-themes.xml
@@ -25,7 +25,8 @@
         <item>@string/keyboard_theme_holo_white</item>
         <item>@string/keyboard_theme_holo_blue</item>
     </string-array>
-    <!-- An element must be a keyboard theme id of {@link KeyboardTheme#THEME_ID_*}. -->
+    <!-- An element must be a keyboard theme id of
+         {@link com.android.inputmethod.keyboard.KeyboardTheme#THEME_ID_ICS} etc. -->
     <integer-array name="keyboard_theme_ids" translatable="false">
         <item>3</item>
         <item>4</item>
diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml
index f7cb10f..2f768de 100644
--- a/java/res/values/themes-common.xml
+++ b/java/res/values/themes-common.xml
@@ -105,8 +105,10 @@
     <style
         name="MainKeyboardView"
         parent="KeyboardView" />
-    <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
+    <!-- Though {@link com.android.inputmethod.keyboard.emoji.EmojiPalettesView} doesn't extend
+         {@link com.android.inputmethod.keyboard.KeyboardView}, some views inside it, for instance
+         delete button, need themed {@link com.android.inputmethod.keyboard.KeyboardView}
+         attributes. -->
     <style name="EmojiPalettesView" />
     <style name="MoreKeysKeyboard" />
     <style name="MoreKeysKeyboardView" />
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index ecf40e4..26ebd2f 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -73,8 +73,10 @@
         <item name="languageOnSpacebarTextShadowRadius">1.0</item>
         <item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
     </style>
-    <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
+    <!-- Though {@link com.android.inputmethod.keyboard.emoji.EmojiPalettesView} doesn't extend
+         {@link com.android.inputmethod.keyboard.KeyboardView}, some views inside it, for instance
+         delete button, need themed {@link com.android.inputmethod.keyboard.KeyboardView}
+         attributes. -->
     <style
         name="EmojiPalettesView.ICS"
         parent="MainKeyboardView.ICS"
diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml
index de1cd9b..c8e11a9 100644
--- a/java/res/values/themes-klp.xml
+++ b/java/res/values/themes-klp.xml
@@ -73,8 +73,10 @@
         <item name="languageOnSpacebarTextShadowRadius">1.0</item>
         <item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
     </style>
-    <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
+    <!-- Though {@link com.android.inputmethod.keyboard.emoji.EmojiPalettesView} doesn't extend
+         {@link com.android.inputmethod.keyboard.KeyboardView}, some views inside it, for instance
+         delete button, need themed {@link com.android.inputmethod.keyboard.KeyboardView}
+         attributes. -->
     <style
         name="EmojiPalettesView.KLP"
         parent="MainKeyboardView.KLP"
diff --git a/java/res/values/themes-lxx-dark.xml b/java/res/values/themes-lxx-dark.xml
index b081772..0535064 100644
--- a/java/res/values/themes-lxx-dark.xml
+++ b/java/res/values/themes-lxx-dark.xml
@@ -73,8 +73,10 @@
         <!-- A negative value to disable text shadow layer. -->
         <item name="languageOnSpacebarTextShadowRadius">-1.0</item>
     </style>
-    <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
+    <!-- Though {@link com.android.inputmethod.keyboard.emoji.EmojiPalettesView} doesn't extend
+         {@link com.android.inputmethod.keyboard.KeyboardView}, some views inside it, for instance
+         delete button, need themed {@link com.android.inputmethod.keyboard.KeyboardView}
+         attributes. -->
     <style
         name="EmojiPalettesView.LXX_Dark"
         parent="MainKeyboardView.LXX_Dark"
diff --git a/java/res/values/themes-lxx-light.xml b/java/res/values/themes-lxx-light.xml
index 3d294e4..80e88b8 100644
--- a/java/res/values/themes-lxx-light.xml
+++ b/java/res/values/themes-lxx-light.xml
@@ -73,8 +73,10 @@
         <!-- A negative value to disable text shadow layer. -->
         <item name="languageOnSpacebarTextShadowRadius">-1.0</item>
     </style>
-    <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
+    <!-- Though {@link com.android.inputmethod.keyboard.emoji.EmojiPalettesView} doesn't extend
+         {@link com.android.inputmethod.keyboard.KeyboardView}, some views inside it, for instance
+         delete button, need themed {@link com.android.inputmethod.keyboard.KeyboardView}
+         attributes. -->
     <style
         name="EmojiPalettesView.LXX_Light"
         parent="MainKeyboardView.LXX_Light"
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 77a46f9..5f05e8b 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -28,7 +28,7 @@
     be_BY: Belarusian (Belarus)/east_slavic
     bg: Bulgarian/bulgarian
     bg: Bulgarian/bulgarian_bds
-    (bn_BD: Bengali (Bangladesh)/bengali_akkhor) # This is a preliminary keyboard layout.
+    bn_BD: Bengali (Bangladesh)/bengali_akkhor # This is a preliminary keyboard layout.
     bn_IN: Bengali (India)/bengali
     ca: Catalan/spanish
     cs: Czech/qwertz
@@ -53,7 +53,7 @@
     gl_ES: Galician (Spain)/spanish
     hi: Hindi/hindi
     hi: Hindi/hindi_compact
-    (hi_ZZ: Hinglish/qwerty)  # This is a preliminary keyboard layout.
+    hi_ZZ: Hinglish/qwerty  # This is a preliminary keyboard layout.
     hr: Croatian/qwertz
     hu: Hungarian/qwertz
     hy_AM: Armenian (Armenia) Phonetic/armenian_phonetic
@@ -75,7 +75,7 @@
     mn_MN: Mongolian (Mongolia)/mongolian
     mr_IN: Marathi (India)/marathi
     ms_MY: Malay (Malaysia)/qwerty
-    (my_MM: Myanmar (Myanmar)/myanmar) # This is a preliminary keyboard layout.
+    my_MM: Myanmar (Myanmar)/myanmar # This is a preliminary keyboard layout.
     nb: Norwegian Bokmål/nordic
     ne_NP: Nepali (Nepal) Romanized/nepali_romanized
     ne_NP: Nepali (Nepal) Traditional/nepali_traditional
@@ -86,22 +86,22 @@
     pt_PT: Portuguese (Portugal)/qwerty
     ro: Romanian/qwerty
     ru: Russian/east_slavic
-    (si_LK: Sinhala (Sri Lanka)/sinhala) # This is a preliminary keyboard layout.
+    si_LK: Sinhala (Sri Lanka)/sinhala # This is a preliminary keyboard layout.
     sk: Slovak/qwerty
     sl: Slovenian/qwerty
     sr: Serbian/south_slavic
-    (sr_ZZ: Serbian (Latin)/serbian_qwertz) # This is a preliminary keyboard layout.
+    sr_ZZ: Serbian (Latin)/serbian_qwertz # This is a preliminary keyboard layout.
     sv: Swedish/nordic
     sw: Swahili/qwerty
     ta_IN: Tamil (India)/tamil
-    (ta_LK: Tamil (Sri Lanka)/tamil) # Disabled in conjunction with si_LK.
+    ta_LK: Tamil (Sri Lanka)/tamil # Disabled in conjunction with si_LK.
     ta_SG: Tamil (Singapore)/tamil
     te_IN: Telugu (India)/telugu
     th: Thai/thai
     tl: Tagalog/spanish
     tr: Turkish/qwerty
     uk: Ukrainian/east_slavic
-    (uz_UZ: Uzbek (Uzbekistan)/uzbek) # This is a preliminary keyboard layout.
+    uz_UZ: Uzbek (Uzbekistan)/uzbek # This is a preliminary keyboard layout.
     vi: Vietnamese/qwerty
     zu: Zulu/qwerty
     zz: QWERTY/qwerty
@@ -183,7 +183,6 @@
     />
     <!-- TODO: This Bengali (Bangladesh) keyboard is a preliminary layout.
                This isn't based on the final specification. -->
-    <!--
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0xa2144b0c"
@@ -192,7 +191,6 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=bengali_akkhor,EmojiCapable"
             android:isAsciiCapable="false"
     />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0xbff5986c"
@@ -371,7 +369,6 @@
     />
     <!-- TODO: This Hinglish keyboard is a preliminary layout.
                This isn't based on the final specification. -->
-    <!--
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_hi_ZZ"
             android:subtypeId="0x352eb37c"
@@ -380,7 +377,6 @@
             android:imeSubtypeExtraValue="AsciiCapable,KeyboardLayoutSet=qwerty,EmojiCapable"
             android:isAsciiCapable="true"
     />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x35b7526a"
@@ -553,7 +549,6 @@
     />
     <!-- TODO: This Myanmar keyboard is a preliminary layout.
                This isn't based on the final specification. -->
-    <!--
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0xea266ea4"
@@ -562,7 +557,6 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=myanmar,EmojiCapable,CombiningRules=MyanmarReordering"
             android:isAsciiCapable="false"
     />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x3f12ee14"
@@ -645,7 +639,6 @@
     />
     <!-- TODO: This Sinhala keyboard is a preliminary layout.
                This isn't based on the final specification. -->
-    <!--
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x5c6b3bde"
@@ -654,7 +647,6 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=sinhala,EmojiCapable"
             android:isAsciiCapable="false"
     />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x8e94d413"
@@ -681,7 +673,6 @@
     />
     <!-- TODO: This Serbian Latin keyboard is a preliminary layout.
                This isn't based on the final specification. -->
-    <!--
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_sr_ZZ"
             android:subtypeId="0xf4a5569c"
@@ -690,7 +681,6 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=serbian_qwertz,AsciiCapable,EmojiCapable"
             android:isAsciiCapable="true"
     />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x48b4ff43"
@@ -716,7 +706,6 @@
             android:isAsciiCapable="false"
     />
     <!-- TODO: Enabling/Disabling ta_LK subtype must be aligned with si_LK subtype. -->
-    <!--
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x6ca12d84"
@@ -725,7 +714,6 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=tamil,EmojiCapable"
             android:isAsciiCapable="false"
     />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x785abbd9"
@@ -776,7 +764,6 @@
     />
     <!-- TODO: This Uzbek keyboard is a preliminary layout.
                This isn't based on the final specification. -->
-    <!--
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0xad5cf7f6"
@@ -785,7 +772,6 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=uzbek,AsciiCapable,EmojiCapable"
             android:isAsciiCapable="true"
     />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x93972eee"
diff --git a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
index 380f8d9..01a9e67 100644
--- a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
@@ -82,10 +82,12 @@
         throw new UnsupportedOperationException("not supported.");
     }
 
+    @SuppressWarnings("unused")
     public RectF getCharacterBounds(final int index) {
         throw new UnsupportedOperationException("not supported.");
     }
 
+    @SuppressWarnings("unused")
     public int getCharacterBoundsFlags(final int index) {
         throw new UnsupportedOperationException("not supported.");
     }
diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
index b9a5367..9e842e7 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
@@ -52,6 +52,7 @@
         // This utility class is not publicly instantiable.
     }
 
+    @SuppressWarnings("deprecation")
     public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale,
             String mode, String extraValue, boolean isAuxiliary,
             boolean overridesImplicitlyEnabledSubtype, int id) {
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java
index 4366348..284032b 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java
@@ -18,7 +18,9 @@
 
 import com.android.inputmethod.latin.utils.FragmentUtils;
 
+import android.annotation.TargetApi;
 import android.content.Intent;
+import android.os.Build;
 import android.os.Bundle;
 import android.preference.PreferenceActivity;
 
@@ -44,8 +46,8 @@
         return modIntent;
     }
 
-    // TODO: Uncomment the override annotation once we start using SDK version 19.
-    // @Override
+    @TargetApi(Build.VERSION_CODES.KITKAT)
+    @Override
     public boolean isValidFragment(String fragmentName) {
         return FragmentUtils.isValidFragment(fragmentName);
     }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java b/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java
index d3c0a91..f1633ff 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java
@@ -24,6 +24,7 @@
 import android.widget.Button;
 import android.widget.TextView;
 
+import com.android.inputmethod.annotations.ExternallyReferenced;
 import com.android.inputmethod.latin.R;
 
 import java.util.Locale;
@@ -63,11 +64,19 @@
         allowButton.setText(String.format(allowButtonFormat, ((float)size)/(1024*1024)));
     }
 
+    // This method is externally referenced from layout/download_over_metered.xml using onClick
+    // attribute of Button.
+    @ExternallyReferenced
+    @SuppressWarnings("unused")
     public void onClickDeny(final View v) {
         UpdateHandler.setDownloadOverMeteredSetting(this, false);
         finish();
     }
 
+    // This method is externally referenced from layout/download_over_metered.xml using onClick
+    // attribute of Button.
+    @ExternallyReferenced
+    @SuppressWarnings("unused")
     public void onClickAllow(final View v) {
         UpdateHandler.setDownloadOverMeteredSetting(this, true);
         UpdateHandler.installIfNeverRequested(this, mClientId, mWordListToDownload,
diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java
index 2d2731f..b5863ed 100644
--- a/java/src/com/android/inputmethod/event/CombinerChain.java
+++ b/java/src/com/android/inputmethod/event/CombinerChain.java
@@ -97,7 +97,8 @@
      *   new event. However it may never be null.
      */
     @Nonnull
-    public Event processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
+    public Event processEvent(final ArrayList<Event> previousEvents,
+            @Nonnull final Event newEvent) {
         final ArrayList<Event> modifiablePreviousEvents = new ArrayList<>(previousEvents);
         Event event = newEvent;
         for (final Combiner combiner : mCombiners) {
diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
index 2e65a08..9d7cc05 100644
--- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
+++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
@@ -217,11 +217,8 @@
 
     @Nonnull
     private static Event createEventChainFromSequence(final @Nonnull CharSequence text,
-            final Event originalEvent) {
-        if (text.length() <= 0) {
-            return originalEvent;
-        }
-        Event lastEvent = null;
+            @Nonnull final Event originalEvent) {
+        Event lastEvent = originalEvent;
         int codePoint = 0;
         for (int i = text.length(); i > 0; i -= Character.charCount(codePoint)) {
             codePoint = Character.codePointBefore(text, i);
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index 3e3ff77..0e6d733 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -223,6 +223,7 @@
      * Creates an input event representing the manual pick of a punctuation suggestion.
      * @return an event for this suggestion pick.
      */
+    @Nonnull
     public static Event createPunctuationSuggestionPickedEvent(
             final SuggestedWordInfo suggestedWordInfo) {
         final int primaryCode = suggestedWordInfo.mWord.charAt(0);
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecorator.java b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
index 79e2206..892d367 100644
--- a/java/src/com/android/inputmethod/keyboard/TextDecorator.java
+++ b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
@@ -74,7 +74,7 @@
         void onClickComposingTextToAddToDictionary(final String word);
     }
 
-    public TextDecorator(final Listener listener) {
+    public TextDecorator(@Nullable final Listener listener) {
         mListener = (listener != null) ? listener : EMPTY_LISTENER;
     }
 
@@ -83,7 +83,7 @@
      * delegated to the associated UI operator.
      * @param uiOperator the UI operator to be associated.
      */
-    public void setUiOperator(final TextDecoratorUiOperator uiOperator) {
+    public void setUiOperator(@Nonnull final TextDecoratorUiOperator uiOperator) {
         mUiOperator.disposeUi();
         mUiOperator = uiOperator;
         mUiOperator.setOnClickListener(getOnClickHandler());
@@ -347,12 +347,14 @@
         }
     }
 
+    @Nonnull
     private final static Listener EMPTY_LISTENER = new Listener() {
         @Override
         public void onClickComposingTextToAddToDictionary(final String word) {
         }
     };
 
+    @Nonnull
     private final static TextDecoratorUiOperator EMPTY_UI_OPERATOR = new TextDecoratorUiOperator() {
         @Override
         public void disposeUi() {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
index a194f3d..755a99a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
@@ -19,6 +19,7 @@
 import android.graphics.Canvas;
 import android.view.View;
 
+import com.android.inputmethod.keyboard.MainKeyboardView;
 import com.android.inputmethod.keyboard.PointerTracker;
 
 /**
@@ -51,11 +52,11 @@
     }
 
     /**
-     * Set {@link MainKeyboardView} geometry and position in the {@link SoftInputWindow}.
+     * Set {@link MainKeyboardView} geometry and position in the window of input method.
      * The class that is overriding this method must call this super implementation.
      *
      * @param originCoords the top-left coordinates of the {@link MainKeyboardView} in
-     *        {@link SoftInputWindow} coordinate-system. This is unused but has a point in an
+     *        the input method window coordinate-system. This is unused but has a point in an
      *        extended class, such as {@link GestureTrailsDrawingPreview}.
      * @param width the width of {@link MainKeyboardView}.
      * @param height the height of {@link MainKeyboardView}.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index f581822..6277107 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -47,6 +47,8 @@
 import java.util.Arrays;
 import java.util.Locale;
 
+import javax.annotation.Nonnull;
+
 /**
  * Keyboard Building helper.
  *
@@ -859,7 +861,7 @@
         mTopEdge = false;
     }
 
-    private void endKey(final Key key) {
+    private void endKey(@Nonnull final Key key) {
         mParams.onAddKey(key);
         if (mLeftEdge) {
             key.markAsLeftEdge(mParams);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
index eed3cb6..81d4b8e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
@@ -31,6 +31,8 @@
 import java.util.HashSet;
 import java.util.Locale;
 
+import javax.annotation.Nonnull;
+
 /**
  * The more key specification object. The more keys are an array of {@link MoreKeySpec}.
  *
@@ -70,6 +72,7 @@
         mIconId = KeySpecParser.getIconId(moreKeySpec);
     }
 
+    @Nonnull
     public Key buildKey(final int x, final int y, final int labelFlags,
             final KeyboardParams params) {
         return new Key(mLabel, mIconId, mCode, mOutputText, null /* hintLabel */, labelFlags,
diff --git a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
index a2ebc9c..d8f0114 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
@@ -80,7 +80,7 @@
         return mRadii.length;
     }
 
-    @SuppressWarnings("static-method")
+    @SuppressWarnings({ "static-method", "unused" })
     public float getX(final int row) {
         return 0.0f;
         // Touch position correction data for X coordinate is obsolete.
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index d8a94e9..dce3217 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -32,8 +32,8 @@
 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
 import com.android.inputmethod.latin.utils.FileUtils;
 import com.android.inputmethod.latin.utils.JniUtils;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
 import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.utils.WordInputEventForPersonalization;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -205,8 +205,8 @@
     private static native boolean updateEntriesForWordWithNgramContextNative(long dict,
             int[][] prevWordCodePointArrays, boolean[] isBeginningOfSentenceArray,
             int[] word, boolean isValidWord, int count, int timestamp);
-    private static native int addMultipleDictionaryEntriesNative(long dict,
-            LanguageModelParam[] languageModelParams, int startIndex);
+    private static native int updateEntriesForInputEventsNative(long dict,
+            WordInputEventForPersonalization[] inputEvents, int startIndex);
     private static native String getPropertyNative(long dict, String query);
     private static native boolean isCorruptedNative(long dict);
     private static native boolean migrateNative(long dict, String dictFilePath,
@@ -351,15 +351,19 @@
 
     @Override
     public int getFrequency(final String word) {
-        if (TextUtils.isEmpty(word)) return NOT_A_PROBABILITY;
-        int[] codePoints = StringUtils.toCodePointArray(word);
+        if (TextUtils.isEmpty(word)) {
+            return NOT_A_PROBABILITY;
+        }
+        final int[] codePoints = StringUtils.toCodePointArray(word);
         return getProbabilityNative(mNativeDict, codePoints);
     }
 
     @Override
     public int getMaxFrequencyOfExactMatches(final String word) {
-        if (TextUtils.isEmpty(word)) return NOT_A_PROBABILITY;
-        int[] codePoints = StringUtils.toCodePointArray(word);
+        if (TextUtils.isEmpty(word)) {
+            return NOT_A_PROBABILITY;
+        }
+        final int[] codePoints = StringUtils.toCodePointArray(word);
         return getMaxProbabilityOfExactMatchesNative(mNativeDict, codePoints);
     }
 
@@ -522,17 +526,19 @@
     }
 
     @UsedForTesting
-    public void addMultipleDictionaryEntries(final LanguageModelParam[] languageModelParams) {
-        if (!isValidDictionary()) return;
-        int processedParamCount = 0;
-        while (processedParamCount < languageModelParams.length) {
+    public void updateEntriesForInputEvents(final WordInputEventForPersonalization[] inputEvents) {
+        if (!isValidDictionary()) {
+            return;
+        }
+        int processedEventCount = 0;
+        while (processedEventCount < inputEvents.length) {
             if (needsToRunGC(true /* mindsBlockByGC */)) {
                 flushWithGC();
             }
-            processedParamCount = addMultipleDictionaryEntriesNative(mNativeDict,
-                    languageModelParams, processedParamCount);
+            processedEventCount = updateEntriesForInputEventsNative(mNativeDict, inputEvents,
+                    processedEventCount);
             mHasUpdated = true;
-            if (processedParamCount <= 0) {
+            if (processedEventCount <= 0) {
                 return;
             }
         }
@@ -550,7 +556,9 @@
 
     // Flush to dict file if the dictionary has been updated.
     public boolean flush() {
-        if (!isValidDictionary()) return false;
+        if (!isValidDictionary()) {
+            return false;
+        }
         if (mHasUpdated) {
             if (!flushNative(mNativeDict, mDictFilePath)) {
                 return false;
@@ -570,7 +578,9 @@
 
     // Run GC and flush to dict file.
     public boolean flushWithGC() {
-        if (!isValidDictionary()) return false;
+        if (!isValidDictionary()) {
+            return false;
+        }
         if (!flushWithGCNative(mNativeDict, mDictFilePath)) {
             return false;
         }
@@ -585,7 +595,9 @@
      * @return whether GC is needed to run or not.
      */
     public boolean needsToRunGC(final boolean mindsBlockByGC) {
-        if (!isValidDictionary()) return false;
+        if (!isValidDictionary()) {
+            return false;
+        }
         return needsToRunGCNative(mNativeDict, mindsBlockByGC);
     }
 
@@ -630,7 +642,9 @@
 
     @UsedForTesting
     public String getPropertyForGettingStats(final String query) {
-        if (!isValidDictionary()) return "";
+        if (!isValidDictionary()) {
+            return "";
+        }
         return getPropertyNative(mNativeDict, query);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 974fb14..1570bda 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -223,7 +223,7 @@
     // ## HACK ## we prevent usage of a dictionary before version 18. The reason for this is, since
     // those do not include whitelist entries, the new code with an old version of the dictionary
     // would lose whitelist functionality.
-    private static boolean hackCanUseDictionaryFile(final Locale locale, final File file) {
+    private static boolean hackCanUseDictionaryFile(final File file) {
         try {
             // Read the version of the file
             final DictionaryHeader header = BinaryDictionaryUtils.getHeader(file);
@@ -275,7 +275,7 @@
         // cachedWordLists may not be null, see doc for getCachedDictionaryList
         for (final File f : cachedWordLists) {
             final String wordListId = DictionaryInfoUtils.getWordListIdFromFileName(f.getName());
-            final boolean canUse = f.canRead() && hackCanUseDictionaryFile(locale, f);
+            final boolean canUse = f.canRead() && hackCanUseDictionaryFile(f);
             if (canUse && DictionaryInfoUtils.isMainWordListId(wordListId)) {
                 foundMainDict = true;
             }
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 19f4adc..fcdcfee 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -28,7 +28,7 @@
 import android.provider.ContactsContract.Contacts;
 import android.util.Log;
 
-import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.annotations.ExternallyReferenced;
 import com.android.inputmethod.latin.personalization.AccountUtils;
 import com.android.inputmethod.latin.utils.ExecutorUtils;
 import com.android.inputmethod.latin.utils.StringUtils;
@@ -82,7 +82,8 @@
         reloadDictionaryIfRequired();
     }
 
-    @UsedForTesting
+    // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
+    @ExternallyReferenced
     public static ContactsBinaryDictionary getDictionary(final Context context, final Locale locale,
             final File dictFile, final String dictNamePrefix) {
         return new ContactsBinaryDictionary(context, locale, dictFile, dictNamePrefix + NAME);
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index d8f1b2a..28a62b2 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -120,10 +120,18 @@
      */
     abstract public boolean isInDictionary(final String word);
 
+    /**
+     * Get the frequency of the word.
+     * @param word the word to get the frequency of.
+     */
     public int getFrequency(final String word) {
         return NOT_A_PROBABILITY;
     }
 
+    /**
+     * Get the maximum frequency of the word.
+     * @param word the word to get the maximum frequency of.
+     */
     public int getMaxFrequencyOfExactMatches(final String word) {
         return NOT_A_PROBABILITY;
     }
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index 7a17dcc..5bf6bf4 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -24,7 +24,7 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.keyboard.ProximityInfo;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback;
+import com.android.inputmethod.latin.ExpandableBinaryDictionary.UpdateEntriesForInputEventsCallback;
 import com.android.inputmethod.latin.NgramContext.WordInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.personalization.ContextualDictionary;
@@ -53,6 +53,9 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 // TODO: Consolidate dictionaries in native code.
 public class DictionaryFacilitator {
     public static final String TAG = DictionaryFacilitator.class.getSimpleName();
@@ -274,6 +277,7 @@
         mMostProbableDictionaryGroup = newMostProbableDictionaryGroup;
     }
 
+    @Nullable
     private static ExpandableBinaryDictionary getSubDict(final String dictType,
             final Context context, final Locale locale, final File dictFile,
             final String dictNamePrefix) {
@@ -303,6 +307,7 @@
                 usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */);
     }
 
+    @Nullable
     static DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups,
             final Locale locale) {
         for (int i = 0; i < dictionaryGroups.length; ++i) {
@@ -317,7 +322,7 @@
             final Locale[] newLocales,
             final boolean useContactsDict, final boolean usePersonalizedDicts,
             final boolean forceReloadMainDictionary,
-            final DictionaryInitializationListener listener,
+            @Nullable final DictionaryInitializationListener listener,
             final String dictNamePrefix) {
         final HashMap<Locale, ArrayList<String>> existingDictsToCleanup = new HashMap<>();
         // TODO: Make subDictTypesToUse configurable by resource or a static final list.
@@ -593,7 +598,7 @@
     }
 
     public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
-            final NgramContext ngramContext, final int timeStampInSeconds,
+            @Nonnull final NgramContext ngramContext, final int timeStampInSeconds,
             final boolean blockPotentiallyOffensive) {
         final DictionaryGroup dictionaryGroup = getDictionaryGroupForMostProbableLanguage();
         final String[] words = suggestion.split(Constants.WORD_SEPARATOR);
@@ -791,8 +796,8 @@
     public void addEntriesToPersonalizationDictionary(
             final PersonalizationDataChunk personalizationDataChunk,
             final SpacingAndPunctuations spacingAndPunctuations,
-            final AddMultipleDictionaryEntriesCallback callback) {
-        mPersonalizationHelper.addEntriesToPersonalizationDictionariesToUpdate(
+            final UpdateEntriesForInputEventsCallback callback) {
+        mPersonalizationHelper.updateEntriesOfPersonalizationDictionaries(
                 getMostProbableLocale(), personalizationDataChunk, spacingAndPunctuations,
                 callback);
     }
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index ff05a2f..a74ffcb 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -32,7 +32,7 @@
 import com.android.inputmethod.latin.utils.DistracterFilter;
 import com.android.inputmethod.latin.utils.ExecutorUtils;
 import com.android.inputmethod.latin.utils.FileUtils;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
+import com.android.inputmethod.latin.utils.WordInputEventForPersonalization;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -53,6 +53,10 @@
  * Abstract base class for an expandable dictionary that can be created and updated dynamically
  * during runtime. When updated it automatically generates a new binary dictionary to handle future
  * queries in native code. This binary dictionary is written to internal storage.
+ *
+ * A class that extends this abstract class must have a static factory method named
+ *   getDictionary(Context context, Locale locale, File dictFile, String dictNamePrefix)
+ * @see DictionaryFacilitator#getSubDict(String,Context,Locale,File,String)
  */
 abstract public class ExpandableBinaryDictionary extends Dictionary {
     private static final boolean DEBUG = false;
@@ -443,16 +447,16 @@
         }, word, distracterFilter);
     }
 
-    public interface AddMultipleDictionaryEntriesCallback {
+    public interface UpdateEntriesForInputEventsCallback {
         public void onFinished();
     }
 
     /**
-     * Dynamically add multiple entries to the dictionary.
+     * Dynamically update entries according to input events.
      */
-    public void addMultipleDictionaryEntriesDynamically(
-            @Nonnull final ArrayList<LanguageModelParam> languageModelParams,
-            final AddMultipleDictionaryEntriesCallback callback) {
+    public void updateEntriesForInputEvents(
+            @Nonnull final ArrayList<WordInputEventForPersonalization> inputEvents,
+            final UpdateEntriesForInputEventsCallback callback) {
         reloadDictionaryIfRequired();
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
@@ -462,9 +466,9 @@
                     if (binaryDictionary == null) {
                         return;
                     }
-                    binaryDictionary.addMultipleDictionaryEntries(
-                            languageModelParams.toArray(
-                                    new LanguageModelParam[languageModelParams.size()]));
+                    binaryDictionary.updateEntriesForInputEvents(
+                            inputEvents.toArray(
+                                    new WordInputEventForPersonalization[inputEvents.size()]));
                 } finally {
                     if (callback != null) {
                         callback.onFinished();
diff --git a/java/src/com/android/inputmethod/latin/InputView.java b/java/src/com/android/inputmethod/latin/InputView.java
index 7fa9354..f3a8ca1 100644
--- a/java/src/com/android/inputmethod/latin/InputView.java
+++ b/java/src/com/android/inputmethod/latin/InputView.java
@@ -139,7 +139,10 @@
             return y - mEventReceivingRect.top;
         }
 
-        // Callback when a {@link MotionEvent} is forwarded.
+        /**
+         * Callback when a {@link MotionEvent} is forwarded.
+         * @param me the motion event to be forwarded.
+         */
         protected void onForwardingEvent(final MotionEvent me) {}
 
         // Returns true if a {@link MotionEvent} is needed to be forwarded to
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index e7a91c5..cd17ada 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1419,7 +1419,7 @@
 
     // This method is public for testability of LatinIME, but also in the future it should
     // completely replace #onCodeInput.
-    public void onEvent(final Event event) {
+    public void onEvent(@Nonnull final Event event) {
         if (Constants.CODE_SHORTCUT == event.mKeyCode) {
             mSubtypeSwitcher.switchToShortcutIME(this);
         }
@@ -1434,6 +1434,7 @@
     // A helper method to split the code point and the key code. Ultimately, they should not be
     // squashed into the same variable, and this method should be removed.
     // public for testing, as we don't want to copy the same logic into test code
+    @Nonnull
     public static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, final int keyX,
              final int keyY, final boolean isKeyRepeat) {
         final int keyCode;
diff --git a/java/src/com/android/inputmethod/latin/NgramContext.java b/java/src/com/android/inputmethod/latin/NgramContext.java
index 2dc409f..4a3ac0f 100644
--- a/java/src/com/android/inputmethod/latin/NgramContext.java
+++ b/java/src/com/android/inputmethod/latin/NgramContext.java
@@ -23,13 +23,17 @@
 
 import java.util.Arrays;
 
+import javax.annotation.Nonnull;
+
 /**
  * Class to represent information of previous words. This class is used to add n-gram entries
  * into binary dictionaries, to get predictions, and to get suggestions.
  */
 public class NgramContext {
+    @Nonnull
     public static final NgramContext EMPTY_PREV_WORDS_INFO =
             new NgramContext(WordInfo.EMPTY_WORD_INFO);
+    @Nonnull
     public static final NgramContext BEGINNING_OF_SENTENCE =
             new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
 
@@ -37,7 +41,9 @@
      * Word information used to represent previous words information.
      */
     public static class WordInfo {
+        @Nonnull
         public static final WordInfo EMPTY_WORD_INFO = new WordInfo(null);
+        @Nonnull
         public static final WordInfo BEGINNING_OF_SENTENCE_WORD_INFO = new WordInfo();
 
         // This is an empty char sequence when mIsBeginningOfSentence is true.
@@ -97,6 +103,7 @@
     }
 
     // Create next prevWordsInfo using current prevWordsInfo.
+    @Nonnull
     public NgramContext getNextNgramContext(final WordInfo wordInfo) {
         final int nextPrevWordCount = Math.min(Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM,
                 mPrevWordsCount + 1);
diff --git a/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java
index 396d062..2dbab0a 100644
--- a/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java
@@ -26,14 +26,14 @@
 import android.content.Context;
 import android.view.inputmethod.InputMethodSubtype;
 
-import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback;
+import com.android.inputmethod.latin.ExpandableBinaryDictionary.UpdateEntriesForInputEventsCallback;
 import com.android.inputmethod.latin.personalization.PersonalizationDataChunk;
 import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 import com.android.inputmethod.latin.utils.DistracterFilter;
 import com.android.inputmethod.latin.utils.DistracterFilterCheckingIsInDictionary;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+import com.android.inputmethod.latin.utils.WordInputEventForPersonalization;
 
 /**
  * Class for managing and updating personalization dictionaries.
@@ -119,10 +119,10 @@
         return personalizationDict;
     }
 
-    private void addEntriesToPersonalizationDictionariesForLocale(final Locale locale,
+    private void updateEntriesOfPersonalizationDictionariesForLocale(final Locale locale,
             final PersonalizationDataChunk personalizationDataChunk,
             final SpacingAndPunctuations spacingAndPunctuations,
-            final AddMultipleDictionaryEntriesCallback callback) {
+            final UpdateEntriesForInputEventsCallback callback) {
         final ExpandableBinaryDictionary personalizationDict =
                 getPersonalizationDictToUpdate(mContext, locale);
         if (personalizationDict == null) {
@@ -131,25 +131,25 @@
             }
             return;
         }
-        final ArrayList<LanguageModelParam> languageModelParams =
-                LanguageModelParam.createLanguageModelParamsFrom(
+        final ArrayList<WordInputEventForPersonalization> inputEvents =
+                WordInputEventForPersonalization.createInputEventFrom(
                         personalizationDataChunk.mTokens,
                         personalizationDataChunk.mTimestampInSeconds, spacingAndPunctuations,
                         locale, new DistracterFilterCheckingIsInDictionary(
                                 mDistracterFilter, personalizationDict));
-        if (languageModelParams == null || languageModelParams.isEmpty()) {
+        if (inputEvents == null || inputEvents.isEmpty()) {
             if (callback != null) {
                 callback.onFinished();
             }
             return;
         }
-        personalizationDict.addMultipleDictionaryEntriesDynamically(languageModelParams, callback);
+        personalizationDict.updateEntriesForInputEvents(inputEvents, callback);
     }
 
-    public void addEntriesToPersonalizationDictionariesToUpdate(final Locale defaultLocale,
+    public void updateEntriesOfPersonalizationDictionaries(final Locale defaultLocale,
             final PersonalizationDataChunk personalizationDataChunk,
             final SpacingAndPunctuations spacingAndPunctuations,
-            final AddMultipleDictionaryEntriesCallback callback) {
+            final UpdateEntriesForInputEventsCallback callback) {
         final String language = personalizationDataChunk.mDetectedLanguage;
         final HashSet<Locale> locales;
         if (mIsMonolingualUser && PersonalizationDataChunk.LANGUAGE_UNKNOWN.equals(language)
@@ -165,8 +165,8 @@
             return;
         }
         final AtomicInteger remainingTaskCount = new AtomicInteger(locales.size());
-        final AddMultipleDictionaryEntriesCallback callbackForLocales =
-                new AddMultipleDictionaryEntriesCallback() {
+        final UpdateEntriesForInputEventsCallback callbackForLocales =
+                new UpdateEntriesForInputEventsCallback() {
                     @Override
                     public void onFinished() {
                         if (remainingTaskCount.decrementAndGet() == 0) {
@@ -178,7 +178,7 @@
                     }
                 };
         for (final Locale locale : locales) {
-            addEntriesToPersonalizationDictionariesForLocale(locale, personalizationDataChunk,
+            updateEntriesOfPersonalizationDictionariesForLocale(locale, personalizationDataChunk,
                     spacingAndPunctuations, callbackForLocales);
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
index 56014cb..6aacf32 100644
--- a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
@@ -56,7 +56,7 @@
 
     /**
      * {@inheritDoc}
-     * Note that {@link super#getWord(int)} returns a punctuation key specification text.
+     * Note that {@link SuggestedWords#getWord(int)} returns a punctuation key specification text.
      * The suggested punctuation should be gotten by parsing the key specification.
      */
     @Override
@@ -70,7 +70,7 @@
 
     /**
      * {@inheritDoc}
-     * Note that {@link super#getWord(int)} returns a punctuation key specification text.
+     * Note that {@link SuggestedWords#getWord(int)} returns a punctuation key specification text.
      * The displayed text should be gotten by parsing the key specification.
      */
     @Override
@@ -82,7 +82,7 @@
     /**
      * {@inheritDoc}
      * Note that {@link #getWord(int)} returns a suggested punctuation. We should create a
-     * {@link SuggestedWordInfo} object that represents a hard coded word.
+     * {@link SuggestedWords.SuggestedWordInfo} object that represents a hard coded word.
      */
     @Override
     public SuggestedWordInfo getInfo(final int index) {
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 2c17660..69f0b3e 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -44,6 +44,8 @@
 import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.TextRange;
 
+import javax.annotation.Nonnull;
+
 /**
  * Enrichment class for InputConnection to simplify interaction and add functionality.
  *
@@ -365,7 +367,9 @@
         }
         // This never calls InputConnection#getCapsMode - in fact, it's a static method that
         // never blocks or initiates IPC.
-        return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType,
+        // TODO: don't call #toString() here. Instead, all accesses to
+        // mCommittedTextBeforeComposingText should be done on the main thread.
+        return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText.toString(), inputType,
                 spacingAndPunctuations, hasSpaceBefore);
     }
 
@@ -591,6 +595,7 @@
     }
 
     @SuppressWarnings("unused")
+    @Nonnull
     public NgramContext getNgramContextFromNthPreviousWord(
             final SpacingAndPunctuations spacingAndPunctuations, final int n) {
         mIC = mParent.getCurrentInputConnection();
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index 113a204..894c115 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -38,6 +38,8 @@
 import java.util.HashMap;
 import java.util.List;
 
+import javax.annotation.Nonnull;
+
 /**
  * Enrichment class for InputMethodManager to simplify interaction and add functionality.
  */
@@ -301,12 +303,13 @@
         return INDEX_NOT_FOUND;
     }
 
+    @Nonnull
     public InputMethodSubtype getCurrentRawSubtype() {
         return mImmWrapper.mImm.getCurrentInputMethodSubtype();
     }
 
     public RichInputMethodSubtype createCurrentRichInputMethodSubtype(
-            final InputMethodSubtype rawSubtype) {
+            @Nonnull final InputMethodSubtype rawSubtype) {
         return AdditionalFeaturesSettingUtils.createRichInputMethodSubtype(this, rawSubtype,
                 mContext);
     }
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 7944750..abdfdfe 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -44,6 +44,8 @@
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.Nonnull;
+
 public final class SubtypeSwitcher {
     private static boolean DBG = DebugFlags.DEBUG_ENABLED;
     private static final String TAG = SubtypeSwitcher.class.getSimpleName();
@@ -169,7 +171,7 @@
     }
 
     // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
-    public void onSubtypeChanged(final InputMethodSubtype newSubtype) {
+    public void onSubtypeChanged(@Nonnull final InputMethodSubtype newSubtype) {
         final RichInputMethodSubtype richSubtype =
                 mRichImm.createCurrentRichInputMethodSubtype(newSubtype);
         if (DBG) {
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 37dd384..2b7fb17 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -28,7 +28,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.annotations.ExternallyReferenced;
 import com.android.inputmethod.compat.UserDictionaryCompatUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
@@ -101,7 +101,8 @@
         reloadDictionaryIfRequired();
     }
 
-    @UsedForTesting
+    // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
+    @ExternallyReferenced
     public static UserBinaryDictionary getDictionary(final Context context, final Locale locale,
             final File dictFile, final String dictNamePrefix) {
         return new UserBinaryDictionary(context, locale, false /* alsoUseMoreRestrictiveLocales */,
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 6530e6b..8ccaafd 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -182,7 +182,7 @@
      * @return the processed event. Never null, but may be marked as consumed.
      */
     @Nonnull
-    public Event processEvent(final Event event) {
+    public Event processEvent(@Nonnull final Event event) {
         final Event processedEvent = mCombinerChain.processEvent(mEvents, event);
         // The retained state of the combiner chain may have changed while processing the event,
         // so we need to update our cache.
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 359ea12..5cc4a67 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -68,6 +68,8 @@
 import java.util.TreeSet;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
+
 /**
  * This class manages the input logic.
  */
@@ -454,8 +456,8 @@
      *     {@link com.android.inputmethod.keyboard.KeyboardSwitcher#getKeyboardShiftMode()}
      * @return the complete transaction object
      */
-    public InputTransaction onCodeInput(final SettingsValues settingsValues, final Event event,
-            final int keyboardShiftMode,
+    public InputTransaction onCodeInput(final SettingsValues settingsValues,
+            @Nonnull final Event event, final int keyboardShiftMode,
             // TODO: remove these arguments
             final int currentKeyboardScriptId, final LatinIME.UIHandler handler) {
         final Event processedEvent = mWordComposer.processEvent(event);
@@ -1373,7 +1375,7 @@
     }
 
     private void performAdditionToUserHistoryDictionary(final SettingsValues settingsValues,
-            final String suggestion, final NgramContext ngramContext) {
+            final String suggestion, @Nonnull final NgramContext ngramContext) {
         // If correction is not enabled, we don't add words to the user history dictionary.
         // That's to avoid unintended additions in some sensitive fields, or fields that
         // expect to receive non-words.
@@ -2301,7 +2303,7 @@
      * Sets the UI operator for {@link TextDecorator}.
      * @param uiOperator the UI operator which should be associated with {@link TextDecorator}.
      */
-    public void setTextDecoratorUi(final TextDecoratorUiOperator uiOperator) {
+    public void setTextDecoratorUi(@Nonnull final TextDecoratorUiOperator uiOperator) {
         mTextDecorator.setUiOperator(uiOperator);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java b/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java
index 502f72f..df54bf4 100644
--- a/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java
+++ b/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java
@@ -95,7 +95,7 @@
     }
 
     /**
-     * Sets the connect timeout. Defaults to {@value #DEFAULT_TIMEOUT} milliseconds.
+     * Sets the connect timeout. Defaults to {@value #DEFAULT_TIMEOUT_MILLIS} milliseconds.
      *
      * TODO: Remove @UsedForTesting after this method is actually used.
      */
@@ -110,7 +110,7 @@
     }
 
     /**
-     * Sets the read timeout. Defaults to {@value #DEFAULT_TIMEOUT} milliseconds.
+     * Sets the read timeout. Defaults to {@value #DEFAULT_TIMEOUT_MILLIS} milliseconds.
      *
      * TODO: Remove @UsedForTesting after this method is actually used.
      */
diff --git a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
index ac55b93..39d9596 100644
--- a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 
-import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.annotations.ExternallyReferenced;
 import com.android.inputmethod.latin.Dictionary;
 import com.android.inputmethod.latin.ExpandableBinaryDictionary;
 
@@ -36,7 +36,9 @@
         clear();
     }
 
-    @UsedForTesting
+    // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
+    @SuppressWarnings("unused")
+    @ExternallyReferenced
     public static ContextualDictionary getDictionary(final Context context, final Locale locale,
             final File dictFile, final String dictNamePrefix) {
         return new ContextualDictionary(context, locale, dictFile);
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
index f2ad22a..33d1273 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 
-import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.annotations.ExternallyReferenced;
 import com.android.inputmethod.latin.Dictionary;
 
 import java.io.File;
@@ -33,7 +33,9 @@
                 Dictionary.TYPE_PERSONALIZATION, null /* dictFile */);
     }
 
-    @UsedForTesting
+    // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
+    @SuppressWarnings("unused")
+    @ExternallyReferenced
     public static PersonalizationDictionary getDictionary(final Context context,
             final Locale locale, final File dictFile, final String dictNamePrefix) {
         return PersonalizationHelper.getPersonalizationDictionary(context, locale);
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index e777c0b..cf1c7ea 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 
-import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.annotations.ExternallyReferenced;
 import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.Dictionary;
 import com.android.inputmethod.latin.ExpandableBinaryDictionary;
@@ -28,6 +28,8 @@
 import java.io.File;
 import java.util.Locale;
 
+import javax.annotation.Nonnull;
+
 /**
  * Locally gathers stats about the words user types and various other signals like auto-correction
  * cancellation or manual picks. This allows the keyboard to adapt to the typist over time.
@@ -41,7 +43,9 @@
                 Dictionary.TYPE_USER_HISTORY, null /* dictFile */);
     }
 
-    @UsedForTesting
+    // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
+    @SuppressWarnings("unused")
+    @ExternallyReferenced
     public static UserHistoryDictionary getDictionary(final Context context, final Locale locale,
             final File dictFile, final String dictNamePrefix) {
         return PersonalizationHelper.getUserHistoryDictionary(context, locale);
@@ -58,8 +62,8 @@
      * @param distracterFilter the filter to check whether the word is a distracter
      */
     public static void addToDictionary(final ExpandableBinaryDictionary userHistoryDictionary,
-            final NgramContext ngramContext, final String word, final boolean isValid,
-            final int timestamp, final DistracterFilter distracterFilter) {
+            @Nonnull final NgramContext ngramContext, final String word, final boolean isValid,
+            final int timestamp, @Nonnull final DistracterFilter distracterFilter) {
         if (word.length() > Constants.DICTIONARY_MAX_WORD_LENGTH) {
             return;
         }
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index c40ffb6..5e23693 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -40,6 +40,8 @@
 import java.util.Set;
 import java.util.concurrent.locks.ReentrantLock;
 
+import javax.annotation.Nonnull;
+
 public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String TAG = Settings.class.getSimpleName();
     // Settings screens
@@ -175,7 +177,7 @@
     }
 
     public void loadSettings(final Context context, final Locale locale,
-            final InputAttributes inputAttributes) {
+            @Nonnull final InputAttributes inputAttributes) {
         mSettingsValuesLock.lock();
         mContext = context;
         try {
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 5b99652..da8810f 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -37,6 +37,8 @@
 import java.util.Arrays;
 import java.util.Locale;
 
+import javax.annotation.Nonnull;
+
 /**
  * When you call the constructor of this class, you may want to change the current system locale by
  * using {@link com.android.inputmethod.latin.utils.RunInLocale}.
@@ -85,6 +87,7 @@
     public final int mScreenMetrics;
 
     // From the input box
+    @Nonnull
     public final InputAttributes mInputAttributes;
 
     // Deduced settings
@@ -115,7 +118,7 @@
     public final float mKeyPreviewDismissEndYScale;
 
     public SettingsValues(final Context context, final SharedPreferences prefs, final Resources res,
-            final InputAttributes inputAttributes) {
+            @Nonnull final InputAttributes inputAttributes) {
         mLocale = res.getConfiguration().locale;
         // Get the resources
         mDelayInMillisecondsToUpdateOldSuggestions =
@@ -123,12 +126,7 @@
         mSpacingAndPunctuations = new SpacingAndPunctuations(res);
 
         // Store the input attributes
-        if (null == inputAttributes) {
-            mInputAttributes = new InputAttributes(
-                    null, false /* isFullscreenMode */, context.getPackageName());
-        } else {
-            mInputAttributes = inputAttributes;
-        }
+        mInputAttributes = inputAttributes;
 
         // Get the settings preferences
         mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java
index 8393b30..ac395bf 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java
@@ -16,8 +16,10 @@
 
 package com.android.inputmethod.latin.spellcheck;
 
+import android.annotation.TargetApi;
 import android.content.res.Resources;
 import android.os.Binder;
+import android.os.Build;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.textservice.SentenceSuggestionsInfo;
@@ -42,6 +44,7 @@
         mResources = service.getResources();
     }
 
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private SentenceSuggestionsInfo fixWronglyInvalidatedWordWithSingleQuote(TextInfo ti,
             SentenceSuggestionsInfo ssi) {
         final CharSequence typedText = TextInfoCompatUtils.getCharSequenceOrString(ti);
@@ -149,7 +152,7 @@
      * @param textInfos an array of the text metadata
      * @param suggestionsLimit the maximum number of suggestions to be returned
      * @return an array of {@link SentenceSuggestionsInfo} returned by
-     * {@link SpellCheckerService.Session#onGetSuggestions(TextInfo, int)}
+     * {@link android.service.textservice.SpellCheckerService.Session#onGetSuggestions(TextInfo, int)}
      */
     private SentenceSuggestionsInfo[] splitAndSuggest(TextInfo[] textInfos, int suggestionsLimit) {
         if (textInfos == null || textInfos.length == 0) {
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
index df9a761..294666b 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
@@ -18,7 +18,9 @@
 
 import com.android.inputmethod.latin.utils.FragmentUtils;
 
+import android.annotation.TargetApi;
 import android.content.Intent;
+import android.os.Build;
 import android.os.Bundle;
 import android.preference.PreferenceActivity;
 
@@ -41,8 +43,8 @@
         return modIntent;
     }
 
-    // TODO: Uncomment the override annotation once we start using SDK version 19.
-    // @Override
+    @TargetApi(Build.VERSION_CODES.KITKAT)
+    @Override
     public boolean isValidFragment(String fragmentName) {
         return FragmentUtils.isValidFragment(fragmentName);
     }
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
index 624783a..90e4faa 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
@@ -47,12 +47,12 @@
             "android.settings.USER_DICTIONARY_SETTINGS";
 
     @Override
-    public void onCreate(Bundle icicle) {
+    public void onCreate(final Bundle icicle) {
         super.onCreate(icicle);
         setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
     }
 
-    public static TreeSet<String> getUserDictionaryLocalesSet(Activity activity) {
+    public static TreeSet<String> getUserDictionaryLocalesSet(final Activity activity) {
         final Cursor cursor = activity.getContentResolver().query(UserDictionary.Words.CONTENT_URI,
                 new String[] { UserDictionary.Words.LOCALE },
                 null, null, null);
@@ -108,7 +108,7 @@
      * Creates the entries that allow the user to go into the user dictionary for each locale.
      * @param userDictGroup The group to put the settings in.
      */
-    protected void createUserDictSettings(PreferenceGroup userDictGroup) {
+    protected void createUserDictSettings(final PreferenceGroup userDictGroup) {
         final Activity activity = getActivity();
         userDictGroup.removeAll();
         final TreeSet<String> localeSet =
@@ -121,10 +121,10 @@
         }
 
         if (localeSet.isEmpty()) {
-            userDictGroup.addPreference(createUserDictionaryPreference(null, activity));
+            userDictGroup.addPreference(createUserDictionaryPreference(null));
         } else {
             for (String locale : localeSet) {
-                userDictGroup.addPreference(createUserDictionaryPreference(locale, activity));
+                userDictGroup.addPreference(createUserDictionaryPreference(locale));
             }
         }
     }
@@ -134,7 +134,7 @@
      * @param locale The locale for which this user dictionary is for.
      * @return The corresponding preference.
      */
-    protected Preference createUserDictionaryPreference(String locale, Activity activity) {
+    protected Preference createUserDictionaryPreference(final String locale) {
         final Preference newPref = new Preference(getActivity());
         final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION);
         if (null == locale) {
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
index 9d89d57..7274857 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
@@ -186,7 +186,7 @@
 
     private ListAdapter createAdapter() {
         return new MyAdapter(getActivity(), R.layout.user_dictionary_item, mCursor,
-                ADAPTER_FROM, ADAPTER_TO, this);
+                ADAPTER_FROM, ADAPTER_TO);
     }
 
     @Override
@@ -288,7 +288,7 @@
         private ViewBinder mViewBinder = new ViewBinder() {
 
             @Override
-            public boolean setViewValue(View v, Cursor c, int columnIndex) {
+            public boolean setViewValue(final View v, final Cursor c, final int columnIndex) {
                 if (!IS_SHORTCUT_API_SUPPORTED) {
                     // just let SimpleCursorAdapter set the view values
                     return false;
@@ -309,10 +309,9 @@
             }
         };
 
-        @SuppressWarnings("deprecation")
-        public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to,
-                UserDictionarySettings settings) {
-            super(context, layout, c, from, to);
+        public MyAdapter(final Context context, final int layout, final Cursor c,
+                final String[] from, final int[] to) {
+            super(context, layout, c, from, to, 0 /* flags */);
 
             if (null != c) {
                 final String alphabet = context.getString(R.string.user_dict_fast_scroll_alphabet);
@@ -323,12 +322,12 @@
         }
 
         @Override
-        public int getPositionForSection(int section) {
+        public int getPositionForSection(final int section) {
             return null == mIndexer ? 0 : mIndexer.getPositionForSection(section);
         }
 
         @Override
-        public int getSectionForPosition(int position) {
+        public int getSectionForPosition(final int position) {
             return null == mIndexer ? 0 : mIndexer.getSectionForPosition(position);
         }
 
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
index 355d00d..525212c 100644
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
+++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
@@ -16,14 +16,16 @@
 
 package com.android.inputmethod.latin.utils;
 
-import java.util.List;
-import java.util.Locale;
-
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.NgramContext;
 
+import java.util.List;
+import java.util.Locale;
+
+import javax.annotation.Nonnull;
+
 public interface DistracterFilter {
     /**
      * Determine whether a word is a distracter to words in dictionaries.
@@ -68,8 +70,9 @@
         public static boolean shouldBeHandledAsOov(final int handlingType) {
             return (handlingType & SHOULD_BE_HANDLED_AS_OOV) != 0;
         }
-    };
+    }
 
+    @Nonnull
     public static final DistracterFilter EMPTY_DISTRACTER_FILTER = new DistracterFilter() {
         @Override
         public boolean isDistracterToWordsInDictionaries(NgramContext ngramContext,
diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
deleted file mode 100644
index 3e5cb33..0000000
--- a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.latin.utils;
-
-import android.util.Log;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.NgramContext;
-import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
-import com.android.inputmethod.latin.utils.DistracterFilter.HandlingType;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-// Note: this class is used as a parameter type of a native method. You should be careful when you
-// rename this class or field name. See BinaryDictionary#addMultipleDictionaryEntriesNative().
-public final class LanguageModelParam {
-    private static final String TAG = LanguageModelParam.class.getSimpleName();
-    private static final boolean DEBUG = false;
-    private static final boolean DEBUG_TOKEN = false;
-
-    // For now, these probability values are being referred to only when we add new entries to
-    // decaying dynamic binary dictionaries. When these are referred to, what matters is 0 or
-    // non-0. Thus, it's not meaningful to compare 10, 100, and so on.
-    // TODO: Revise the logic in ForgettingCurveUtils in native code.
-    private static final int UNIGRAM_PROBABILITY_FOR_VALID_WORD = 100;
-    private static final int UNIGRAM_PROBABILITY_FOR_OOV_WORD = Dictionary.NOT_A_PROBABILITY;
-    private static final int BIGRAM_PROBABILITY_FOR_VALID_WORD = 10;
-    private static final int BIGRAM_PROBABILITY_FOR_OOV_WORD = Dictionary.NOT_A_PROBABILITY;
-
-    public final CharSequence mTargetWord;
-    public final int[] mWord0;
-    public final int[] mWord1;
-    // TODO: this needs to be a list of shortcuts
-    public final int[] mShortcutTarget;
-    public final int mUnigramProbability;
-    public final int mBigramProbability;
-    public final int mShortcutProbability;
-    public final boolean mIsNotAWord;
-    public final boolean mIsPossiblyOffensive;
-    // Time stamp in seconds.
-    public final int mTimestamp;
-
-    // Constructor for unigram. TODO: support shortcuts
-    @UsedForTesting
-    public LanguageModelParam(final CharSequence word, final int unigramProbability,
-            final int timestamp) {
-        this(null /* word0 */, word, unigramProbability, Dictionary.NOT_A_PROBABILITY, timestamp);
-    }
-
-    // Constructor for unigram and bigram.
-    @UsedForTesting
-    public LanguageModelParam(final CharSequence word0, final CharSequence word1,
-            final int unigramProbability, final int bigramProbability,
-            final int timestamp) {
-        mTargetWord = word1;
-        mWord0 = (word0 == null) ? null : StringUtils.toCodePointArray(word0);
-        mWord1 = StringUtils.toCodePointArray(word1);
-        mShortcutTarget = null;
-        mUnigramProbability = unigramProbability;
-        mBigramProbability = bigramProbability;
-        mShortcutProbability = Dictionary.NOT_A_PROBABILITY;
-        mIsNotAWord = false;
-        mIsPossiblyOffensive = false;
-        mTimestamp = timestamp;
-    }
-
-    // Process a list of words and return a list of {@link LanguageModelParam} objects.
-    public static ArrayList<LanguageModelParam> createLanguageModelParamsFrom(
-            final List<String> tokens, final int timestamp,
-            final SpacingAndPunctuations spacingAndPunctuations, final Locale locale,
-            final DistracterFilter distracterFilter) {
-        final ArrayList<LanguageModelParam> languageModelParams = new ArrayList<>();
-        final int N = tokens.size();
-        NgramContext ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
-        for (int i = 0; i < N; ++i) {
-            final String tempWord = tokens.get(i);
-            if (StringUtils.isEmptyStringOrWhiteSpaces(tempWord)) {
-                // just skip this token
-                if (DEBUG_TOKEN) {
-                    Log.d(TAG, "--- isEmptyStringOrWhiteSpaces: \"" + tempWord + "\"");
-                }
-                continue;
-            }
-            if (!DictionaryInfoUtils.looksValidForDictionaryInsertion(
-                    tempWord, spacingAndPunctuations)) {
-                if (DEBUG_TOKEN) {
-                    Log.d(TAG, "--- not looksValidForDictionaryInsertion: \""
-                            + tempWord + "\"");
-                }
-                // Sentence terminator found. Split.
-                ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
-                continue;
-            }
-            if (DEBUG_TOKEN) {
-                Log.d(TAG, "--- word: \"" + tempWord + "\"");
-            }
-            final LanguageModelParam languageModelParam =
-                    detectWhetherVaildWordOrNotAndGetLanguageModelParam(
-                            ngramContext, tempWord, timestamp, locale, distracterFilter);
-            if (languageModelParam == null) {
-                continue;
-            }
-            languageModelParams.add(languageModelParam);
-            ngramContext = ngramContext.getNextNgramContext(
-                    new NgramContext.WordInfo(tempWord));
-        }
-        return languageModelParams;
-    }
-
-    private static LanguageModelParam detectWhetherVaildWordOrNotAndGetLanguageModelParam(
-            final NgramContext ngramContext, final String targetWord, final int timestamp,
-            final Locale locale, final DistracterFilter distracterFilter) {
-        if (locale == null) {
-            return null;
-        }
-        final int wordHandlingType = distracterFilter.getWordHandlingType(ngramContext,
-                targetWord, locale);
-        final String word = HandlingType.shouldBeLowerCased(wordHandlingType) ?
-                targetWord.toLowerCase(locale) : targetWord;
-        if (distracterFilter.isDistracterToWordsInDictionaries(ngramContext, targetWord, locale)) {
-            // The word is a distracter.
-            return null;
-        }
-        return createAndGetLanguageModelParamOfWord(ngramContext, word, timestamp,
-                !HandlingType.shouldBeHandledAsOov(wordHandlingType));
-    }
-
-    private static LanguageModelParam createAndGetLanguageModelParamOfWord(
-            final NgramContext ngramContext, final String word, final int timestamp,
-            final boolean isValidWord) {
-        final int unigramProbability = isValidWord ?
-                UNIGRAM_PROBABILITY_FOR_VALID_WORD : UNIGRAM_PROBABILITY_FOR_OOV_WORD;
-        if (!ngramContext.isValid()) {
-            if (DEBUG) {
-                Log.d(TAG, "--- add unigram: current("
-                        + (isValidWord ? "Valid" : "OOV") + ") = " + word);
-            }
-            return new LanguageModelParam(word, unigramProbability, timestamp);
-        }
-        if (DEBUG) {
-            Log.d(TAG, "--- add bigram: prev = " + ngramContext + ", current("
-                    + (isValidWord ? "Valid" : "OOV") + ") = " + word);
-        }
-        final int bigramProbability = isValidWord ?
-                BIGRAM_PROBABILITY_FOR_VALID_WORD : BIGRAM_PROBABILITY_FOR_OOV_WORD;
-        return new LanguageModelParam(ngramContext.getNthPrevWord(1 /* n */), word,
-                unigramProbability, bigramProbability, timestamp);
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java b/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java
index 95a1f0f..ba43677 100644
--- a/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java
@@ -16,14 +16,16 @@
 
 package com.android.inputmethod.latin.utils;
 
-import java.util.Arrays;
-import java.util.regex.Pattern;
-
 import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.NgramContext;
 import com.android.inputmethod.latin.NgramContext.WordInfo;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 
+import java.util.Arrays;
+import java.util.regex.Pattern;
+
+import javax.annotation.Nonnull;
+
 public final class NgramContextUtils {
     private NgramContextUtils() {
         // Intentional empty constructor for utility class.
@@ -52,6 +54,7 @@
     // (n = 2) "abc|" -> beginning-of-sentence
     // (n = 2) "abc |" -> beginning-of-sentence
     // (n = 2) "abc. def|" -> beginning-of-sentence
+    @Nonnull
     public static NgramContext getNgramContextFromNthPreviousWord(final CharSequence prev,
             final SpacingAndPunctuations spacingAndPunctuations, final int n) {
         if (prev == null) return NgramContext.EMPTY_PREV_WORDS_INFO;
diff --git a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java
index 093c5a6..d1fc642 100644
--- a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java
@@ -110,7 +110,6 @@
      * are true for the specified key value pairs.
      *
      * For example, "condition,constant" has the following format.
-     * (See {@link ResourceUtilsTests#testFindConstantForKeyValuePairsRegexp()})
      *  - HARDWARE=mako,constantForNexus4
      *  - MODEL=Nexus 4:MANUFACTURER=LGE,constantForNexus4
      *  - ,defaultConstant
@@ -119,6 +118,7 @@
      * @param conditionConstantArray an array of "condition,constant" elements to be searched.
      * @return the constant part of the matched "condition,constant" element. Returns null if no
      * condition matches.
+     * @see com.android.inputmethod.latin.utils.ResourceUtilsTests#testFindConstantForKeyValuePairsRegexp()
      */
     @UsedForTesting
     static String findConstantForKeyValuePairs(final HashMap<String, String> keyValuePairs,
diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java
index bbcef99..bc068ac 100644
--- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java
@@ -521,12 +521,12 @@
      * {@code charSequence.toString().split(regex, preserveTrailingEmptySegments ? -1 : 0)}
      * except that the spans are preserved in the result array.
      * </p>
-     * @param input the character sequence to be split.
+     * @param charSequence the character sequence to be split.
      * @param regex the regex pattern to be used as the separator.
      * @param preserveTrailingEmptySegments {@code true} to preserve the trailing empty
      * segments. Otherwise, trailing empty segments will be removed before being returned.
-     * @return the array which contains the result. All the spans in the {@param input} is
-     * preserved.
+     * @return the array which contains the result. All the spans in the <code>charSequence</code>
+     * is preserved.
      */
     @UsedForTesting
     public static CharSequence[] split(final CharSequence charSequence, final String regex,
diff --git a/java/src/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java b/java/src/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java
new file mode 100644
index 0000000..644fda5
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin.utils;
+
+import android.util.Log;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.NgramContext;
+import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
+import com.android.inputmethod.latin.utils.DistracterFilter.HandlingType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+// Note: this class is used as a parameter type of a native method. You should be careful when you
+// rename this class or field name. See BinaryDictionary#addMultipleDictionaryEntriesNative().
+public final class WordInputEventForPersonalization {
+    private static final String TAG = WordInputEventForPersonalization.class.getSimpleName();
+    private static final boolean DEBUG_TOKEN = false;
+
+    public final int[] mTargetWord;
+    public final int mPrevWordsCount;
+    public final int[][] mPrevWordArray = new int[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM][];
+    public final boolean[] mIsPrevWordBeginningOfSentenceArray =
+            new boolean[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    public final boolean mIsValid;
+    // Time stamp in seconds.
+    public final int mTimestamp;
+
+    @UsedForTesting
+    public WordInputEventForPersonalization(final CharSequence targetWord,
+            final NgramContext ngramContext, final boolean isValid, final int timestamp) {
+        mTargetWord = StringUtils.toCodePointArray(targetWord);
+        mPrevWordsCount = ngramContext.getPrevWordCount();
+        ngramContext.outputToArray(mPrevWordArray, mIsPrevWordBeginningOfSentenceArray);
+        mIsValid = isValid;
+        mTimestamp = timestamp;
+    }
+
+    // Process a list of words and return a list of {@link WordInputEventForPersonalization}
+    // objects.
+    public static ArrayList<WordInputEventForPersonalization> createInputEventFrom(
+            final List<String> tokens, final int timestamp,
+            final SpacingAndPunctuations spacingAndPunctuations, final Locale locale,
+            final DistracterFilter distracterFilter) {
+        final ArrayList<WordInputEventForPersonalization> inputEvents = new ArrayList<>();
+        final int N = tokens.size();
+        NgramContext ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
+        for (int i = 0; i < N; ++i) {
+            final String tempWord = tokens.get(i);
+            if (StringUtils.isEmptyStringOrWhiteSpaces(tempWord)) {
+                // just skip this token
+                if (DEBUG_TOKEN) {
+                    Log.d(TAG, "--- isEmptyStringOrWhiteSpaces: \"" + tempWord + "\"");
+                }
+                continue;
+            }
+            if (!DictionaryInfoUtils.looksValidForDictionaryInsertion(
+                    tempWord, spacingAndPunctuations)) {
+                if (DEBUG_TOKEN) {
+                    Log.d(TAG, "--- not looksValidForDictionaryInsertion: \""
+                            + tempWord + "\"");
+                }
+                // Sentence terminator found. Split.
+                // TODO: Detect whether the context is beginning-of-sentence.
+                ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
+                continue;
+            }
+            if (DEBUG_TOKEN) {
+                Log.d(TAG, "--- word: \"" + tempWord + "\"");
+            }
+            final WordInputEventForPersonalization inputEvent =
+                    detectWhetherVaildWordOrNotAndGetInputEvent(
+                            ngramContext, tempWord, timestamp, locale, distracterFilter);
+            if (inputEvent == null) {
+                continue;
+            }
+            inputEvents.add(inputEvent);
+            ngramContext = ngramContext.getNextNgramContext(new NgramContext.WordInfo(tempWord));
+        }
+        return inputEvents;
+    }
+
+    private static WordInputEventForPersonalization detectWhetherVaildWordOrNotAndGetInputEvent(
+            final NgramContext ngramContext, final String targetWord, final int timestamp,
+            final Locale locale, final DistracterFilter distracterFilter) {
+        if (locale == null) {
+            return null;
+        }
+        final int wordHandlingType = distracterFilter.getWordHandlingType(ngramContext,
+                targetWord, locale);
+        final String word = HandlingType.shouldBeLowerCased(wordHandlingType) ?
+                targetWord.toLowerCase(locale) : targetWord;
+        if (distracterFilter.isDistracterToWordsInDictionaries(ngramContext, targetWord, locale)) {
+            // The word is a distracter.
+            return null;
+        }
+        return new WordInputEventForPersonalization(word, ngramContext,
+                !HandlingType.shouldBeHandledAsOov(wordHandlingType), timestamp);
+    }
+}
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 9239c84..118f600 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -453,98 +453,60 @@
             historicalInfo);
 }
 
-// Returns how many language model params are processed.
-static int latinime_BinaryDictionary_addMultipleDictionaryEntries(JNIEnv *env, jclass clazz,
-        jlong dict, jobjectArray languageModelParams, jint startIndex) {
+// Returns how many input events are processed.
+static int latinime_BinaryDictionary_updateEntriesForInputEvents(JNIEnv *env, jclass clazz,
+        jlong dict, jobjectArray inputEvents, jint startIndex) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) {
         return 0;
     }
-    jsize languageModelParamCount = env->GetArrayLength(languageModelParams);
-    if (languageModelParamCount == 0 || startIndex >= languageModelParamCount) {
+    jsize inputEventCount = env->GetArrayLength(inputEvents);
+    if (inputEventCount == 0 || startIndex >= inputEventCount) {
         return 0;
     }
-    jobject languageModelParam = env->GetObjectArrayElement(languageModelParams, 0);
-    jclass languageModelParamClass = env->GetObjectClass(languageModelParam);
-    env->DeleteLocalRef(languageModelParam);
+    jobject inputEvent = env->GetObjectArrayElement(inputEvents, 0);
+    jclass wordInputEventClass = env->GetObjectClass(inputEvent);
+    env->DeleteLocalRef(inputEvent);
 
-    jfieldID word0FieldId = env->GetFieldID(languageModelParamClass, "mWord0", "[I");
-    jfieldID word1FieldId = env->GetFieldID(languageModelParamClass, "mWord1", "[I");
-    jfieldID unigramProbabilityFieldId =
-            env->GetFieldID(languageModelParamClass, "mUnigramProbability", "I");
-    jfieldID bigramProbabilityFieldId =
-            env->GetFieldID(languageModelParamClass, "mBigramProbability", "I");
-    jfieldID timestampFieldId =
-            env->GetFieldID(languageModelParamClass, "mTimestamp", "I");
-    jfieldID shortcutTargetFieldId =
-            env->GetFieldID(languageModelParamClass, "mShortcutTarget", "[I");
-    jfieldID shortcutProbabilityFieldId =
-            env->GetFieldID(languageModelParamClass, "mShortcutProbability", "I");
-    jfieldID isNotAWordFieldId =
-            env->GetFieldID(languageModelParamClass, "mIsNotAWord", "Z");
-    jfieldID isPossiblyOffensiveFieldId =
-            env->GetFieldID(languageModelParamClass, "mIsPossiblyOffensive", "Z");
-    env->DeleteLocalRef(languageModelParamClass);
+    jfieldID targetWordFieldId = env->GetFieldID(wordInputEventClass, "mTargetWord", "[I");
+    jfieldID prevWordCountFieldId = env->GetFieldID(wordInputEventClass, "mPrevWordsCount", "I");
+    jfieldID prevWordArrayFieldId = env->GetFieldID(wordInputEventClass, "mPrevWordArray", "[[I");
+    jfieldID isPrevWordBoSArrayFieldId =
+            env->GetFieldID(wordInputEventClass, "mIsPrevWordBeginningOfSentenceArray", "[Z");
+    jfieldID isValidFieldId = env->GetFieldID(wordInputEventClass, "mIsValid", "Z");
+    jfieldID timestampFieldId = env->GetFieldID(wordInputEventClass, "mTimestamp", "I");
+    env->DeleteLocalRef(wordInputEventClass);
 
-    for (int i = startIndex; i < languageModelParamCount; ++i) {
-        jobject languageModelParam = env->GetObjectArrayElement(languageModelParams, i);
-        // languageModelParam is a set of params for word1; thus, word1 cannot be null. On the
-        // other hand, word0 can be null and then it means the set of params doesn't contain bigram
-        // information.
-        jintArray word0 = static_cast<jintArray>(
-                env->GetObjectField(languageModelParam, word0FieldId));
-        jsize word0Length = word0 ? env->GetArrayLength(word0) : 0;
-        int word0CodePoints[word0Length];
-        if (word0) {
-            env->GetIntArrayRegion(word0, 0, word0Length, word0CodePoints);
-        }
-        jintArray word1 = static_cast<jintArray>(
-                env->GetObjectField(languageModelParam, word1FieldId));
-        jsize word1Length = env->GetArrayLength(word1);
-        int word1CodePoints[word1Length];
-        env->GetIntArrayRegion(word1, 0, word1Length, word1CodePoints);
-        jint unigramProbability = env->GetIntField(languageModelParam, unigramProbabilityFieldId);
-        jint timestamp = env->GetIntField(languageModelParam, timestampFieldId);
-        jboolean isNotAWord = env->GetBooleanField(languageModelParam, isNotAWordFieldId);
-        jboolean isPossiblyOffensive = env->GetBooleanField(languageModelParam,
-                isPossiblyOffensiveFieldId);
-        jintArray shortcutTarget = static_cast<jintArray>(
-                env->GetObjectField(languageModelParam, shortcutTargetFieldId));
-        std::vector<UnigramProperty::ShortcutProperty> shortcuts;
-        {
-            std::vector<int> shortcutTargetCodePoints;
-            JniDataUtils::jintarrayToVector(env, shortcutTarget, &shortcutTargetCodePoints);
-            if (!shortcutTargetCodePoints.empty()) {
-                jint shortcutProbability =
-                        env->GetIntField(languageModelParam, shortcutProbabilityFieldId);
-                shortcuts.emplace_back(std::move(shortcutTargetCodePoints), shortcutProbability);
-            }
-        }
+    for (int i = startIndex; i < inputEventCount; ++i) {
+        jobject inputEvent = env->GetObjectArrayElement(inputEvents, i);
+        jintArray targetWord = static_cast<jintArray>(
+                env->GetObjectField(inputEvent, targetWordFieldId));
+        jsize wordLength = env->GetArrayLength(targetWord);
+        int wordCodePoints[wordLength];
+        env->GetIntArrayRegion(targetWord, 0, wordLength, wordCodePoints);
+        env->DeleteLocalRef(targetWord);
+
+        jint prevWordCount = env->GetIntField(inputEvent, prevWordCountFieldId);
+        jobjectArray prevWordArray =
+                static_cast<jobjectArray>(env->GetObjectField(inputEvent, prevWordArrayFieldId));
+        jbooleanArray isPrevWordBeginningOfSentenceArray = static_cast<jbooleanArray>(
+                env->GetObjectField(inputEvent, isPrevWordBoSArrayFieldId));
+        jboolean isValid = env->GetBooleanField(inputEvent, isValidFieldId);
+        jint timestamp = env->GetIntField(inputEvent, timestampFieldId);
+        const NgramContext ngramContext = JniDataUtils::constructNgramContext(env,
+                prevWordArray, isPrevWordBeginningOfSentenceArray, prevWordCount);
         // Use 1 for count to indicate the word has inputted.
-        const UnigramProperty unigramProperty(false /* isBeginningOfSentence */, isNotAWord,
-                isPossiblyOffensive, unigramProbability,
-                HistoricalInfo(timestamp, 0 /* level */, 1 /* count */), std::move(shortcuts));
-        dictionary->addUnigramEntry(CodePointArrayView(word1CodePoints, word1Length),
-                &unigramProperty);
-        if (word0) {
-            jint bigramProbability = env->GetIntField(languageModelParam, bigramProbabilityFieldId);
-            // Use 1 for count to indicate the bigram has inputted.
-            const NgramContext ngramContext(word0CodePoints, word0Length,
-                    false /* isBeginningOfSentence */);
-            const NgramProperty ngramProperty(ngramContext,
-                    CodePointArrayView(word1CodePoints, word1Length).toVector(),
-                    bigramProbability, HistoricalInfo(timestamp, 0 /* level */, 1 /* count */));
-            dictionary->addNgramEntry(&ngramProperty);
-        }
+        dictionary->updateEntriesForWordWithNgramContext(&ngramContext,
+                CodePointArrayView(wordCodePoints, wordLength), isValid,
+                HistoricalInfo(timestamp, 0 /* level */, 1 /* count */));
         if (dictionary->needsToRunGC(true /* mindsBlockByGC */)) {
             return i + 1;
         }
-        env->DeleteLocalRef(word0);
-        env->DeleteLocalRef(word1);
-        env->DeleteLocalRef(shortcutTarget);
-        env->DeleteLocalRef(languageModelParam);
+        env->DeleteLocalRef(prevWordArray);
+        env->DeleteLocalRef(isPrevWordBeginningOfSentenceArray);
+        env->DeleteLocalRef(inputEvent);
     }
-    return languageModelParamCount;
+    return inputEventCount;
 }
 
 static jstring latinime_BinaryDictionary_getProperty(JNIEnv *env, jclass clazz, jlong dict,
@@ -754,10 +716,10 @@
         reinterpret_cast<void *>(latinime_BinaryDictionary_updateEntriesForWordWithNgramContext)
     },
     {
-        const_cast<char *>("addMultipleDictionaryEntriesNative"),
+        const_cast<char *>("updateEntriesForInputEventsNative"),
         const_cast<char *>(
-                "(J[Lcom/android/inputmethod/latin/utils/LanguageModelParam;I)I"),
-        reinterpret_cast<void *>(latinime_BinaryDictionary_addMultipleDictionaryEntries)
+                "(J[Lcom/android/inputmethod/latin/utils/WordInputEventForPersonalization;I)I"),
+        reinterpret_cast<void *>(latinime_BinaryDictionary_updateEntriesForInputEvents)
     },
     {
         const_cast<char *>("getPropertyNative"),
diff --git a/native/jni/src/utils/jni_data_utils.h b/native/jni/src/utils/jni_data_utils.h
index 25cc417..a259e1c 100644
--- a/native/jni/src/utils/jni_data_utils.h
+++ b/native/jni/src/utils/jni_data_utils.h
@@ -50,6 +50,7 @@
             const jsize keyUtf8Length = env->GetStringUTFLength(keyString);
             char keyChars[keyUtf8Length + 1];
             env->GetStringUTFRegion(keyString, 0, env->GetStringLength(keyString), keyChars);
+            env->DeleteLocalRef(keyString);
             keyChars[keyUtf8Length] = '\0';
             DictionaryHeaderStructurePolicy::AttributeMap::key_type key;
             HeaderReadWriteUtils::insertCharactersIntoVector(keyChars, &key);
@@ -59,6 +60,7 @@
             const jsize valueUtf8Length = env->GetStringUTFLength(valueString);
             char valueChars[valueUtf8Length + 1];
             env->GetStringUTFRegion(valueString, 0, env->GetStringLength(valueString), valueChars);
+            env->DeleteLocalRef(valueString);
             valueChars[valueUtf8Length] = '\0';
             DictionaryHeaderStructurePolicy::AttributeMap::mapped_type value;
             HeaderReadWriteUtils::insertCharactersIntoVector(valueChars, &value);
@@ -113,6 +115,7 @@
                 continue;
             }
             env->GetIntArrayRegion(prevWord, 0, prevWordLength, prevWordCodePoints[i]);
+            env->DeleteLocalRef(prevWord);
             prevWordCodePointCount[i] = prevWordLength;
             jboolean isBeginningOfSentenceBoolean = JNI_FALSE;
             env->GetBooleanArrayRegion(isBeginningOfSentenceArray, i, 1 /* len */,
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java
index 2134eb5..6f747b3 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java
@@ -27,8 +27,8 @@
 
 @SmallTest
 public class KeyboardLayoutSetSubtypesCountTests extends KeyboardLayoutSetTestsBase {
-    private static final int NUMBER_OF_SUBTYPES = 78;
-    private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 47;
+    private static final int NUMBER_OF_SUBTYPES = 85;
+    private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 50;
     private static final int NUMBER_OF_PREDEFINED_ADDITIONAL_SUBTYPES = 2;
 
     @Override
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliBD.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliBD.java
index c39a392..6262589 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliBD.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliBD.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout.tests;
 
-import android.test.suitebuilder.annotation.Suppress;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.BengaliAkkhor;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
@@ -29,7 +29,7 @@
 /**
  * bn_BD: Bengali (Bangladesh)/bengali_akkhor
  */
-@Suppress
+@SmallTest
 public final class TestsBengaliBD extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("bn", "BD");
     private static final LayoutBase LAYOUT = new BengaliAkkhor(new BengaliBDCustomzier(LOCALE));
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java
index a8e8723..613b3bb 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout.tests;
 
-import android.test.suitebuilder.annotation.Suppress;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
@@ -30,7 +30,7 @@
 /*
  * hi_ZZ: Hinglish/qwerty
  */
-@Suppress
+@SmallTest
 public final class TestsHinglish extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("hi", "ZZ");
     private static final LayoutBase LAYOUT = new Qwerty(new HinglishCustomizer(LOCALE));
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMyanmarMM.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMyanmarMM.java
index 18baa61..b581e4a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMyanmarMM.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMyanmarMM.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout.tests;
 
-import android.test.suitebuilder.annotation.Suppress;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Myanmar;
@@ -26,7 +26,7 @@
 /**
  * my_MM: Myanmar (Myanmar)/myanmar
  */
-@Suppress
+@SmallTest
 public final class TestsMyanmarMM extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("my", "MM");
     private static final LayoutBase LAYOUT = new Myanmar(LOCALE);
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatin.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatin.java
index ea957e4..7490d30 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatin.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatin.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout.tests;
 
-import android.test.suitebuilder.annotation.Suppress;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.SerbianQwertz;
@@ -27,7 +27,7 @@
 /**
  * sr_ZZ: Serbian (Latin)/serbian_qwertz
  */
-@Suppress
+@SmallTest
 public final class TestsSerbianLatin extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("sr", "ZZ");
     private static final LayoutBase LAYOUT = new SerbianQwertz(new SerbianLatinCustomizer(LOCALE));
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatinQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatinQwerty.java
index a198473..6d9351c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatinQwerty.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatinQwerty.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout.tests;
 
-import android.test.suitebuilder.annotation.Suppress;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
@@ -29,7 +29,7 @@
 /**
  * sr_ZZ: Serbian (Latin)/qwerty
  */
-@Suppress
+@SmallTest
 public final class TestsSerbianLatinQwerty extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("sr", "ZZ");
     private static final LayoutBase LAYOUT = new Qwerty(new SerbianLatinQwertyCustomizer(LOCALE));
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilLK.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilLK.java
index 72872ba..6e49c59 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilLK.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilLK.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout.tests;
 
-import android.test.suitebuilder.annotation.Suppress;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Symbols;
@@ -30,7 +30,7 @@
 /**
  * ta_LK: Tamil (Sri Lanka)/tamil
  */
-@Suppress
+@SmallTest
 public final class TestsTamilLK extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("ta", "LK");
     private static final LayoutBase LAYOUT = new Tamil(new TamilLKCustomizer(LOCALE));
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbek.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbek.java
index 169de1f..fd12a6a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbek.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbek.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout.tests;
 
-import android.test.suitebuilder.annotation.Suppress;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Uzbek;
@@ -27,7 +27,7 @@
 /**
  * uz_UZ: Uzbek (Uzbekistan)/uzbek
  */
-@Suppress
+@SmallTest
 public final class TestsUzbek extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("uz", "UZ");
     private static final LayoutBase LAYOUT = new Uzbek(new UzbekCustomizer(LOCALE));
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbekQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbekQwerty.java
index c210da1..4c33a8c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbekQwerty.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbekQwerty.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout.tests;
 
-import android.test.suitebuilder.annotation.Suppress;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
@@ -28,7 +28,7 @@
 /**
  * uz_UZ: Uzbek (Uzbekistan)/qwerty
  */
-@Suppress
+@SmallTest
 public final class TestsUzbekQwerty extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("uz", "UZ");
     private static final LayoutBase LAYOUT = new Qwerty(new UzbekQwertyCustomizer(LOCALE));
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
index 15f7568..47badc1 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
@@ -32,6 +32,7 @@
 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
 import com.android.inputmethod.latin.utils.FileUtils;
 import com.android.inputmethod.latin.utils.LocaleUtils;
+import com.android.inputmethod.latin.utils.WordInputEventForPersonalization;
 
 import java.io.File;
 import java.io.IOException;
@@ -748,4 +749,66 @@
 
         binaryDictionary.close();
     }
+
+    public void testUpdateEntriesForInputEvents() {
+        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+            testUpdateEntriesForInputEvents(formatVersion);
+        }
+    }
+
+    private void testUpdateEntriesForInputEvents(final int formatVersion) {
+        setCurrentTimeForTestMode(mCurrentTime);
+        final int codePointSetSize = 20;
+        final int EVENT_COUNT = 1000;
+        final double CONTINUE_RATE = 0.9;
+        final long seed = System.currentTimeMillis();
+        final Random random = new Random(seed);
+        final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+
+        final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
+        final ArrayList<String> unigrams = new ArrayList<>();
+        final ArrayList<Pair<String, String>> bigrams = new ArrayList<>();
+        final ArrayList<Pair<Pair<String, String>, String>> trigrams = new ArrayList<>();
+
+        final WordInputEventForPersonalization[] inputEvents =
+                new WordInputEventForPersonalization[EVENT_COUNT];
+        NgramContext ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
+        int prevWordCount = 0;
+        for (int i = 0; i < inputEvents.length; i++) {
+            final String word = CodePointUtils.generateWord(random, codePointSet);
+            inputEvents[i] = new WordInputEventForPersonalization(word, ngramContext,
+                    true /* isValid */, mCurrentTime);
+            unigrams.add(word);
+            if (prevWordCount >= 2) {
+                final Pair<String, String> prevWordsPair = bigrams.get(bigrams.size() - 1);
+                trigrams.add(new Pair<>(prevWordsPair, word));
+            }
+            if (prevWordCount >= 1) {
+                bigrams.add(new Pair<>(ngramContext.getNthPrevWord(1 /* n */).toString(), word));
+            }
+            if (random.nextDouble() > CONTINUE_RATE) {
+                ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
+                prevWordCount = 0;
+            } else {
+                ngramContext = ngramContext.getNextNgramContext(new WordInfo(word));
+                prevWordCount++;
+            }
+        }
+        final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
+        binaryDictionary.updateEntriesForInputEvents(inputEvents);
+
+        for (final String word : unigrams) {
+            assertTrue(binaryDictionary.isInDictionary(word));
+        }
+        for (final Pair<String, String> bigram : bigrams) {
+            assertTrue(isValidBigram(binaryDictionary, bigram.first, bigram.second));
+        }
+        if (!supportsNgram(formatVersion)) {
+            return;
+        }
+        for (final Pair<Pair<String, String>, String> trigram : trigrams) {
+            assertTrue(isValidTrigram(binaryDictionary, trigram.first.first, trigram.first.second,
+                    trigram.second));
+        }
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index 5a72e41..d0f4f39 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -29,7 +29,6 @@
 import com.android.inputmethod.latin.makedict.WordProperty;
 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
 import com.android.inputmethod.latin.utils.FileUtils;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
 
 import java.io.File;
 import java.io.IOException;
@@ -37,7 +36,6 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Random;
 
 // TODO Use the seed passed as an argument for makedict test.
@@ -884,63 +882,6 @@
         }
     }
 
-    public void testAddMultipleDictionaryEntries() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddMultipleDictionaryEntries(formatVersion);
-        }
-    }
-
-    private void testAddMultipleDictionaryEntries(final int formatVersion) {
-        final int codePointSetSize = 20;
-        final int lmParamCount = 1000;
-        final double bigramContinueRate = 0.9;
-        final long seed = System.currentTimeMillis();
-        final Random random = new Random(seed);
-        final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
-
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-        final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
-        final HashMap<Pair<String, String>, Integer> bigramProbabilities = new HashMap<>();
-
-        final LanguageModelParam[] languageModelParams = new LanguageModelParam[lmParamCount];
-        String prevWord = null;
-        for (int i = 0; i < languageModelParams.length; i++) {
-            final String word = CodePointUtils.generateWord(random, codePointSet);
-            final int probability = random.nextInt(0xFF);
-            final int bigramProbability = probability + random.nextInt(0xFF - probability);
-            unigramProbabilities.put(word, probability);
-            if (prevWord == null) {
-                languageModelParams[i] = new LanguageModelParam(word, probability,
-                        BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-            } else {
-                languageModelParams[i] = new LanguageModelParam(prevWord, word, probability,
-                        bigramProbability, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-                bigramProbabilities.put(new Pair<>(prevWord, word),
-                        bigramProbability);
-            }
-            prevWord = (random.nextDouble() < bigramContinueRate) ? word : null;
-        }
-
-        final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
-        binaryDictionary.addMultipleDictionaryEntries(languageModelParams);
-
-        for (Map.Entry<String, Integer> entry : unigramProbabilities.entrySet()) {
-            assertEquals((int)entry.getValue(), binaryDictionary.getFrequency(entry.getKey()));
-        }
-
-        for (Map.Entry<Pair<String, String>, Integer> entry : bigramProbabilities.entrySet()) {
-            final String word0 = entry.getKey().first;
-            final String word1 = entry.getKey().second;
-            final int bigramProbability = entry.getValue();
-            assertEquals(bigramProbability != Dictionary.NOT_A_PROBABILITY,
-                    isValidBigram(binaryDictionary, word0, word1));
-            if (canCheckBigramProbability(formatVersion)) {
-                assertEquals(bigramProbability,
-                        getBigramProbability(binaryDictionary, word0, word1));
-            }
-        }
-    }
-
     public void testGetWordProperties() {
         for (final int formatVersion : DICT_FORMAT_VERSIONS) {
             testGetWordProperties(formatVersion);
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
index 21411f2..120b96b 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
@@ -165,7 +165,7 @@
          *
          * @param codePoints the code point array to write.
          * @param buffer the byte buffer to write to.
-         * @param index the index in buffer to write the character array to.
+         * @param fromIndex the index in buffer to write the character array to.
          * @param codePointToOneByteCodeMap the map to convert the code point.
          * @return the index after the last character.
          */
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
index a3a71a4..60e3825 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
@@ -535,7 +535,7 @@
      * Helper method to write a children position to a file.
      *
      * @param buffer the buffer to write to.
-     * @param index the index in the buffer to write the address to.
+     * @param fromIndex the index in the buffer to write the address to.
      * @param position the position to write.
      * @return the size in bytes the address actually took.
      */
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
index 5e90387..0ff4c21 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
@@ -44,7 +44,7 @@
     public static DictDecoder getDictDecoder(final File dictFile, final long offset,
             final long length, final int bufferType) {
         if (dictFile.isDirectory()) {
-            return new Ver4DictDecoder(dictFile, bufferType);
+            return new Ver4DictDecoder(dictFile);
         } else if (dictFile.isFile()) {
             return new Ver2DictDecoder(dictFile, offset, length, bufferType);
         }
@@ -54,7 +54,7 @@
     public static DictDecoder getDictDecoder(final File dictFile, final long offset,
             final long length, final DictionaryBufferFactory factory) {
         if (dictFile.isDirectory()) {
-            return new Ver4DictDecoder(dictFile, factory);
+            return new Ver4DictDecoder(dictFile);
         } else if (dictFile.isFile()) {
             return new Ver2DictDecoder(dictFile, offset, length, factory);
         }
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
index 7c1ae2f..7e54ce9 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
@@ -33,12 +33,7 @@
     final File mDictDirectory;
 
     @UsedForTesting
-    /* package */ Ver4DictDecoder(final File dictDirectory, final int factoryFlag) {
-        this(dictDirectory, null /* factory */);
-    }
-
-    @UsedForTesting
-    /* package */ Ver4DictDecoder(final File dictDirectory, final DictionaryBufferFactory factory) {
+    /* package */ Ver4DictDecoder(final File dictDirectory) {
         mDictDirectory = dictDirectory;
 
     }
diff --git a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
index 6ccb79d..dc6fb00 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
@@ -30,7 +30,7 @@
 import com.android.inputmethod.latin.DictionaryFacilitator;
 import com.android.inputmethod.latin.ExpandableBinaryDictionary;
 import com.android.inputmethod.latin.RichInputMethodManager;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback;
+import com.android.inputmethod.latin.ExpandableBinaryDictionary.UpdateEntriesForInputEventsCallback;
 import com.android.inputmethod.latin.common.CodePointUtils;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 
@@ -96,8 +96,8 @@
                     true /* inputByUser */, tokens, timeStampInSeconds, DUMMY_PACKAGE_NAME,
                     LOCALE_EN_US.getLanguage());
             final CountDownLatch countDownLatch = new CountDownLatch(1);
-            final AddMultipleDictionaryEntriesCallback callback =
-                    new AddMultipleDictionaryEntriesCallback() {
+            final UpdateEntriesForInputEventsCallback callback =
+                    new UpdateEntriesForInputEventsCallback() {
                         @Override
                         public void onFinished() {
                             countDownLatch.countDown();
diff --git a/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
index 8bda672..3feb60e 100644
--- a/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
@@ -29,7 +29,7 @@
 @SmallTest
 public class CollectionUtilsTests extends AndroidTestCase {
     /**
-     * Tests that {@link CollectionUtils#arrayAsList(E[],int,int)} gives the expected
+     * Tests that {@link CollectionUtils#arrayAsList(Object[],int,int)} gives the expected
      * results for a few valid inputs.
      */
     public void testArrayAsList() {
@@ -42,7 +42,7 @@
     }
 
     /**
-     * Tests that {@link CollectionUtils#isEmpty(java.util.Collection)} gives the expected
+     * Tests that {@link CollectionUtils#isNullOrEmpty(java.util.Collection)} gives the expected
      * results for a few cases.
      */
     public void testIsNullOrEmpty() {
diff --git a/tools/dicttool/Android.mk b/tools/dicttool/Android.mk
index ff6c1e4..09af9a0 100644
--- a/tools/dicttool/Android.mk
+++ b/tools/dicttool/Android.mk
@@ -35,7 +35,6 @@
 LATINIME_BASE_SRC_DIR := $(LATINIME_LOCAL_DIR)/java/src/com/android/inputmethod
 LATINIME_BASE_OVERRIDABLE_SRC_DIR := \
         $(LATINIME_LOCAL_DIR)/java-overridable/src/com/android/inputmethod
-LATINIME_ANNOTATIONS_SRC_DIR := $(LATINIME_BASE_SRC_DIR)/annotations
 MAKEDICT_CORE_SRC_DIR := $(LATINIME_BASE_SRC_DIR)/latin/makedict
 LATINIME_TESTS_SRC_DIR := $(LATINIME_LOCAL_DIR)/tests/src/com/android/inputmethod/latin
 
@@ -82,15 +81,12 @@
 
 LOCAL_MAIN_SRC_FILES := $(call all-java-files-under, $(MAKEDICT_CORE_SRC_DIR))
 LOCAL_TOOL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_ANNOTATIONS_SRC_FILES := $(call all-java-files-under, $(LATINIME_ANNOTATIONS_SRC_DIR))
 
 LOCAL_SRC_FILES := $(LOCAL_TOOL_SRC_FILES) \
         $(filter-out $(addprefix %/, $(notdir $(LOCAL_TOOL_SRC_FILES))), $(LOCAL_MAIN_SRC_FILES)) \
-        $(call all-java-files-under, $(DICTTOOL_COMPAT_TESTS_DIR)) \
-        $(LOCAL_ANNOTATIONS_SRC_FILES) $(USED_TARGETED_SRC_FILES) \
-        $(LATINIME_BASE_SRC_DIR)/latin/Constants.java \
-        $(call all-java-files-under, tests) \
-        $(call all-java-files-under, $(DICTTOOL_ONDEVICE_TESTS_DIR))
+        $(USED_TARGETED_SRC_FILES) \
+        $(call all-java-files-under, \
+                tests $(DICTTOOL_COMPAT_TESTS_DIR) $(DICTTOOL_ONDEVICE_TESTS_DIR))
 
 LOCAL_JAVA_LIBRARIES := junit
 LOCAL_STATIC_JAVA_LIBRARIES := jsr305lib latinime-common-host
diff --git a/tools/dicttool/compat/android/test/MoreAsserts.java b/tools/dicttool/compat/android/test/MoreAsserts.java
deleted file mode 100644
index f56420b..0000000
--- a/tools/dicttool/compat/android/test/MoreAsserts.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test;
-
-import junit.framework.Assert;
-
-/**
- * This is a compatibility class that aims at emulating android.test.MoreAsserts from the
- * Android library as simply as possible, and only to the extent that is used by the client classes.
- * Its purpose is to provide compatibility without having to pull the whole Android library.
- */
-public class MoreAsserts {
-    public static void assertNotEqual(Object unexpected, Object actual) {
-        if (equal(unexpected, actual)) {
-            Assert.fail("expected not to be:<" + unexpected + ">");
-        }
-    }
-    private static boolean equal(Object a, Object b) {
-        return a == b || (a != null && a.equals(b));
-    }
-}
diff --git a/tools/dicttool/compat/com/android/inputmethod/keyboard/Keyboard.java b/tools/dicttool/compat/com/android/inputmethod/keyboard/Keyboard.java
index 61b209f..3d6bfd0 100644
--- a/tools/dicttool/compat/com/android/inputmethod/keyboard/Keyboard.java
+++ b/tools/dicttool/compat/com/android/inputmethod/keyboard/Keyboard.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.keyboard;
 
+@SuppressWarnings("unused")
 public class Keyboard {
     private final Key KEY = new Key();
     public final Key getKey(final int i) { return KEY; }
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
index e04751d..8f9e4a3 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
@@ -27,7 +27,6 @@
 import com.android.inputmethod.latin.makedict.Ver2DictEncoder;
 import com.android.inputmethod.latin.makedict.Ver4DictEncoder;
 
-import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
@@ -253,14 +252,6 @@
         }
     }
 
-    private static BufferedInputStream getBufferedFileInputStream(final String filename)
-            throws FileNotFoundException {
-        if (filename == null) {
-            return null;
-        }
-        return new BufferedInputStream(new FileInputStream(filename));
-    }
-
     /**
      * Invoke the right output method according to args.
      *
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java
index 3df3737..b8a64e3 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java
@@ -64,8 +64,7 @@
                 + " whitelist entries)");
     }
 
-    private static void showWordInfo(final FusionDictionary dict, final String word,
-            final boolean plumbing) {
+    private static void showWordInfo(final FusionDictionary dict, final String word) {
         final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, word);
         if (null == ptNode) {
             System.out.println(word + " is not in the dictionary");
@@ -124,7 +123,7 @@
             showInfo(dict, plumbing);
         } else {
             for (int i = 1; i < mArgs.length; ++i) {
-                showWordInfo(dict, mArgs[i], plumbing);
+                showWordInfo(dict, mArgs[i]);
             }
         }
     }
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
index a4ad6b5..dcc4e19 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.latin.personalization;
 
+@SuppressWarnings("unused")
 public class PersonalizationHelper {
     public static void currentTimeChangedForTesting(final int currentTimestamp) {
     }