Merge "Fix some compiler warnings"
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index edcdd4c..a0210e4 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -346,7 +346,8 @@
     }
 
     // TODO: Remove this method once TTS supports emoticon verbalization.
-    private String getSpokenEmoticonDescription(final Context context, final String outputText) {
+    private static String getSpokenEmoticonDescription(final Context context,
+            final String outputText) {
         final StringBuilder sb = new StringBuilder(SPOKEN_EMOTICON_RESOURCE_NAME_PREFIX);
         final int textLength = outputText.length();
         for (int index = 0; index < textLength; index = outputText.offsetByCodePoints(index, 1)) {
diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
index 66b0acb..7fc1e9d 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
@@ -329,9 +329,8 @@
         if (currentSettings.isWordSeparator(key.getCode())) {
             return mAccessibilityUtils.getAutoCorrectionDescription(
                     keyCodeDescription, shouldObscure);
-        } else {
-            return keyCodeDescription;
         }
+        return keyCodeDescription;
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java
index 6aa2736..5db8019 100644
--- a/java/src/com/android/inputmethod/compat/CompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/CompatUtils.java
@@ -144,7 +144,7 @@
 
         public <T> ToObjectMethodWrapper<T> getMethod(final String name,
                 final T defaultValue, final Class<?>... parameterTypes) {
-            return new ToObjectMethodWrapper<T>(CompatUtils.getMethod(mClass, name, parameterTypes),
+            return new ToObjectMethodWrapper<>(CompatUtils.getMethod(mClass, name, parameterTypes),
                     defaultValue);
         }
 
diff --git a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
index f4f54b6..550d474 100644
--- a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
@@ -46,7 +46,7 @@
      */
     public static final int FLAG_IS_RTL = 0x04;
 
-    private CursorAnchorInfoCompatWrapper() {
+    CursorAnchorInfoCompatWrapper() {
         // This class is not publicly instantiable.
     }
 
diff --git a/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java b/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java
index f411f18..58e5a36 100644
--- a/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.compat;
 
 import android.text.Spannable;
+import android.text.Spanned;
 import android.text.style.LocaleSpan;
 import android.util.Log;
 
@@ -127,13 +128,13 @@
             final int spanFlag = spannable.getSpanFlags(existingLocaleSpan);
             if (spanStart < newStart) {
                 newStart = spanStart;
-                isStartExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) ==
-                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                isStartExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
+                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             }
             if (newEnd < spanEnd) {
                 newEnd = spanEnd;
-                isEndExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) ==
-                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                isEndExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
+                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             }
             existingLocaleSpansToBeMerged.add(existingLocaleSpan);
         }
@@ -201,24 +202,17 @@
 
     private static int getSpanFlag(final int originalFlag,
             final boolean isStartExclusive, final boolean isEndExclusive) {
-        return (originalFlag & ~Spannable.SPAN_POINT_MARK_MASK) |
+        return (originalFlag & ~Spanned.SPAN_POINT_MARK_MASK) |
                 getSpanPointMarkFlag(isStartExclusive, isEndExclusive);
     }
 
     private static int getSpanPointMarkFlag(final boolean isStartExclusive,
             final boolean isEndExclusive) {
         if (isStartExclusive) {
-            if (isEndExclusive) {
-                return Spannable.SPAN_EXCLUSIVE_EXCLUSIVE;
-            } else {
-                return Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
-            }
-        } else {
-            if (isEndExclusive) {
-                return Spannable.SPAN_INCLUSIVE_EXCLUSIVE;
-            } else {
-                return Spannable.SPAN_INCLUSIVE_INCLUSIVE;
-            }
+            return isEndExclusive ? Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+                    : Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
         }
+        return isEndExclusive ? Spanned.SPAN_INCLUSIVE_EXCLUSIVE
+                : Spanned.SPAN_INCLUSIVE_INCLUSIVE;
     }
 }
diff --git a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
index eb18007..70ab972 100644
--- a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
@@ -71,13 +71,13 @@
         CompatUtils.invoke(builder, null, METHOD_setPriority, PRIORITY_LOW);
     }
 
+    @SuppressWarnings("deprecation")
     public static Notification build(final Notification.Builder builder) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
             // #build was added in API level 16, JELLY_BEAN
             return (Notification) CompatUtils.invoke(builder, null, METHOD_build);
-        } else {
-            // #getNotification was deprecated in API level 16, JELLY_BEAN
-            return builder.getNotification();
         }
+        // #getNotification was deprecated in API level 16, JELLY_BEAN
+        return builder.getNotification();
     }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
index 6d6c8f5..0fa72c3 100644
--- a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
+++ b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
@@ -122,19 +122,23 @@
         mDeleteButton.setTranslationX(STATUS_DELETE == status ? 0 : width);
     }
 
+    // The helper method for {@link AnimatorListenerAdapter}.
+    void animateButtonIfStatusIsEqual(final View newButton, final int newStatus) {
+        if (newStatus != mStatus) return;
+        animateButton(newButton, ANIMATION_IN);
+    }
+
     private void animateButtonPosition(final int oldStatus, final int newStatus) {
         final View oldButton = getButton(oldStatus);
         final View newButton = getButton(newStatus);
         if (null != oldButton && null != newButton) {
             // Transition between two buttons : animate out, then in
-            animateButton(oldButton, ANIMATION_OUT).setListener(
-                    new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(final Animator animation) {
-                            if (newStatus != mStatus) return;
-                            animateButton(newButton, ANIMATION_IN);
-                        }
-                    });
+            animateButton(oldButton, ANIMATION_OUT).setListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(final Animator animation) {
+                    animateButtonIfStatusIsEqual(newButton, newStatus);
+                }
+            });
         } else if (null != oldButton) {
             animateButton(oldButton, ANIMATION_OUT);
         } else if (null != newButton) {
@@ -159,9 +163,8 @@
         if (ANIMATION_IN == direction) {
             button.setClickable(true);
             return button.animate().translationX(0);
-        } else {
-            button.setClickable(false);
-            return button.animate().translationX(outerX - innerX);
         }
+        button.setClickable(false);
+        return button.animate().translationX(outerX - innerX);
     }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java
index 1d84e58..7598520 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java
@@ -148,7 +148,7 @@
             }
         }
 
-        private class UpdateHelper implements Runnable {
+        class UpdateHelper implements Runnable {
             private int mProgress;
             @Override
             public void run() {
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
index 8e02617..836340a 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
@@ -32,7 +32,7 @@
  * in case some dictionaries appeared, disappeared, changed states etc.
  */
 public class DictionaryListInterfaceState {
-    private static class State {
+    static class State {
         public boolean mOpen = false;
         public int mStatus = MetadataDbHelper.STATUS_UNKNOWN;
     }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
index e748321..37fa76b 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
@@ -255,10 +255,9 @@
                 if (null != dictFiles && dictFiles.size() > 0) {
                     PrivateLog.log("Returned " + dictFiles.size() + " files");
                     return new ResourcePathCursor(dictFiles);
-                } else {
-                    PrivateLog.log("No dictionary files for this URL");
-                    return new ResourcePathCursor(Collections.<WordListInfo>emptyList());
                 }
+                PrivateLog.log("No dictionary files for this URL");
+                return new ResourcePathCursor(Collections.<WordListInfo>emptyList());
             // V2_METADATA and V2_DATAFILE are not supported for query()
             default:
                 return null;
@@ -319,14 +318,13 @@
                 final AssetFileDescriptor afd = getContext().getResources().openRawResourceFd(
                         R.raw.empty);
                 return afd;
-            } else {
-                final String localFilename =
-                        wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
-                final File f = getContext().getFileStreamPath(localFilename);
-                final ParcelFileDescriptor pfd =
-                        ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
-                return new AssetFileDescriptor(pfd, 0, pfd.getStatSize());
             }
+            final String localFilename =
+                    wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
+            final File f = getContext().getFileStreamPath(localFilename);
+            final ParcelFileDescriptor pfd =
+                    ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
+            return new AssetFileDescriptor(pfd, 0, pfd.getStatSize());
         } catch (FileNotFoundException e) {
             // No file : fall through and return null
         }
@@ -461,13 +459,16 @@
         final String wordlistId = uri.getLastPathSegment();
         final String clientId = getClientId(uri);
         final ContentValues wordList = getWordlistMetadataForWordlistId(clientId, wordlistId);
-        if (null == wordList) return 0;
+        if (null == wordList) {
+            return 0;
+        }
         final int status = wordList.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
         final int version = wordList.getAsInteger(MetadataDbHelper.VERSION_COLUMN);
         if (MetadataDbHelper.STATUS_DELETING == status) {
             UpdateHandler.markAsDeleted(getContext(), clientId, wordlistId, version, status);
             return 1;
-        } else if (MetadataDbHelper.STATUS_INSTALLED == status) {
+        }
+        if (MetadataDbHelper.STATUS_INSTALLED == status) {
             final String result = uri.getQueryParameter(QUERY_PARAMETER_DELETE_RESULT);
             if (QUERY_PARAMETER_FAILURE.equals(result)) {
                 if (DEBUG) {
@@ -480,15 +481,10 @@
                     wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
             final File f = getContext().getFileStreamPath(localFilename);
             // f.delete() returns true if the file was successfully deleted, false otherwise
-            if (f.delete()) {
-                return 1;
-            } else {
-                return 0;
-            }
-        } else {
-            Log.e(TAG, "Attempt to delete a file whose status is " + status);
-            return 0;
+            return f.delete() ? 1 : 0;
         }
+        Log.e(TAG, "Attempt to delete a file whose status is " + status);
+        return 0;
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
index 568c80a..e9b634e 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
@@ -179,7 +179,7 @@
         return Service.START_REDELIVER_INTENT;
     }
 
-    private static void dispatchBroadcast(final Context context, final Intent intent) {
+    static void dispatchBroadcast(final Context context, final Intent intent) {
         if (DATE_CHANGED_INTENT_ACTION.equals(intent.getAction())) {
             // This happens when the date of the device changes. This normally happens
             // at midnight local time, but it may happen if the user changes the date
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
index 11982fa..c2dc879 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
@@ -31,7 +31,6 @@
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceGroup;
 import android.text.TextUtils;
-import android.text.format.DateUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -203,25 +202,19 @@
     @Override
     public void updateCycleCompleted() {}
 
-    private void refreshNetworkState() {
+    void refreshNetworkState() {
         NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
         boolean isConnected = null == info ? false : info.isConnected();
         if (null != mUpdateNowMenu) mUpdateNowMenu.setEnabled(isConnected);
     }
 
-    private void refreshInterface() {
+    void refreshInterface() {
         final Activity activity = getActivity();
         if (null == activity) return;
-        final long lastUpdateDate =
-                MetadataDbHelper.getLastUpdateDateForClient(getActivity(), mClientId);
         final PreferenceGroup prefScreen = getPreferenceScreen();
         final Collection<? extends Preference> prefList =
                 createInstalledDictSettingsCollection(mClientId);
 
-        final String updateNowSummary = getString(R.string.last_update) + " "
-                + DateUtils.formatDateTime(activity, lastUpdateDate,
-                        DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME);
-
         activity.runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
@@ -239,14 +232,14 @@
             });
     }
 
-    private Preference createErrorMessage(final Activity activity, final int messageResource) {
+    private static Preference createErrorMessage(final Activity activity, final int messageResource) {
         final Preference message = new Preference(activity);
         message.setTitle(messageResource);
         message.setEnabled(false);
         return message;
     }
 
-    private void removeAnyDictSettings(final PreferenceGroup prefGroup) {
+    static void removeAnyDictSettings(final PreferenceGroup prefGroup) {
         for (int i = prefGroup.getPreferenceCount() - 1; i >= 0; --i) {
             prefGroup.removePreference(prefGroup.getPreference(i));
         }
@@ -276,7 +269,7 @@
                 .appendQueryParameter(DictionaryProvider.QUERY_PARAMETER_PROTOCOL_VERSION, "2")
                 .build();
         final Activity activity = getActivity();
-        final Cursor cursor = null == activity ? null
+        final Cursor cursor = (null == activity) ? null
                 : activity.getContentResolver().query(contentUri, null, null, null, null);
 
         if (null == cursor) {
@@ -289,61 +282,57 @@
                 final ArrayList<Preference> result = new ArrayList<>();
                 result.add(createErrorMessage(activity, R.string.no_dictionaries_available));
                 return result;
-            } else {
-                final String systemLocaleString = Locale.getDefault().toString();
-                final TreeMap<String, WordListPreference> prefMap = new TreeMap<>();
-                final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
-                final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN);
-                final int localeIndex = cursor.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
-                final int descriptionIndex =
-                        cursor.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN);
-                final int statusIndex = cursor.getColumnIndex(MetadataDbHelper.STATUS_COLUMN);
-                final int filesizeIndex = cursor.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN);
-                do {
-                    final String wordlistId = cursor.getString(idIndex);
-                    final int version = cursor.getInt(versionIndex);
-                    final String localeString = cursor.getString(localeIndex);
-                    final Locale locale = new Locale(localeString);
-                    final String description = cursor.getString(descriptionIndex);
-                    final int status = cursor.getInt(statusIndex);
-                    final int matchLevel =
-                            LocaleUtils.getMatchLevel(systemLocaleString, localeString);
-                    final String matchLevelString =
-                            LocaleUtils.getMatchLevelSortedString(matchLevel);
-                    final int filesize = cursor.getInt(filesizeIndex);
-                    // The key is sorted in lexicographic order, according to the match level, then
-                    // the description.
-                    final String key = matchLevelString + "." + description + "." + wordlistId;
-                    final WordListPreference existingPref = prefMap.get(key);
-                    if (null == existingPref || existingPref.hasPriorityOver(status)) {
-                        final WordListPreference oldPreference = mCurrentPreferenceMap.get(key);
-                        final WordListPreference pref;
-                        if (null != oldPreference
-                                && oldPreference.mVersion == version
-                                && oldPreference.hasStatus(status)
-                                && oldPreference.mLocale.equals(locale)) {
-                            // If the old preference has all the new attributes, reuse it. Ideally,
-                            // we should reuse the old pref even if its status is different and call
-                            // setStatus here, but setStatus calls Preference#setSummary() which
-                            // needs to be done on the UI thread and we're not on the UI thread
-                            // here. We could do all this work on the UI thread, but in this case
-                            // it's probably lighter to stay on a background thread and throw this
-                            // old preference out.
-                            pref = oldPreference;
-                        } else {
-                            // Otherwise, discard it and create a new one instead.
-                            // TODO: when the status is different from the old one, we need to
-                            // animate the old one out before animating the new one in.
-                            pref = new WordListPreference(activity, mDictionaryListInterfaceState,
-                                    mClientId, wordlistId, version, locale, description, status,
-                                    filesize);
-                        }
-                        prefMap.put(key, pref);
-                    }
-                } while (cursor.moveToNext());
-                mCurrentPreferenceMap = prefMap;
-                return prefMap.values();
             }
+            final String systemLocaleString = Locale.getDefault().toString();
+            final TreeMap<String, WordListPreference> prefMap = new TreeMap<>();
+            final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
+            final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN);
+            final int localeIndex = cursor.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
+            final int descriptionIndex = cursor.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN);
+            final int statusIndex = cursor.getColumnIndex(MetadataDbHelper.STATUS_COLUMN);
+            final int filesizeIndex = cursor.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN);
+            do {
+                final String wordlistId = cursor.getString(idIndex);
+                final int version = cursor.getInt(versionIndex);
+                final String localeString = cursor.getString(localeIndex);
+                final Locale locale = new Locale(localeString);
+                final String description = cursor.getString(descriptionIndex);
+                final int status = cursor.getInt(statusIndex);
+                final int matchLevel = LocaleUtils.getMatchLevel(systemLocaleString, localeString);
+                final String matchLevelString = LocaleUtils.getMatchLevelSortedString(matchLevel);
+                final int filesize = cursor.getInt(filesizeIndex);
+                // The key is sorted in lexicographic order, according to the match level, then
+                // the description.
+                final String key = matchLevelString + "." + description + "." + wordlistId;
+                final WordListPreference existingPref = prefMap.get(key);
+                if (null == existingPref || existingPref.hasPriorityOver(status)) {
+                    final WordListPreference oldPreference = mCurrentPreferenceMap.get(key);
+                    final WordListPreference pref;
+                    if (null != oldPreference
+                            && oldPreference.mVersion == version
+                            && oldPreference.hasStatus(status)
+                            && oldPreference.mLocale.equals(locale)) {
+                        // If the old preference has all the new attributes, reuse it. Ideally,
+                        // we should reuse the old pref even if its status is different and call
+                        // setStatus here, but setStatus calls Preference#setSummary() which
+                        // needs to be done on the UI thread and we're not on the UI thread
+                        // here. We could do all this work on the UI thread, but in this case
+                        // it's probably lighter to stay on a background thread and throw this
+                        // old preference out.
+                        pref = oldPreference;
+                    } else {
+                        // Otherwise, discard it and create a new one instead.
+                        // TODO: when the status is different from the old one, we need to
+                        // animate the old one out before animating the new one in.
+                        pref = new WordListPreference(activity, mDictionaryListInterfaceState,
+                                mClientId, wordlistId, version, locale, description, status,
+                                filesize);
+                    }
+                    prefMap.put(key, pref);
+                }
+            } while (cursor.moveToNext());
+            mCurrentPreferenceMap = prefMap;
+            return prefMap.values();
         } finally {
             cursor.close();
         }
@@ -396,26 +385,28 @@
         if (null != mUpdateNowMenu) mUpdateNowMenu.setTitle(R.string.cancel);
     }
 
-    private void stopLoadingAnimation() {
+    void stopLoadingAnimation() {
         final View preferenceView = getView();
         final Activity activity = getActivity();
         if (null == activity) return;
+        final View loadingView = mLoadingView;
+        final MenuItem updateNowMenu = mUpdateNowMenu;
         activity.runOnUiThread(new Runnable() {
-                @Override
-                public void run() {
-                    mLoadingView.setVisibility(View.GONE);
-                    preferenceView.setVisibility(View.VISIBLE);
-                    mLoadingView.startAnimation(AnimationUtils.loadAnimation(
-                            getActivity(), android.R.anim.fade_out));
-                    preferenceView.startAnimation(AnimationUtils.loadAnimation(
-                            getActivity(), android.R.anim.fade_in));
-                    // The menu is created by the framework asynchronously after the activity,
-                    // which means it's possible to have the activity running but the menu not
-                    // created yet - hence the necessity for a null check here.
-                    if (null != mUpdateNowMenu) {
-                        mUpdateNowMenu.setTitle(R.string.check_for_updates_now);
-                    }
+            @Override
+            public void run() {
+                loadingView.setVisibility(View.GONE);
+                preferenceView.setVisibility(View.VISIBLE);
+                loadingView.startAnimation(AnimationUtils.loadAnimation(
+                        activity, android.R.anim.fade_out));
+                preferenceView.startAnimation(AnimationUtils.loadAnimation(
+                        activity, android.R.anim.fade_in));
+                // The menu is created by the framework asynchronously after the activity,
+                // which means it's possible to have the activity running but the menu not
+                // created yet - hence the necessity for a null check here.
+                if (null != updateNowMenu) {
+                    updateNowMenu.setTitle(R.string.check_for_updates_now);
                 }
-            });
+            }
+        });
     }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index c9e8f91..db4315f 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -226,7 +226,7 @@
         createClientTable(db);
     }
 
-    private void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db) {
+    private static void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db) {
         try {
             db.execSQL("SELECT " + RAW_CHECKSUM_COLUMN + " FROM "
                     + METADATA_TABLE_NAME + " LIMIT 0;");
@@ -237,7 +237,7 @@
         }
     }
 
-    private void addRetryCountColumnUnlessPresent(final SQLiteDatabase db) {
+    private static void addRetryCountColumnUnlessPresent(final SQLiteDatabase db) {
         try {
             db.execSQL("SELECT " + RETRY_COUNT_COLUMN + " FROM "
                     + METADATA_TABLE_NAME + " LIMIT 0;");
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java b/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
index 639d904..329b9f6 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
@@ -30,9 +30,6 @@
  * Helper class to easy up manipulation of dictionary pack metadata.
  */
 public class MetadataHandler {
-    @SuppressWarnings("unused")
-    private static final String TAG = "DictionaryProvider:" + MetadataHandler.class.getSimpleName();
-
     // The canonical file name for metadata. This is not the name of a real file on the
     // device, but a symbolic name used in the database and in metadata handling. It is never
     // tested against, only used for human-readability as the file name for the metadata.
diff --git a/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java b/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
index 67dd7b9..bb64721 100644
--- a/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
+++ b/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
@@ -43,8 +43,8 @@
             + COLUMN_DATE + " TEXT,"
             + COLUMN_EVENT + " TEXT);";
 
-    private static final SimpleDateFormat sDateFormat =
-            new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
+    static final SimpleDateFormat sDateFormat = new SimpleDateFormat(
+            "yyyy/MM/dd HH:mm:ss", Locale.ROOT);
 
     private static PrivateLog sInstance = new PrivateLog();
     private static DebugHelper sDebugHelper = null;
@@ -62,9 +62,9 @@
         }
     }
 
-    private static class DebugHelper extends SQLiteOpenHelper {
+    static class DebugHelper extends SQLiteOpenHelper {
 
-        private DebugHelper(final Context context) {
+        DebugHelper(final Context context) {
             super(context, LOG_DATABASE_NAME, null, LOG_DATABASE_VERSION);
         }
 
@@ -84,7 +84,7 @@
             insert(db, "Upgrade finished");
         }
 
-        private static void insert(SQLiteDatabase db, String event) {
+        static void insert(SQLiteDatabase db, String event) {
             if (!DEBUG) return;
             final ContentValues c = new ContentValues(2);
             c.put(COLUMN_DATE, sDateFormat.format(new Date(System.currentTimeMillis())));
diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
index 90a7504..d59b7a5 100644
--- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
@@ -59,6 +59,8 @@
 import java.util.Set;
 import java.util.TreeSet;
 
+import javax.annotation.Nullable;
+
 /**
  * Handler for the update process.
  *
@@ -750,19 +752,22 @@
      * @return an ordered list of runnables to be called to upgrade.
      */
     private static ActionBatch compareMetadataForUpgrade(final Context context,
-            final String clientId, List<WordListMetadata> from, List<WordListMetadata> to) {
+            final String clientId, @Nullable final List<WordListMetadata> from,
+            @Nullable final List<WordListMetadata> to) {
         final ActionBatch actions = new ActionBatch();
         // Upgrade existing word lists
         DebugLogUtils.l("Comparing dictionaries");
         final Set<String> wordListIds = new TreeSet<>();
         // TODO: Can these be null?
-        if (null == from) from = new ArrayList<>();
-        if (null == to) to = new ArrayList<>();
-        for (WordListMetadata wlData : from) wordListIds.add(wlData.mId);
-        for (WordListMetadata wlData : to) wordListIds.add(wlData.mId);
+        final List<WordListMetadata> fromList = (from == null) ? new ArrayList<WordListMetadata>()
+                : from;
+        final List<WordListMetadata> toList = (to == null) ? new ArrayList<WordListMetadata>()
+                : to;
+        for (WordListMetadata wlData : fromList) wordListIds.add(wlData.mId);
+        for (WordListMetadata wlData : toList) wordListIds.add(wlData.mId);
         for (String id : wordListIds) {
-            final WordListMetadata currentInfo = MetadataHandler.findWordListById(from, id);
-            final WordListMetadata metadataInfo = MetadataHandler.findWordListById(to, id);
+            final WordListMetadata currentInfo = MetadataHandler.findWordListById(fromList, id);
+            final WordListMetadata metadataInfo = MetadataHandler.findWordListById(toList, id);
             // TODO: Remove the following unnecessary check, since we are now doing the filtering
             // inside findWordListById.
             final WordListMetadata newInfo = null == metadataInfo
diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
index aea16af..500e39e 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
@@ -38,45 +38,39 @@
  * enable or delete it as appropriate for the current state of the word list.
  */
 public final class WordListPreference extends Preference {
-    static final private String TAG = WordListPreference.class.getSimpleName();
+    private static final String TAG = WordListPreference.class.getSimpleName();
 
     // What to display in the "status" field when we receive unknown data as a status from
     // the content provider. Empty string sounds sensible.
-    static final private String NO_STATUS_MESSAGE = "";
+    private static final String NO_STATUS_MESSAGE = "";
 
     /// Actions
-    static final private int ACTION_UNKNOWN = 0;
-    static final private int ACTION_ENABLE_DICT = 1;
-    static final private int ACTION_DISABLE_DICT = 2;
-    static final private int ACTION_DELETE_DICT = 3;
+    private static final int ACTION_UNKNOWN = 0;
+    private static final int ACTION_ENABLE_DICT = 1;
+    private static final int ACTION_DISABLE_DICT = 2;
+    private static final int ACTION_DELETE_DICT = 3;
 
     // Members
-    // The context to get resources
-    final Context mContext;
-    // The id of the client for which this preference is.
-    final String mClientId;
     // The metadata word list id and version of this word list.
     public final String mWordlistId;
     public final int mVersion;
     public final Locale mLocale;
     public final String mDescription;
+
+    // The id of the client for which this preference is.
+    private final String mClientId;
     // The status
     private int mStatus;
     // The size of the dictionary file
     private final int mFilesize;
 
     private final DictionaryListInterfaceState mInterfaceState;
-    private final OnWordListPreferenceClick mPreferenceClickHandler =
-            new OnWordListPreferenceClick();
-    private final OnActionButtonClick mActionButtonClickHandler =
-            new OnActionButtonClick();
 
     public WordListPreference(final Context context,
             final DictionaryListInterfaceState dictionaryListInterfaceState, final String clientId,
             final String wordlistId, final int version, final Locale locale,
             final String description, final int status, final int filesize) {
         super(context, null);
-        mContext = context;
         mInterfaceState = dictionaryListInterfaceState;
         mClientId = clientId;
         mVersion = version;
@@ -116,22 +110,23 @@
     }
 
     private String getSummary(final int status) {
+        final Context context = getContext();
         switch (status) {
-            // If we are deleting the word list, for the user it's like it's already deleted.
-            // It should be reinstallable. Exposing to the user the whole complexity of
-            // the delayed deletion process between the dictionary pack and Android Keyboard
-            // would only be confusing.
-            case MetadataDbHelper.STATUS_DELETING:
-            case MetadataDbHelper.STATUS_AVAILABLE:
-                return mContext.getString(R.string.dictionary_available);
-            case MetadataDbHelper.STATUS_DOWNLOADING:
-                return mContext.getString(R.string.dictionary_downloading);
-            case MetadataDbHelper.STATUS_INSTALLED:
-                return mContext.getString(R.string.dictionary_installed);
-            case MetadataDbHelper.STATUS_DISABLED:
-                return mContext.getString(R.string.dictionary_disabled);
-            default:
-                return NO_STATUS_MESSAGE;
+        // If we are deleting the word list, for the user it's like it's already deleted.
+        // It should be reinstallable. Exposing to the user the whole complexity of
+        // the delayed deletion process between the dictionary pack and Android Keyboard
+        // would only be confusing.
+        case MetadataDbHelper.STATUS_DELETING:
+        case MetadataDbHelper.STATUS_AVAILABLE:
+            return context.getString(R.string.dictionary_available);
+        case MetadataDbHelper.STATUS_DOWNLOADING:
+            return context.getString(R.string.dictionary_downloading);
+        case MetadataDbHelper.STATUS_INSTALLED:
+            return context.getString(R.string.dictionary_installed);
+        case MetadataDbHelper.STATUS_DISABLED:
+            return context.getString(R.string.dictionary_disabled);
+        default:
+            return NO_STATUS_MESSAGE;
         }
     }
 
@@ -154,7 +149,7 @@
         { ButtonSwitcher.STATUS_INSTALL, ACTION_ENABLE_DICT }
     };
 
-    private int getButtonSwitcherStatus(final int status) {
+    static int getButtonSwitcherStatus(final int status) {
         if (status >= sStatusActionList.length) {
             Log.e(TAG, "Unknown status " + status);
             return ButtonSwitcher.STATUS_NO_BUTTON;
@@ -162,7 +157,7 @@
         return sStatusActionList[status][0];
     }
 
-    private static int getActionIdFromStatusAndMenuEntry(final int status) {
+    static int getActionIdFromStatusAndMenuEntry(final int status) {
         if (status >= sStatusActionList.length) {
             Log.e(TAG, "Unknown status " + status);
             return ACTION_UNKNOWN;
@@ -171,9 +166,10 @@
     }
 
     private void disableDict() {
-        SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
+        final Context context = getContext();
+        final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
         CommonPreferences.disable(prefs, mWordlistId);
-        UpdateHandler.markAsUnused(mContext, mClientId, mWordlistId, mVersion, mStatus);
+        UpdateHandler.markAsUnused(context, mClientId, mWordlistId, mVersion, mStatus);
         if (MetadataDbHelper.STATUS_DOWNLOADING == mStatus) {
             setStatus(MetadataDbHelper.STATUS_AVAILABLE);
         } else if (MetadataDbHelper.STATUS_INSTALLED == mStatus) {
@@ -184,11 +180,13 @@
             Log.e(TAG, "Unexpected state of the word list for disabling " + mStatus);
         }
     }
+
     private void enableDict() {
-        SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
+        final Context context = getContext();
+        final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
         CommonPreferences.enable(prefs, mWordlistId);
         // Explicit enabling by the user : allow downloading on metered data connection.
-        UpdateHandler.markAsUsed(mContext, mClientId, mWordlistId, mVersion, mStatus, true);
+        UpdateHandler.markAsUsed(context, mClientId, mWordlistId, mVersion, mStatus, true);
         if (MetadataDbHelper.STATUS_AVAILABLE == mStatus) {
             setStatus(MetadataDbHelper.STATUS_DOWNLOADING);
         } else if (MetadataDbHelper.STATUS_DISABLED == mStatus
@@ -203,11 +201,13 @@
             Log.e(TAG, "Unexpected state of the word list for enabling " + mStatus);
         }
     }
+
     private void deleteDict() {
-        SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
+        final Context context = getContext();
+        final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
         CommonPreferences.disable(prefs, mWordlistId);
         setStatus(MetadataDbHelper.STATUS_DELETING);
-        UpdateHandler.markAsDeleting(mContext, mClientId, mWordlistId, mVersion, mStatus);
+        UpdateHandler.markAsDeleting(context, mClientId, mWordlistId, mVersion, mStatus);
     }
 
     @Override
@@ -225,8 +225,8 @@
         status.setVisibility(showProgressBar ? View.INVISIBLE : View.VISIBLE);
         progressBar.setVisibility(showProgressBar ? View.VISIBLE : View.INVISIBLE);
 
-        final ButtonSwitcher buttonSwitcher =
-                (ButtonSwitcher)view.findViewById(R.id.wordlist_button_switcher);
+        final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)view.findViewById(
+                R.id.wordlist_button_switcher);
         // We need to clear the state of the button switcher, because we reuse views; if we didn't
         // reset it would animate from whatever its old state was.
         buttonSwitcher.reset(mInterfaceState);
@@ -244,63 +244,67 @@
             // The button is closed.
             buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
         }
-        buttonSwitcher.setInternalOnClickListener(mActionButtonClickHandler);
-        view.setOnClickListener(mPreferenceClickHandler);
+        buttonSwitcher.setInternalOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                onActionButtonClicked();
+            }
+        });
+        view.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                onWordListClicked(v);
+            }
+        });
     }
 
-    private class OnWordListPreferenceClick implements View.OnClickListener {
-        @Override
-        public void onClick(final View v) {
-            // Note : v is the preference view
-            final ViewParent parent = v.getParent();
-            // Just in case something changed in the framework, test for the concrete class
-            if (!(parent instanceof ListView)) return;
-            final ListView listView = (ListView)parent;
-            final int indexToOpen;
-            // Close all first, we'll open back any item that needs to be open.
-            final boolean wasOpen = mInterfaceState.isOpen(mWordlistId);
-            mInterfaceState.closeAll();
-            if (wasOpen) {
-                // This button being shown. Take note that we don't want to open any button in the
-                // loop below.
-                indexToOpen = -1;
+    void onWordListClicked(final View v) {
+        // Note : v is the preference view
+        final ViewParent parent = v.getParent();
+        // Just in case something changed in the framework, test for the concrete class
+        if (!(parent instanceof ListView)) return;
+        final ListView listView = (ListView)parent;
+        final int indexToOpen;
+        // Close all first, we'll open back any item that needs to be open.
+        final boolean wasOpen = mInterfaceState.isOpen(mWordlistId);
+        mInterfaceState.closeAll();
+        if (wasOpen) {
+            // This button being shown. Take note that we don't want to open any button in the
+            // loop below.
+            indexToOpen = -1;
+        } else {
+            // This button was not being shown. Open it, and remember the index of this
+            // child as the one to open in the following loop.
+            mInterfaceState.setOpen(mWordlistId, mStatus);
+            indexToOpen = listView.indexOfChild(v);
+        }
+        final int lastDisplayedIndex =
+                listView.getLastVisiblePosition() - listView.getFirstVisiblePosition();
+        // The "lastDisplayedIndex" is actually displayed, hence the <=
+        for (int i = 0; i <= lastDisplayedIndex; ++i) {
+            final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)listView.getChildAt(i)
+                    .findViewById(R.id.wordlist_button_switcher);
+            if (i == indexToOpen) {
+                buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus));
             } else {
-                // This button was not being shown. Open it, and remember the index of this
-                // child as the one to open in the following loop.
-                mInterfaceState.setOpen(mWordlistId, mStatus);
-                indexToOpen = listView.indexOfChild(v);
-            }
-            final int lastDisplayedIndex =
-                    listView.getLastVisiblePosition() - listView.getFirstVisiblePosition();
-            // The "lastDisplayedIndex" is actually displayed, hence the <=
-            for (int i = 0; i <= lastDisplayedIndex; ++i) {
-                final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)listView.getChildAt(i)
-                        .findViewById(R.id.wordlist_button_switcher);
-                if (i == indexToOpen) {
-                    buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus));
-                } else {
-                    buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
-                }
+                buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
             }
         }
     }
 
-    private class OnActionButtonClick implements View.OnClickListener {
-        @Override
-        public void onClick(final View v) {
-            switch (getActionIdFromStatusAndMenuEntry(mStatus)) {
-            case ACTION_ENABLE_DICT:
-                enableDict();
-                break;
-            case ACTION_DISABLE_DICT:
-                disableDict();
-                break;
-            case ACTION_DELETE_DICT:
-                deleteDict();
-                break;
-            default:
-                Log.e(TAG, "Unknown menu item pressed");
-            }
+    void onActionButtonClicked() {
+        switch (getActionIdFromStatusAndMenuEntry(mStatus)) {
+        case ACTION_ENABLE_DICT:
+            enableDict();
+            break;
+        case ACTION_DISABLE_DICT:
+            disableDict();
+            break;
+        case ACTION_DELETE_DICT:
+            deleteDict();
+            break;
+        default:
+            Log.e(TAG, "Unknown menu item pressed");
         }
     }
 }
diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
index 88c7063..2e65a08 100644
--- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
+++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
@@ -18,7 +18,6 @@
 
 import android.text.TextUtils;
 import android.util.SparseIntArray;
-import android.view.KeyCharacterMap;
 
 import com.android.inputmethod.latin.Constants;
 
@@ -70,8 +69,8 @@
         /**
          * Maps Unicode combining diacritical to display-form dead key.
          */
-        private static final SparseIntArray sCombiningToAccent = new SparseIntArray();
-        private static final SparseIntArray sAccentToCombining = new SparseIntArray();
+        static final SparseIntArray sCombiningToAccent = new SparseIntArray();
+        static final SparseIntArray sAccentToCombining = new SparseIntArray();
         static {
             // U+0300: COMBINING GRAVE ACCENT
             addCombining('\u0300', ACCENT_GRAVE);
@@ -217,21 +216,20 @@
     final StringBuilder mDeadSequence = new StringBuilder();
 
     @Nonnull
-    private Event createEventChainFromSequence(final @Nonnull CharSequence text,
+    private static Event createEventChainFromSequence(final @Nonnull CharSequence text,
             final Event originalEvent) {
         if (text.length() <= 0) {
             return originalEvent;
-        } else {
-            Event lastEvent = null;
-            int codePoint = 0;
-            for (int i = text.length(); i > 0; i -= Character.charCount(codePoint)) {
-                codePoint = Character.codePointBefore(text, i);
-                final Event thisEvent = Event.createHardwareKeypressEvent(codePoint,
-                        originalEvent.mKeyCode, lastEvent, false /* isKeyRepeat */);
-                lastEvent = thisEvent;
-            }
-            return lastEvent;
         }
+        Event lastEvent = null;
+        int codePoint = 0;
+        for (int i = text.length(); i > 0; i -= Character.charCount(codePoint)) {
+            codePoint = Character.codePointBefore(text, i);
+            final Event thisEvent = Event.createHardwareKeypressEvent(codePoint,
+                    originalEvent.mKeyCode, lastEvent, false /* isKeyRepeat */);
+            lastEvent = thisEvent;
+        }
+        return lastEvent;
     }
 
     @Override
@@ -248,51 +246,49 @@
             // no dead keys at all in the current input, so this combiner has nothing to do and
             // simply returns the event as is. The majority of events will go through this path.
             return event;
-        } else {
-            if (Character.isWhitespace(event.mCodePoint)
-                    || event.mCodePoint == mDeadSequence.codePointBefore(mDeadSequence.length())) {
-                // When whitespace or twice the same dead key, we should output the dead sequence
-                // as is.
-                final Event resultEvent = createEventChainFromSequence(mDeadSequence.toString(),
-                        event);
-                mDeadSequence.setLength(0);
-                return resultEvent;
-            } else if (event.isFunctionalKeyEvent()) {
-                if (Constants.CODE_DELETE == event.mKeyCode) {
-                    // Remove the last code point
-                    final int trimIndex = mDeadSequence.length() - Character.charCount(
-                            mDeadSequence.codePointBefore(mDeadSequence.length()));
-                    mDeadSequence.setLength(trimIndex);
-                    return Event.createConsumedEvent(event);
-                } else {
-                    return event;
-                }
-            } else if (event.isDead()) {
-                mDeadSequence.appendCodePoint(event.mCodePoint);
-                return Event.createConsumedEvent(event);
-            } else {
-                // Combine normally.
-                final StringBuilder sb = new StringBuilder();
-                sb.appendCodePoint(event.mCodePoint);
-                int codePointIndex = 0;
-                while (codePointIndex < mDeadSequence.length()) {
-                    final int deadCodePoint = mDeadSequence.codePointAt(codePointIndex);
-                    final char replacementSpacingChar =
-                            Data.getNonstandardCombination(deadCodePoint, event.mCodePoint);
-                    if (Data.NOT_A_CHAR != replacementSpacingChar) {
-                        sb.setCharAt(0, replacementSpacingChar);
-                    } else {
-                        final int combining = Data.sAccentToCombining.get(deadCodePoint);
-                        sb.appendCodePoint(0 == combining ? deadCodePoint : combining);
-                    }
-                    codePointIndex += Character.isSupplementaryCodePoint(deadCodePoint) ? 2 : 1;
-                }
-                final String normalizedString = Normalizer.normalize(sb, Normalizer.Form.NFC);
-                final Event resultEvent = createEventChainFromSequence(normalizedString, event);
-                mDeadSequence.setLength(0);
-                return resultEvent;
-            }
         }
+        if (Character.isWhitespace(event.mCodePoint)
+                || event.mCodePoint == mDeadSequence.codePointBefore(mDeadSequence.length())) {
+            // When whitespace or twice the same dead key, we should output the dead sequence as is.
+            final Event resultEvent = createEventChainFromSequence(mDeadSequence.toString(),
+                    event);
+            mDeadSequence.setLength(0);
+            return resultEvent;
+        }
+        if (event.isFunctionalKeyEvent()) {
+            if (Constants.CODE_DELETE == event.mKeyCode) {
+                // Remove the last code point
+                final int trimIndex = mDeadSequence.length() - Character.charCount(
+                        mDeadSequence.codePointBefore(mDeadSequence.length()));
+                mDeadSequence.setLength(trimIndex);
+                return Event.createConsumedEvent(event);
+            }
+            return event;
+        }
+        if (event.isDead()) {
+            mDeadSequence.appendCodePoint(event.mCodePoint);
+            return Event.createConsumedEvent(event);
+        }
+        // Combine normally.
+        final StringBuilder sb = new StringBuilder();
+        sb.appendCodePoint(event.mCodePoint);
+        int codePointIndex = 0;
+        while (codePointIndex < mDeadSequence.length()) {
+            final int deadCodePoint = mDeadSequence.codePointAt(codePointIndex);
+            final char replacementSpacingChar =
+                    Data.getNonstandardCombination(deadCodePoint, event.mCodePoint);
+            if (Data.NOT_A_CHAR != replacementSpacingChar) {
+                sb.setCharAt(0, replacementSpacingChar);
+            } else {
+                final int combining = Data.sAccentToCombining.get(deadCodePoint);
+                sb.appendCodePoint(0 == combining ? deadCodePoint : combining);
+            }
+            codePointIndex += Character.isSupplementaryCodePoint(deadCodePoint) ? 2 : 1;
+        }
+        final String normalizedString = Normalizer.normalize(sb, Normalizer.Form.NFC);
+        final Event resultEvent = createEventChainFromSequence(normalizedString, event);
+        mDeadSequence.setLength(0);
+        return resultEvent;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index ff6f880..3e3ff77 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -21,6 +21,8 @@
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.utils.StringUtils;
 
+import javax.annotation.Nonnull;
+
 /**
  * Class representing a generic input event as handled by Latin IME.
  *
@@ -134,12 +136,14 @@
         }
     }
 
+    @Nonnull
     public static Event createSoftwareKeypressEvent(final int codePoint, final int keyCode,
             final int x, final int y, final boolean isKeyRepeat) {
         return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, x, y,
                 null /* suggestedWordInfo */, isKeyRepeat ? FLAG_REPEAT : FLAG_NONE, null);
     }
 
+    @Nonnull
     public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode,
             final Event next, final boolean isKeyRepeat) {
         return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
@@ -149,6 +153,7 @@
 
     // This creates an input event for a dead character. @see {@link #FLAG_DEAD}
     @ExternallyReferenced
+    @Nonnull
     public static Event createDeadEvent(final int codePoint, final int keyCode, final Event next) {
         // TODO: add an argument or something if we ever create a software layout with dead keys.
         return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
@@ -163,6 +168,7 @@
      * @param codePoint the code point.
      * @return an event for this code point.
      */
+    @Nonnull
     public static Event createEventForCodePointFromUnknownSource(final int codePoint) {
         // TODO: should we have a different type of event for this? After all, it's not a key press.
         return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE,
@@ -178,6 +184,7 @@
      * @param y the Y coordinate.
      * @return an event for this code point and coordinates.
      */
+    @Nonnull
     public static Event createEventForCodePointFromAlreadyTypedText(final int codePoint,
             final int x, final int y) {
         // TODO: should we have a different type of event for this? After all, it's not a key press.
@@ -189,6 +196,7 @@
      * Creates an input event representing the manual pick of a suggestion.
      * @return an event for this suggestion pick.
      */
+    @Nonnull
     public static Event createSuggestionPickedEvent(final SuggestedWordInfo suggestedWordInfo) {
         return new Event(EVENT_TYPE_SUGGESTION_PICKED, suggestedWordInfo.mWord,
                 NOT_A_CODE_POINT, NOT_A_KEY_CODE,
@@ -204,6 +212,7 @@
      * @param keyCode the key code, or NOT_A_KEYCODE if not applicable.
      * @return an event for this text.
      */
+    @Nonnull
     public static Event createSoftwareTextEvent(final CharSequence text, final int keyCode) {
         return new Event(EVENT_TYPE_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode,
                 Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
@@ -228,6 +237,7 @@
      * @param source the event to copy the properties of.
      * @return an identical event marked as consumed.
      */
+    @Nonnull
     public static Event createConsumedEvent(final Event source) {
         // A consumed event should not input any text at all, so we pass the empty string as text.
         return new Event(source.mEventType, source.mText, source.mCodePoint, source.mKeyCode,
@@ -235,6 +245,7 @@
                 source.mNextEvent);
     }
 
+    @Nonnull
     public static Event createNotHandledEvent() {
         return new Event(EVENT_TYPE_NOT_HANDLED, null /* text */, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
                 Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
diff --git a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
index c61f45e..6aa6043 100644
--- a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
+++ b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
@@ -67,10 +67,9 @@
                 if (keyEvent.isShiftPressed()) {
                     return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT,
                             Constants.CODE_SHIFT_ENTER, null /* next */, isKeyRepeat);
-                } else {
-                    return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode,
-                            null /* next */, isKeyRepeat);
                 }
+                return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode,
+                        null /* next */, isKeyRepeat);
             }
             // If not Enter, then this is just a regular keypress event for a normal character
             // that can be committed right away, taking into account the current state.
diff --git a/java/src/com/android/inputmethod/event/MyanmarReordering.java b/java/src/com/android/inputmethod/event/MyanmarReordering.java
index dcd06c8..40b5439 100644
--- a/java/src/com/android/inputmethod/event/MyanmarReordering.java
+++ b/java/src/com/android/inputmethod/event/MyanmarReordering.java
@@ -115,6 +115,7 @@
      * @param newEvent the new event to add to the stream. null if none.
      * @return the resulting software text event. Never null.
      */
+    @Nonnull
     private Event clearAndGetResultingEvent(final Event newEvent) {
         final CharSequence combinedText;
         if (mCurrentEvents.size() > 0) {
@@ -139,7 +140,8 @@
             if (null == lastEvent) {
                 mCurrentEvents.add(newEvent);
                 return Event.createConsumedEvent(newEvent);
-            } else if (isConsonantOrMedial(lastEvent.mCodePoint)) {
+            }
+            if (isConsonantOrMedial(lastEvent.mCodePoint)) {
                 final Event resultingEvent = clearAndGetResultingEvent(null);
                 mCurrentEvents.add(Event.createSoftwareKeypressEvent(ZERO_WIDTH_NON_JOINER,
                         Event.NOT_A_KEY_CODE,
@@ -147,15 +149,17 @@
                         false /* isKeyRepeat */));
                 mCurrentEvents.add(newEvent);
                 return resultingEvent;
-            } else { // VOWEL_E == lastCodePoint. But if that was anything else this is correct too.
-                return clearAndGetResultingEvent(newEvent);
             }
-        } if (isConsonant(codePoint)) {
+            // VOWEL_E == lastCodePoint. But if that was anything else this is correct too.
+            return clearAndGetResultingEvent(newEvent);
+        }
+        if (isConsonant(codePoint)) {
             final Event lastEvent = getLastEvent();
             if (null == lastEvent) {
                 mCurrentEvents.add(newEvent);
                 return Event.createConsumedEvent(newEvent);
-            } else if (VOWEL_E == lastEvent.mCodePoint) {
+            }
+            if (VOWEL_E == lastEvent.mCodePoint) {
                 final int eventSize = mCurrentEvents.size();
                 if (eventSize >= 2
                         && mCurrentEvents.get(eventSize - 2).mCodePoint == ZERO_WIDTH_NON_JOINER) {
@@ -178,15 +182,17 @@
                 mCurrentEvents.add(newEvent);
                 mCurrentEvents.add(lastEvent);
                 return Event.createConsumedEvent(newEvent);
-            } else { // lastCodePoint is a consonant/medial. But if it's something else it's fine
-                return clearAndGetResultingEvent(newEvent);
             }
-        } else if (isMedial(codePoint)) {
+            // lastCodePoint is a consonant/medial. But if it's something else it's fine
+            return clearAndGetResultingEvent(newEvent);
+        }
+        if (isMedial(codePoint)) {
             final Event lastEvent = getLastEvent();
             if (null == lastEvent) {
                 mCurrentEvents.add(newEvent);
                 return Event.createConsumedEvent(newEvent);
-            } else if (VOWEL_E == lastEvent.mCodePoint) {
+            }
+            if (VOWEL_E == lastEvent.mCodePoint) {
                 final int eventSize = mCurrentEvents.size();
                 // If there is already a consonant, then we are in the middle of a syllable, and we
                 // need to reorder.
@@ -205,37 +211,36 @@
                 }
                 // Otherwise, we just commit everything.
                 return clearAndGetResultingEvent(null);
-            } else { // lastCodePoint is a consonant/medial. But if it's something else it's fine
-                return clearAndGetResultingEvent(newEvent);
             }
-        } else if (Constants.CODE_DELETE == newEvent.mKeyCode) {
-            final Event lastEvent = getLastEvent();
+            // lastCodePoint is a consonant/medial. But if it's something else it's fine
+            return clearAndGetResultingEvent(newEvent);
+        }
+        final Event lastEvent = getLastEvent();
+        if (Constants.CODE_DELETE == newEvent.mKeyCode && null != lastEvent) {
             final int eventSize = mCurrentEvents.size();
-            if (null != lastEvent) {
-                if (VOWEL_E == lastEvent.mCodePoint) {
-                    // We have a VOWEL_E at the end. There are four cases.
-                    // - The vowel is the only code point in the buffer. Remove it.
-                    // - The vowel is preceded by a ZWNJ. Remove both vowel E and ZWNJ.
-                    // - The vowel is preceded by a consonant/medial, remove the consonant/medial.
-                    // - In all other cases, it's strange, so just remove the last code point.
-                    if (eventSize <= 1) {
-                        mCurrentEvents.clear();
-                    } else { // eventSize >= 2
-                        final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint;
-                        if (previousCodePoint == ZERO_WIDTH_NON_JOINER) {
-                            mCurrentEvents.remove(eventSize - 1);
-                            mCurrentEvents.remove(eventSize - 2);
-                        } else if (isConsonantOrMedial(previousCodePoint)) {
-                            mCurrentEvents.remove(eventSize - 2);
-                        } else {
-                            mCurrentEvents.remove(eventSize - 1);
-                        }
+            if (VOWEL_E == lastEvent.mCodePoint) {
+                // We have a VOWEL_E at the end. There are four cases.
+                // - The vowel is the only code point in the buffer. Remove it.
+                // - The vowel is preceded by a ZWNJ. Remove both vowel E and ZWNJ.
+                // - The vowel is preceded by a consonant/medial, remove the consonant/medial.
+                // - In all other cases, it's strange, so just remove the last code point.
+                if (eventSize <= 1) {
+                    mCurrentEvents.clear();
+                } else { // eventSize >= 2
+                    final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint;
+                    if (previousCodePoint == ZERO_WIDTH_NON_JOINER) {
+                        mCurrentEvents.remove(eventSize - 1);
+                        mCurrentEvents.remove(eventSize - 2);
+                    } else if (isConsonantOrMedial(previousCodePoint)) {
+                        mCurrentEvents.remove(eventSize - 2);
+                    } else {
+                        mCurrentEvents.remove(eventSize - 1);
                     }
-                    return Event.createConsumedEvent(newEvent);
-                } else if (eventSize > 0) {
-                    mCurrentEvents.remove(eventSize - 1);
-                    return Event.createConsumedEvent(newEvent);
                 }
+                return Event.createConsumedEvent(newEvent);
+            } else if (eventSize > 0) {
+                mCurrentEvents.remove(eventSize - 1);
+                return Event.createConsumedEvent(newEvent);
             }
         }
         // This character is not part of the combining scheme, so we should reset everything.
@@ -243,10 +248,9 @@
             // If we have events in flight, then add the new event and return the resulting event.
             mCurrentEvents.add(newEvent);
             return clearAndGetResultingEvent(null);
-        } else {
-            // If we don't have any events in flight, then just pass this one through.
-            return newEvent;
         }
+        // If we don't have any events in flight, then just pass this one through.
+        return newEvent;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index ab0d633..36ca97d 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -25,7 +25,6 @@
 import com.android.inputmethod.compat.EditorInfoCompatUtils;
 import com.android.inputmethod.latin.RichInputMethodSubtype;
 import com.android.inputmethod.latin.utils.InputTypeUtils;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.util.Arrays;
 import java.util.Locale;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index 1c66c37..2344284 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -40,7 +40,6 @@
 import com.android.inputmethod.latin.RichInputMethodSubtype;
 import com.android.inputmethod.latin.SubtypeSwitcher;
 import com.android.inputmethod.latin.define.DebugFlags;
-import com.android.inputmethod.latin.utils.DebugLogUtils;
 import com.android.inputmethod.latin.utils.InputTypeUtils;
 import com.android.inputmethod.latin.utils.ScriptUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
@@ -424,9 +423,8 @@
                     final String tag = parser.getName();
                     if (TAG_KEYBOARD_SET.equals(tag)) {
                         break;
-                    } else {
-                        throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_KEYBOARD_SET);
                     }
+                    throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_KEYBOARD_SET);
                 }
             }
         }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 93123d1..3bcce4f 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -273,6 +273,7 @@
     }
 
     // Future method for requesting an updating to the shift state.
+    @Override
     public void requestUpdatingShiftState(final int currentAutoCapsState,
             final int currentRecapitalizeState) {
         mState.onUpdateShiftState(currentAutoCapsState, currentRecapitalizeState);
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 9c5abcd..fdf8ef8 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -17,7 +17,6 @@
 package com.android.inputmethod.keyboard;
 
 import android.graphics.Rect;
-import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.inputmethod.keyboard.internal.TouchPositionCorrection;
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecorator.java b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
index 2b7d2ce..79e2206 100644
--- a/java/src/com/android/inputmethod/keyboard/TextDecorator.java
+++ b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
@@ -181,7 +181,7 @@
         layoutMain();
     }
 
-    private void layoutMain() {
+    void layoutMain() {
         final CursorAnchorInfoCompatWrapper info = mCursorAnchorInfoWrapper;
 
         if (info == null) {
@@ -289,7 +289,7 @@
                 mHasRtlCharsInLastComposingText);
     }
 
-    private void onClickIndicator() {
+    void onClickIndicator() {
         if (mMode != MODE_SHOWING_INDICATOR) {
             return;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
index 0f9dc85..440d64b 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
@@ -147,7 +147,7 @@
         mShownCategories.add(properties);
     }
 
-    public String getCategoryName(final int categoryId, final int categoryPageId) {
+    public static String getCategoryName(final int categoryId, final int categoryPageId) {
         return sCategoryName[categoryId] + "-" + categoryPageId;
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
index 925ec6b..54d3e3b 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
@@ -138,6 +138,21 @@
         return mKeyDetector.detectHitKey(x, y);
     }
 
+    void callListenerOnReleaseKey(final Key releasedKey, final boolean withKeyRegistering) {
+        releasedKey.onReleased();
+        invalidateKey(releasedKey);
+        if (withKeyRegistering) {
+            mListener.onReleaseKey(releasedKey);
+        }
+    }
+
+    void callListenerOnPressKey(final Key pressedKey) {
+        mPendingKeyDown = null;
+        pressedKey.onReleased();
+        invalidateKey(pressedKey);
+        mListener.onPressKey(pressedKey);
+    }
+
     public void releaseCurrentKey(final boolean withKeyRegistering) {
         mHandler.removeCallbacks(mPendingKeyDown);
         mPendingKeyDown = null;
@@ -145,11 +160,7 @@
         if (currentKey == null) {
             return;
         }
-        currentKey.onReleased();
-        invalidateKey(currentKey);
-        if (withKeyRegistering) {
-            mListener.onReleaseKey(currentKey);
-        }
+        callListenerOnReleaseKey(currentKey, withKeyRegistering);
         mCurrentKey = null;
     }
 
@@ -165,10 +176,7 @@
         mPendingKeyDown = new Runnable() {
             @Override
             public void run() {
-                mPendingKeyDown = null;
-                key.onPressed();
-                invalidateKey(key);
-                mListener.onPressKey(key);
+                callListenerOnPressKey(key);
             }
         };
         mHandler.postDelayed(mPendingKeyDown, KEY_PRESS_DELAY_TIME);
@@ -195,15 +203,11 @@
             mHandler.postDelayed(new Runnable() {
                 @Override
                 public void run() {
-                    key.onReleased();
-                    invalidateKey(key);
-                    mListener.onReleaseKey(key);
+                    callListenerOnReleaseKey(key, true /* withRegistering */);
                 }
             }, KEY_RELEASE_DELAY_TIME);
         } else {
-            key.onReleased();
-            invalidateKey(key);
-            mListener.onReleaseKey(key);
+            callListenerOnReleaseKey(key, true /* withRegistering */);
         }
         return true;
     }
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
index e37cd23..1157f85 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
@@ -149,7 +149,7 @@
     }
 
     private void addTab(final TabHost host, final int categoryId) {
-        final String tabId = mEmojiCategory.getCategoryName(categoryId, 0 /* categoryPageId */);
+        final String tabId = EmojiCategory.getCategoryName(categoryId, 0 /* categoryPageId */);
         final TabHost.TabSpec tspec = host.newTabSpec(tabId);
         tspec.setContent(R.id.emoji_keyboard_dummy);
         final ImageView iconView = (ImageView)LayoutInflater.from(getContext()).inflate(
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
index 5005b7d..ddb193e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
@@ -148,7 +148,7 @@
         keyPreviewView.setPivotY(previewHeight);
     }
 
-    private void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
+    void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
             final boolean withAnimation) {
         if (!withAnimation) {
             keyPreviewView.setVisibility(View.VISIBLE);
@@ -166,25 +166,25 @@
     }
 
     public Animator createShowUpAnimator(final Key key, final KeyPreviewView keyPreviewView) {
-        final Animator animator = mParams.createShowUpAnimator(keyPreviewView);
-        animator.addListener(new AnimatorListenerAdapter() {
+        final Animator showUpAnimator = mParams.createShowUpAnimator(keyPreviewView);
+        showUpAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(final Animator animator) {
                 showKeyPreview(key, keyPreviewView, false /* withAnimation */);
             }
         });
-        return animator;
+        return showUpAnimator;
     }
 
     private Animator createDismissAnimator(final Key key, final KeyPreviewView keyPreviewView) {
-        final Animator animator = mParams.createDismissAnimator(keyPreviewView);
-        animator.addListener(new AnimatorListenerAdapter() {
+        final Animator dismissAnimator = mParams.createDismissAnimator(keyPreviewView);
+        dismissAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(final Animator animator) {
                 dismissKeyPreview(key, false /* withAnimation */);
             }
         });
-        return animator;
+        return dismissAnimator;
     }
 
     private static class KeyPreviewAnimators extends AnimatorListenerAdapter {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index f4e010c..f581822 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -733,18 +733,18 @@
         }
     }
 
-    private boolean matchLocaleCodes(TypedArray caseAttr, final Locale[] locales) {
+    private static boolean matchLocaleCodes(TypedArray caseAttr, final Locale[] locales) {
         // TODO: adujst this for multilingual input
         return matchString(caseAttr, R.styleable.Keyboard_Case_localeCode, locales[0].toString());
     }
 
-    private boolean matchLanguageCodes(TypedArray caseAttr, Locale[] locales) {
+    private static boolean matchLanguageCodes(TypedArray caseAttr, Locale[] locales) {
         // TODO: adujst this for multilingual input
         return matchString(caseAttr, R.styleable.Keyboard_Case_languageCode,
                 locales[0].getLanguage());
     }
 
-    private boolean matchCountryCodes(TypedArray caseAttr, Locale[] locales) {
+    private static boolean matchCountryCodes(TypedArray caseAttr, Locale[] locales) {
         // TODO: adujst this for multilingual input
         return matchString(caseAttr, R.styleable.Keyboard_Case_countryCode,
                 locales[0].getCountry());
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java b/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java
index c1f3749..d927cc3 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java
@@ -28,7 +28,8 @@
  */
 @UsedForTesting
 public class MatrixUtils {
-    private static final String TAG = MatrixUtils.class.getSimpleName();
+    static final String TAG = MatrixUtils.class.getSimpleName();
+
     public static class MatrixOperationFailedException extends Exception {
         private static final long serialVersionUID = 4384485606788583829L;
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
index 0cd031e..eed3cb6 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
@@ -108,9 +108,8 @@
                 : Constants.printableCode(mCode));
         if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) {
             return output;
-        } else {
-            return label + "|" + output;
         }
+        return label + "|" + output;
     }
 
     public static class LettersOnBaseLayout {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
index fef97cc..a2ebc9c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
@@ -80,6 +80,7 @@
         return mRadii.length;
     }
 
+    @SuppressWarnings("static-method")
     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/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 867c186..974fb14 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -121,12 +121,11 @@
                 // reason some dictionaries have been installed BUT the dictionary pack can't be
                 // found anymore it's safer to actually supply installed dictionaries.
                 return true;
-            } else {
-                // The default is true here for the same reasons as above. We got the dictionary
-                // pack but if we don't have any settings for it it means the user has never been
-                // to the settings yet. So by default, the main dictionaries should be on.
-                return mDictPreferences.getBoolean(dictId, true);
             }
+            // The default is true here for the same reasons as above. We got the dictionary
+            // pack but if we don't have any settings for it it means the user has never been
+            // to the settings yet. So by default, the main dictionaries should be on.
+            return mDictPreferences.getBoolean(dictId, true);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 0542c4b..19f4adc 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -26,7 +26,6 @@
 import android.provider.BaseColumns;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Contacts;
-import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.inputmethod.annotations.UsedForTesting;
@@ -164,7 +163,7 @@
         }
     }
 
-    private boolean useFirstLastBigramsForLocale(final Locale locale) {
+    private static boolean useFirstLastBigramsForLocale(final Locale locale) {
         // TODO: Add firstname/lastname bigram rules for other languages.
         if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
             return true;
@@ -269,7 +268,7 @@
         return end;
     }
 
-    private boolean haveContentsChanged() {
+    boolean haveContentsChanged() {
         final long startTime = SystemClock.uptimeMillis();
         final int contactCount = getContactCount();
         if (contactCount > MAX_CONTACT_COUNT) {
diff --git a/java/src/com/android/inputmethod/latin/DicTraverseSession.java b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
index 2751c12..710fdf4 100644
--- a/java/src/com/android/inputmethod/latin/DicTraverseSession.java
+++ b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
@@ -70,7 +70,7 @@
                 mNativeDicTraverseSession, dictionary, previousWord, previousWordLength);
     }
 
-    private final long createNativeDicTraverseSession(String locale, long dictSize) {
+    private static long createNativeDicTraverseSession(String locale, long dictSize) {
         return setDicTraverseSessionNative(locale, dictSize);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index e66847b..d8f1b2a 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -72,9 +72,13 @@
      * Set out of the dictionary types listed above that are based on data specific to the user,
      * e.g., the user's contacts.
      */
-    private static final HashSet<String> sUserSpecificDictionaryTypes =
-            new HashSet(Arrays.asList(new String[] { TYPE_USER_TYPED, TYPE_USER, TYPE_CONTACTS,
-                    TYPE_USER_HISTORY, TYPE_PERSONALIZATION, TYPE_CONTEXTUAL }));
+    private static final HashSet<String> sUserSpecificDictionaryTypes = new HashSet<>(Arrays.asList(
+            TYPE_USER_TYPED,
+            TYPE_USER,
+            TYPE_CONTACTS,
+            TYPE_USER_HISTORY,
+            TYPE_PERSONALIZATION,
+            TYPE_CONTEXTUAL));
 
     public Dictionary(final String dictType, final Locale locale) {
         mDictType = dictType;
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index 46ddccd..7a17dcc 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -172,9 +172,8 @@
         public Dictionary getDict(final String dictType) {
             if (Dictionary.TYPE_MAIN.equals(dictType)) {
                 return mMainDict;
-            } else {
-                return getSubDict(dictType);
             }
+            return getSubDict(dictType);
         }
 
         public ExpandableBinaryDictionary getSubDict(final String dictType) {
@@ -184,9 +183,8 @@
         public boolean hasDict(final String dictType) {
             if (Dictionary.TYPE_MAIN.equals(dictType)) {
                 return mMainDict != null;
-            } else {
-                return mSubDictMap.containsKey(dictType);
             }
+            return mSubDictMap.containsKey(dictType);
         }
 
         public void closeDict(final String dictType) {
@@ -305,7 +303,7 @@
                 usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */);
     }
 
-    private DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups,
+    static DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups,
             final Locale locale) {
         for (int i = 0; i < dictionaryGroups.length; ++i) {
             if (locale.equals(dictionaryGroups[i].mLocale)) {
@@ -422,34 +420,41 @@
         ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() {
             @Override
             public void run() {
-                for (final Locale locale : locales) {
-                    final DictionaryGroup dictionaryGroup =
-                            findDictionaryGroupWithLocale(mDictionaryGroups, locale);
-                    if (null == dictionaryGroup) {
-                        // This should never happen, but better safe than crashy
-                        Log.w(TAG, "Expected a dictionary group for " + locale + " but none found");
-                        continue;
-                    }
-                    final Dictionary mainDict =
-                            DictionaryFactory.createMainDictionaryFromManager(context, locale);
-                    synchronized (mLock) {
-                        if (locale.equals(dictionaryGroup.mLocale)) {
-                            dictionaryGroup.setMainDict(mainDict);
-                        } else {
-                            // Dictionary facilitator has been reset for another locale.
-                            mainDict.close();
-                        }
-                    }
-                }
-                if (listener != null) {
-                    listener.onUpdateMainDictionaryAvailability(
-                            hasAtLeastOneInitializedMainDictionary());
-                }
-                latchForWaitingLoadingMainDictionary.countDown();
+                doReloadUninitializedMainDictionaries(
+                        context, locales, listener, latchForWaitingLoadingMainDictionary);
             }
         });
     }
 
+    void doReloadUninitializedMainDictionaries(final Context context, final Locale[] locales,
+            final DictionaryInitializationListener listener,
+            final CountDownLatch latchForWaitingLoadingMainDictionary) {
+        for (final Locale locale : locales) {
+            final DictionaryGroup dictionaryGroup =
+                    findDictionaryGroupWithLocale(mDictionaryGroups, locale);
+            if (null == dictionaryGroup) {
+                // This should never happen, but better safe than crashy
+                Log.w(TAG, "Expected a dictionary group for " + locale + " but none found");
+                continue;
+            }
+            final Dictionary mainDict =
+                    DictionaryFactory.createMainDictionaryFromManager(context, locale);
+            synchronized (mLock) {
+                if (locale.equals(dictionaryGroup.mLocale)) {
+                    dictionaryGroup.setMainDict(mainDict);
+                } else {
+                    // Dictionary facilitator has been reset for another locale.
+                    mainDict.close();
+                }
+            }
+        }
+        if (listener != null) {
+            listener.onUpdateMainDictionaryAvailability(
+                    hasAtLeastOneInitializedMainDictionary());
+        }
+        latchForWaitingLoadingMainDictionary.countDown();
+    }
+
     @UsedForTesting
     public void resetDictionariesForTesting(final Context context, final Locale[] locales,
             final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles,
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java
index 1b33d91..b578159 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java
@@ -31,7 +31,7 @@
  * This class automatically creates and releases facilitator instances using LRU policy.
  */
 public class DictionaryFacilitatorLruCache {
-    private static final String TAG = DictionaryFacilitatorLruCache.class.getSimpleName();
+    static final String TAG = DictionaryFacilitatorLruCache.class.getSimpleName();
     private static final int WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS = 1000;
     private static final int MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT = 5;
 
@@ -81,7 +81,8 @@
         mDictionaryNamePrefix = dictionaryNamePrefix;
     }
 
-    private void waitForLoadingMainDictionary(final DictionaryFacilitator dictionaryFacilitator) {
+    private static void waitForLoadingMainDictionary(
+            final DictionaryFacilitator dictionaryFacilitator) {
         for (int i = 0; i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT; i++) {
             try {
                 dictionaryFacilitator.waitForLoadingMainDictionaries(
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 66eeeca..ff05a2f 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -21,11 +21,11 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.makedict.DictionaryHeader;
 import com.android.inputmethod.latin.makedict.FormatSpec;
 import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
 import com.android.inputmethod.latin.makedict.WordProperty;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
 import com.android.inputmethod.latin.utils.AsyncResultHolder;
 import com.android.inputmethod.latin.utils.CombinedFormatUtils;
@@ -47,6 +47,7 @@
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 /**
  * Abstract base class for an expandable dictionary that can be created and updated dynamically
@@ -107,11 +108,11 @@
      */
     protected abstract void loadInitialContentsLocked();
 
-    private boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) {
+    static boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) {
         return formatVersion == FormatSpec.VERSION4;
     }
 
-    private boolean needsToMigrateDictionary(final int formatVersion) {
+    private static boolean needsToMigrateDictionary(final int formatVersion) {
         // When we bump up the dictionary format version, the old version should be added to here
         // for supporting migration. Note that native code has to support reading such formats.
         return formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING;
@@ -159,7 +160,7 @@
         asyncExecuteTaskWithLock(mLock.writeLock(), mDictName /* executorName */, task);
     }
 
-    private void asyncExecuteTaskWithLock(final Lock lock, final String executorName,
+    private static void asyncExecuteTaskWithLock(final Lock lock, final String executorName,
             final Runnable task) {
         asyncPreCheckAndExecuteTaskWithLock(lock, null /* preCheckTask */, executorName, task);
     }
@@ -172,8 +173,9 @@
     }
 
     // Execute task with lock when the result of preCheckTask is true or preCheckTask is null.
-    private void asyncPreCheckAndExecuteTaskWithLock(final Lock lock,
+    private static void asyncPreCheckAndExecuteTaskWithLock(final Lock lock,
             final Callable<Boolean> preCheckTask, final String executorName, final Runnable task) {
+        final String tag = TAG;
         ExecutorUtils.getExecutor(executorName).execute(new Runnable() {
             @Override
             public void run() {
@@ -183,7 +185,7 @@
                             return;
                         }
                     } catch (final Exception e) {
-                        Log.e(TAG, "The pre check task throws an exception.", e);
+                        Log.e(tag, "The pre check task throws an exception.", e);
                         return;
                     }
                 }
@@ -197,6 +199,18 @@
         });
     }
 
+    @Nullable
+    BinaryDictionary getBinaryDictionary() {
+        return mBinaryDictionary;
+    }
+
+    void closeBinaryDictionary() {
+        if (mBinaryDictionary != null) {
+            mBinaryDictionary.close();
+            mBinaryDictionary = null;
+        }
+    }
+
     /**
      * Closes and cleans up the binary dictionary.
      */
@@ -205,10 +219,7 @@
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary != null) {
-                    mBinaryDictionary.close();
-                    mBinaryDictionary = null;
-                }
+                closeBinaryDictionary();
             }
         });
     }
@@ -234,14 +245,11 @@
         });
     }
 
-    private void removeBinaryDictionaryLocked() {
-        if (mBinaryDictionary != null) {
-            mBinaryDictionary.close();
-        }
+    void removeBinaryDictionaryLocked() {
+        closeBinaryDictionary();
         if (mDictFile.exists() && !FileUtils.deleteRecursively(mDictFile)) {
             Log.e(TAG, "Can't remove a file: " + mDictFile.getName());
         }
-        mBinaryDictionary = null;
     }
 
     private void openBinaryDictionaryLocked() {
@@ -250,7 +258,7 @@
                 true /* useFullEditDistance */, mLocale, mDictType, true /* isUpdatable */);
     }
 
-    private void createOnMemoryBinaryDictionaryLocked() {
+    void createOnMemoryBinaryDictionaryLocked() {
         mBinaryDictionary = new BinaryDictionary(
                 mDictFile.getAbsolutePath(), true /* useFullEditDistance */, mLocale, mDictType,
                 DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap());
@@ -273,7 +281,7 @@
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
+                if (getBinaryDictionary() == null) {
                     return;
                 }
                 runGCIfRequiredLocked(mindsBlockByGC);
@@ -291,24 +299,24 @@
             @Nonnull final Runnable updateTask,
             @Nonnull final String word, @Nonnull final DistracterFilter distracterFilter) {
         reloadDictionaryIfRequired();
-        asyncPreCheckAndExecuteTaskWithWriteLock(
-                new Callable<Boolean>() {
-                    @Override
-                    public Boolean call() throws Exception {
-                        return !distracterFilter.isDistracterToWordsInDictionaries(
-                                NgramContext.EMPTY_PREV_WORDS_INFO, word, mLocale);
-                    }
-                },
-                new Runnable() {
-                    @Override
-                    public void run() {
-                        if (mBinaryDictionary == null) {
-                            return;
-                        }
-                        runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                        updateTask.run();
-                    }
-                });
+        final Callable<Boolean> preCheckTask = new Callable<Boolean>() {
+            @Override
+            public Boolean call() throws Exception {
+                return !distracterFilter.isDistracterToWordsInDictionaries(
+                        NgramContext.EMPTY_PREV_WORDS_INFO, word, mLocale);
+            }
+        };
+        final Runnable task = new Runnable() {
+            @Override
+            public void run() {
+                if (getBinaryDictionary() == null) {
+                    return;
+                }
+                runGCIfRequiredLocked(true /* mindsBlockByGC */);
+                updateTask.run();
+            }
+        };
+        asyncPreCheckAndExecuteTaskWithWriteLock(preCheckTask, task);
     }
 
     /**
@@ -344,11 +352,12 @@
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
                     return;
                 }
                 runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                if (!mBinaryDictionary.removeUnigramEntry(word)) {
+                if (!binaryDictionary.removeUnigramEntry(word)) {
                     if (DEBUG) {
                         Log.i(TAG, "Cannot remove unigram entry: " + word);
                     }
@@ -366,7 +375,7 @@
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
+                if (getBinaryDictionary() == null) {
                     return;
                 }
                 runGCIfRequiredLocked(true /* mindsBlockByGC */);
@@ -395,11 +404,12 @@
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
                     return;
                 }
                 runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                if (!mBinaryDictionary.removeNgramEntry(ngramContext, word)) {
+                if (!binaryDictionary.removeNgramEntry(ngramContext, word)) {
                     if (DEBUG) {
                         Log.i(TAG, "Cannot remove n-gram entry.");
                         Log.i(TAG, "  NgramContext: " + ngramContext + ", word: " + word);
@@ -418,7 +428,11 @@
         updateDictionaryWithWriteLockIfWordIsNotADistracter(new Runnable() {
             @Override
             public void run() {
-                if (!mBinaryDictionary.updateEntriesForWordWithNgramContext(ngramContext, word,
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
+                    return;
+                }
+                if (!binaryDictionary.updateEntriesForWordWithNgramContext(ngramContext, word,
                         isValidWord, count, timestamp)) {
                     if (DEBUG) {
                         Log.e(TAG, "Cannot update counter. word: " + word
@@ -444,10 +458,11 @@
             @Override
             public void run() {
                 try {
-                    if (mBinaryDictionary == null) {
+                    final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                    if (binaryDictionary == null) {
                         return;
                     }
-                    mBinaryDictionary.addMultipleDictionaryEntries(
+                    binaryDictionary.addMultipleDictionaryEntries(
                             languageModelParams.toArray(
                                     new LanguageModelParam[languageModelParams.size()]));
                 } finally {
@@ -555,7 +570,7 @@
      * Loads the current binary dictionary from internal storage. Assumes the dictionary file
      * exists.
      */
-    private void loadBinaryDictionaryLocked() {
+    void loadBinaryDictionaryLocked() {
         if (DBG_STRESS_TEST) {
             // Test if this class does not cause problems when it takes long time to load binary
             // dictionary.
@@ -583,7 +598,7 @@
     /**
      * Create a new binary dictionary and load initial contents.
      */
-    private void createNewDictionaryLocked() {
+    void createNewDictionaryLocked() {
         removeBinaryDictionaryLocked();
         createOnMemoryBinaryDictionaryLocked();
         loadInitialContentsLocked();
@@ -599,6 +614,14 @@
         mNeedsToRecreate = true;
     }
 
+    void clearNeedsToRecreate() {
+        mNeedsToRecreate = false;
+    }
+
+    boolean isNeededToRecreate() {
+        return mNeedsToRecreate;
+    }
+
     /**
      * Load the current binary dictionary from internal storage. If the dictionary file doesn't
      * exists or needs to be regenerated, the new dictionary file will be asynchronously generated.
@@ -621,35 +644,39 @@
      * Reloads the dictionary. Access is controlled on a per dictionary file basis.
      */
     private final void asyncReloadDictionary() {
-        if (mIsReloading.compareAndSet(false, true)) {
-            asyncExecuteTaskWithWriteLock(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        if (!mDictFile.exists() || mNeedsToRecreate) {
-                            // If the dictionary file does not exist or contents have been updated,
-                            // generate a new one.
-                            createNewDictionaryLocked();
-                        } else if (mBinaryDictionary == null) {
-                            // Otherwise, load the existing dictionary.
-                            loadBinaryDictionaryLocked();
-                            if (mBinaryDictionary != null && !(isValidDictionaryLocked()
-                                    // TODO: remove the check below
-                                    && matchesExpectedBinaryDictFormatVersionForThisType(
-                                            mBinaryDictionary.getFormatVersion()))) {
-                                // Binary dictionary or its format version is not valid. Regenerate
-                                // the dictionary file. createNewDictionaryLocked will remove the
-                                // existing files if appropriate.
-                                createNewDictionaryLocked();
-                            }
-                        }
-                        mNeedsToRecreate = false;
-                    } finally {
-                        mIsReloading.set(false);
-                    }
-                }
-            });
+        final AtomicBoolean isReloading = mIsReloading;
+        if (!isReloading.compareAndSet(false, true)) {
+            return;
         }
+        final File dictFile = mDictFile;
+        asyncExecuteTaskWithWriteLock(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    if (!dictFile.exists() || isNeededToRecreate()) {
+                        // If the dictionary file does not exist or contents have been updated,
+                        // generate a new one.
+                        createNewDictionaryLocked();
+                    } else if (getBinaryDictionary() == null) {
+                        // Otherwise, load the existing dictionary.
+                        loadBinaryDictionaryLocked();
+                        final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                        if (binaryDictionary != null && !(isValidDictionaryLocked()
+                                // TODO: remove the check below
+                                && matchesExpectedBinaryDictFormatVersionForThisType(
+                                        binaryDictionary.getFormatVersion()))) {
+                            // Binary dictionary or its format version is not valid. Regenerate
+                            // the dictionary file. createNewDictionaryLocked will remove the
+                            // existing files if appropriate.
+                            createNewDictionaryLocked();
+                        }
+                    }
+                    clearNeedsToRecreate();
+                } finally {
+                    isReloading.set(false);
+                }
+            }
+        });
     }
 
     /**
@@ -659,19 +686,20 @@
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
                     return;
                 }
-                if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
-                    mBinaryDictionary.flushWithGC();
+                if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
+                    binaryDictionary.flushWithGC();
                 } else {
-                    mBinaryDictionary.flush();
+                    binaryDictionary.flush();
                 }
             }
         });
     }
 
-    private static int parseEntryCount(final String entryCountStr) {
+    static int parseEntryCount(final String entryCountStr) {
         int entryCount;
         try {
             entryCount = Integer.parseInt(entryCountStr);
@@ -683,23 +711,27 @@
 
     public DictionaryStats getDictionaryStats() {
         reloadDictionaryIfRequired();
+        final String dictName = mDictName;
+        final File dictFile = mDictFile;
         final AsyncResultHolder<DictionaryStats> result = new AsyncResultHolder<>();
-        asyncExecuteTaskWithLock(mLock.readLock(), mDictName /* executorName */, new Runnable() {
+        asyncExecuteTaskWithLock(mLock.readLock(), dictName /* executorName */, new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
-                    result.set(new DictionaryStats(mLocale, mDictName, mDictFile,
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
+                    result.set(new DictionaryStats(mLocale, dictName, dictFile,
                             DictionaryStats.NOT_AN_ENTRY_COUNT,
                             DictionaryStats.NOT_AN_ENTRY_COUNT));
+                    return;
                 }
                 final int unigramCount = parseEntryCount(
-                        mBinaryDictionary.getPropertyForGettingStats(
+                        binaryDictionary.getPropertyForGettingStats(
                                 BinaryDictionary.MAX_UNIGRAM_COUNT_QUERY));
                 // TODO: Get dedicated entry counts for bigram, trigram, and so on.
-                final int ngramCount = parseEntryCount(mBinaryDictionary.getPropertyForGettingStats(
+                final int ngramCount = parseEntryCount(binaryDictionary.getPropertyForGettingStats(
                         BinaryDictionary.MAX_BIGRAM_COUNT_QUERY));
                 // TODO: Get more information from dictionary.
-                result.set(new DictionaryStats(mLocale, mDictName, mDictFile, unigramCount,
+                result.set(new DictionaryStats(mLocale, dictName, dictFile, unigramCount,
                         ngramCount));
             }
         });
@@ -731,28 +763,34 @@
 
     public void dumpAllWordsForDebug() {
         reloadDictionaryIfRequired();
+        final String tag = TAG;
+        final String dictName = mDictName;
         asyncExecuteTaskWithLock(mLock.readLock(), "dumpAllWordsForDebug", new Runnable() {
             @Override
             public void run() {
-                Log.d(TAG, "Dump dictionary: " + mDictName + " for " + mLocale);
+                Log.d(tag, "Dump dictionary: " + dictName + " for " + mLocale);
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
+                    return;
+                }
                 try {
-                    final DictionaryHeader header = mBinaryDictionary.getHeader();
-                    Log.d(TAG, "Format version: " + mBinaryDictionary.getFormatVersion());
-                    Log.d(TAG, CombinedFormatUtils.formatAttributeMap(
+                    final DictionaryHeader header = binaryDictionary.getHeader();
+                    Log.d(tag, "Format version: " + binaryDictionary.getFormatVersion());
+                    Log.d(tag, CombinedFormatUtils.formatAttributeMap(
                             header.mDictionaryOptions.mAttributes));
                 } catch (final UnsupportedFormatException e) {
-                    Log.d(TAG, "Cannot fetch header information.", e);
+                    Log.d(tag, "Cannot fetch header information.", e);
                 }
                 int token = 0;
                 do {
                     final BinaryDictionary.GetNextWordPropertyResult result =
-                            mBinaryDictionary.getNextWordProperty(token);
+                            binaryDictionary.getNextWordProperty(token);
                     final WordProperty wordProperty = result.mWordProperty;
                     if (wordProperty == null) {
-                        Log.d(TAG, " dictionary is empty.");
+                        Log.d(tag, " dictionary is empty.");
                         break;
                     }
-                    Log.d(TAG, wordProperty.toString());
+                    Log.d(tag, wordProperty.toString());
                     token = result.mNextToken;
                 } while (token != 0);
             }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 91a4ec8..e59b839 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -119,15 +119,15 @@
         SuggestionStripView.Listener, SuggestionStripViewAccessor,
         DictionaryFacilitator.DictionaryInitializationListener,
         ImportantNoticeDialog.ImportantNoticeDialogListener {
-    private static final String TAG = LatinIME.class.getSimpleName();
+    static final String TAG = LatinIME.class.getSimpleName();
     private static final boolean TRACE = false;
     private static boolean DEBUG = false;
 
     private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100;
     private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2;
     private static final int PENDING_IMS_CALLBACK_DURATION_MILLIS = 800;
-    private static final long DELAY_WAIT_FOR_DICTIONARY_LOAD_MILLIS = TimeUnit.SECONDS.toMillis(2);
-    private static final long DELAY_DEALLOCATE_MEMORY_MILLIS = TimeUnit.SECONDS.toMillis(10);
+    static final long DELAY_WAIT_FOR_DICTIONARY_LOAD_MILLIS = TimeUnit.SECONDS.toMillis(2);
+    static final long DELAY_DEALLOCATE_MEMORY_MILLIS = TimeUnit.SECONDS.toMillis(10);
 
     /**
      * The name of the scheme used by the Package Manager to warn of a new package installation,
@@ -135,7 +135,7 @@
      */
     private static final String SCHEME_PACKAGE = "package";
 
-    private final Settings mSettings;
+    final Settings mSettings;
     private final DictionaryFacilitator mDictionaryFacilitator =
             new DictionaryFacilitator(this /* context */);
     // TODO: Move from LatinIME.
@@ -149,7 +149,7 @@
                             mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
                         }
                     });
-    private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
+    final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
             this /* SuggestionStripViewAccessor */, mDictionaryFacilitator);
     // We expect to have only one decoder in almost all cases, hence the default capacity of 1.
     // If it turns out we need several, it will get grown seamlessly.
@@ -163,7 +163,7 @@
 
     private RichInputMethodManager mRichImm;
     @UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
-    private final SubtypeSwitcher mSubtypeSwitcher;
+    final SubtypeSwitcher mSubtypeSwitcher;
     private final SubtypeState mSubtypeState = new SubtypeState();
     private final SpecialKeyDetector mSpecialKeyDetector;
     private StatsUtilsManager mStatsUtilsManager;
@@ -204,7 +204,6 @@
         private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
         private static final int ARG1_SHOW_GESTURE_FLOATING_PREVIEW_TEXT = 2;
         private static final int ARG2_UNUSED = 0;
-        private static final int ARG1_FALSE = 0;
         private static final int ARG1_TRUE = 1;
 
         private int mDelayInMillisecondsToUpdateSuggestions;
@@ -654,7 +653,7 @@
         }
     }
 
-    private void resetDictionaryFacilitatorIfNecessary() {
+    void resetDictionaryFacilitatorIfNecessary() {
         final Locale[] subtypeSwitcherLocales = mSubtypeSwitcher.getCurrentSubtypeLocales();
         if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)) {
             return;
@@ -791,17 +790,21 @@
         }
     }
 
+    void updateCursorAnchorInfo() {
+        // CursorAnchorInfo is used on L and later.
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            if (isFullscreenMode() && mExtractEditText != null) {
+                mInputLogic.onUpdateCursorAnchorInfo(
+                        CursorAnchorInfoUtils.extractFromTextView(mExtractEditText));
+            }
+        }
+    }
+
     private final ViewTreeObserver.OnPreDrawListener mExtractTextViewPreDrawListener =
             new ViewTreeObserver.OnPreDrawListener() {
                 @Override
                 public boolean onPreDraw() {
-                    // CursorAnchorInfo is used on L and later.
-                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-                        if (isFullscreenMode() && mExtractEditText != null) {
-                            mInputLogic.onUpdateCursorAnchorInfo(
-                                    CursorAnchorInfoUtils.extractFromTextView(mExtractEditText));
-                        }
-                    }
+                    updateCursorAnchorInfo();
                     return true;
                 }
             };
@@ -846,12 +849,12 @@
         loadKeyboard();
     }
 
-    private void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
+    void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
         super.onStartInput(editorInfo, restarting);
     }
 
     @SuppressWarnings("deprecation")
-    private void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
+    void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
         super.onStartInputView(editorInfo, restarting);
         // Switch to the null consumer to handle cases leading to early exit below, for which we
         // also wouldn't be consuming gesture data.
@@ -1034,7 +1037,7 @@
         }
     }
 
-    private void onFinishInputInternal() {
+    void onFinishInputInternal() {
         super.onFinishInput();
 
         final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
@@ -1043,7 +1046,7 @@
         }
     }
 
-    private void onFinishInputViewInternal(final boolean finishingInput) {
+    void onFinishInputViewInternal(final boolean finishingInput) {
         super.onFinishInputView(finishingInput);
         cleanupInternalStateForFinishInput();
     }
@@ -1295,11 +1298,11 @@
         }
     }
 
-    private int getCurrentAutoCapsState() {
+    int getCurrentAutoCapsState() {
         return mInputLogic.getCurrentAutoCapsState(mSettings.getCurrent());
     }
 
-    private int getCurrentRecapitalizeState() {
+    int getCurrentRecapitalizeState() {
         return mInputLogic.getCurrentRecapitalizeState();
     }
 
@@ -1389,12 +1392,10 @@
             final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard();
             if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
                 return codePoint;
-            } else {
-                return Constants.CODE_SYMBOL_SHIFT;
             }
-        } else {
-            return codePoint;
+            return Constants.CODE_SYMBOL_SHIFT;
         }
+        return codePoint;
     }
 
     // Implementation of {@link KeyboardActionListener}.
@@ -1496,7 +1497,7 @@
     }
 
     // This method must run on the UI Thread.
-    private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
+    void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
             final boolean dismissGestureFloatingPreviewText) {
         showSuggestionStrip(suggestedWords);
         final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
@@ -1812,7 +1813,7 @@
         }
     };
 
-    private void launchSettings() {
+    void launchSettings() {
         mInputLogic.commitTyped(mSettings.getCurrent(), LastComposedWord.NOT_A_SEPARATOR);
         requestHideSelf(0);
         final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
@@ -1836,6 +1837,7 @@
                 languageSelectionTitle,
                 getString(ApplicationUtils.getActivityTitleResId(this, SettingsActivity.class))
         };
+        final String imeId = mRichImm.getInputMethodIdOfThisIme();
         final OnClickListener listener = new OnClickListener() {
             @Override
             public void onClick(DialogInterface di, int position) {
@@ -1843,7 +1845,7 @@
                 switch (position) {
                 case 0:
                     final Intent intent = IntentUtils.getInputLanguageSelectionIntent(
-                            mRichImm.getInputMethodIdOfThisIme(),
+                            imeId,
                             Intent.FLAG_ACTIVITY_NEW_TASK
                                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                                     | Intent.FLAG_ACTIVITY_CLEAR_TOP);
diff --git a/java/src/com/android/inputmethod/latin/NgramContext.java b/java/src/com/android/inputmethod/latin/NgramContext.java
index a02531c..2dc409f 100644
--- a/java/src/com/android/inputmethod/latin/NgramContext.java
+++ b/java/src/com/android/inputmethod/latin/NgramContext.java
@@ -31,14 +31,14 @@
     public static final NgramContext EMPTY_PREV_WORDS_INFO =
             new NgramContext(WordInfo.EMPTY_WORD_INFO);
     public static final NgramContext BEGINNING_OF_SENTENCE =
-            new NgramContext(WordInfo.BEGINNING_OF_SENTENCE);
+            new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
 
     /**
      * Word information used to represent previous words information.
      */
     public static class WordInfo {
         public static final WordInfo EMPTY_WORD_INFO = new WordInfo(null);
-        public static final WordInfo BEGINNING_OF_SENTENCE = new WordInfo();
+        public static final WordInfo BEGINNING_OF_SENTENCE_WORD_INFO = new WordInfo();
 
         // This is an empty char sequence when mIsBeginningOfSentence is true.
         public final CharSequence mWord;
@@ -48,7 +48,7 @@
         public final boolean mIsBeginningOfSentence;
 
         // Beginning of sentence.
-        public WordInfo() {
+        private WordInfo() {
             mWord = "";
             mIsBeginningOfSentence = true;
         }
@@ -96,18 +96,6 @@
         mPrevWordsCount = prevWordsInfo.length;
     }
 
-    // Construct from WordInfo array and size. The caller shouldn't change prevWordsInfo after
-    // calling this method.
-    private NgramContext(final NgramContext ngramContext, final int prevWordsCount) {
-        if (ngramContext.mPrevWordsCount < prevWordsCount) {
-            throw new IndexOutOfBoundsException("ngramContext.mPrevWordsCount ("
-                    + ngramContext.mPrevWordsCount + ") is smaller than prevWordsCount ("
-                    + prevWordsCount + ")");
-        }
-        mPrevWordsInfo = ngramContext.mPrevWordsInfo;
-        mPrevWordsCount = prevWordsCount;
-    }
-
     // Create next prevWordsInfo using current prevWordsInfo.
     public NgramContext getNextNgramContext(final WordInfo wordInfo) {
         final int nextPrevWordCount = Math.min(Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM,
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index a3f7bb4..2c17660 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -44,8 +44,6 @@
 import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.TextRange;
 
-import java.util.Arrays;
-
 /**
  * Enrichment class for InputConnection to simplify interaction and add functionality.
  *
@@ -91,7 +89,7 @@
 
     /**
      * This variable is a temporary object used in
-     * {@link #commitTextWithBackgroundColor(CharSequence, int, int)} to avoid object creation.
+     * {@link #commitTextWithBackgroundColor(CharSequence,int,int,int)} to avoid object creation.
      */
     private SpannableStringBuilder mTempObjectForCommitText = new SpannableStringBuilder();
     /**
@@ -151,9 +149,8 @@
         } else {
             if (DBG) {
                 throw new RuntimeException("Nest level too deep");
-            } else {
-                Log.e(TAG, "Nest level too deep : " + mNestLevel);
             }
+            Log.e(TAG, "Nest level too deep : " + mNestLevel);
         }
         if (DEBUG_BATCH_NESTING) checkBatchEdit();
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@@ -351,10 +348,9 @@
                 // If we have some composing text and a space before, then we should have
                 // MODE_CHARACTERS and MODE_WORDS on.
                 return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & inputType;
-            } else {
-                // We have some composing text - we should be in MODE_CHARACTERS only.
-                return TextUtils.CAP_MODE_CHARACTERS & inputType;
             }
+            // We have some composing text - we should be in MODE_CHARACTERS only.
+            return TextUtils.CAP_MODE_CHARACTERS & inputType;
         }
         // TODO: this will generally work, but there may be cases where the buffer contains SOME
         // information but not enough to determine the caps mode accurately. This may happen after
@@ -624,10 +620,6 @@
                 prev, spacingAndPunctuations, n);
     }
 
-    private static boolean isSeparator(final int code, final int[] sortedSeparators) {
-        return Arrays.binarySearch(sortedSeparators, code) >= 0;
-    }
-
     private static boolean isPartOfCompositionForScript(final int codePoint,
             final SpacingAndPunctuations spacingAndPunctuations, final int scriptId) {
         // We always consider word connectors part of compositions.
@@ -977,7 +969,8 @@
 
     /**
      * @return {@code true} if the application reported that the monitor mode of
-     * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} is currently enabled.
+     * {@link InputMethodService#onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo)}
+     * is currently enabled.
      */
     public boolean isCursorAnchorInfoMonitorEnabled() {
         return mCursorAnchorInfoMonitorEnabled;
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index e6df35b..113a204 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -20,7 +20,6 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.content.res.Resources;
 import android.os.Build;
 import android.os.IBinder;
 import android.preference.PreferenceManager;
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 6fc5495..7944750 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -291,8 +291,9 @@
     }
 
     private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
+
     @UsedForTesting
-    void forceSubtype(final InputMethodSubtype subtype) {
+    static void forceSubtype(final InputMethodSubtype subtype) {
         sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index e6c1384..6042e7e 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -328,7 +328,7 @@
      * @param info the suggestion info
      * @return whether it's fine to auto-correct to this.
      */
-    private boolean isAllowedByAutoCorrectionWithSpaceFilter(final SuggestedWordInfo info) {
+    private static boolean isAllowedByAutoCorrectionWithSpaceFilter(final SuggestedWordInfo info) {
         final Locale locale = info.mSourceDict.mLocale;
         if (null == locale) {
             return true;
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index e5bf25d..dffe97b 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -365,9 +365,8 @@
         public String toString() {
             if (TextUtils.isEmpty(mDebugString)) {
                 return mWord;
-            } else {
-                return mWord + " (" + mDebugString + ")";
             }
+            return mWord + " (" + mDebugString + ")";
         }
 
         // This will always remove the higher index if a duplicate is found.
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 9332e4a..37dd384 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -64,7 +64,7 @@
     private static final String NAME = "userunigram";
 
     private ContentObserver mObserver;
-    final private String mLocale;
+    final private String mLocaleString;
     final private boolean mAlsoUseMoreRestrictiveLocales;
 
     protected UserBinaryDictionary(final Context context, final Locale locale,
@@ -74,9 +74,9 @@
         final String localeStr = locale.toString();
         if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) {
             // If we don't have a locale, insert into the "all locales" user dictionary.
-            mLocale = USER_DICTIONARY_ALL_LANGUAGES;
+            mLocaleString = USER_DICTIONARY_ALL_LANGUAGES;
         } else {
-            mLocale = localeStr;
+            mLocaleString = localeStr;
         }
         mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
         ContentResolver cres = context.getContentResolver();
@@ -124,7 +124,7 @@
         // This is correct for locale processing.
         // For this example, we'll look at the "en_US_POSIX" case.
         final String[] localeElements =
-                TextUtils.isEmpty(mLocale) ? new String[] {} : mLocale.split("_", 3);
+                TextUtils.isEmpty(mLocaleString) ? new String[] {} : mLocaleString.split("_", 3);
         final int length = localeElements.length;
 
         final StringBuilder request = new StringBuilder("(locale is NULL)");
@@ -207,9 +207,8 @@
         if (client != null) {
             client.release();
             return true;
-        } else {
-            return false;
         }
+        return false;
     }
 
     /**
@@ -227,17 +226,16 @@
                 HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY, null, locale);
     }
 
-    private int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
+    private static int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
         // The default frequency for the user dictionary is 250 for historical reasons.
         // Latin IME considers a good value for the default user dictionary frequency
         // is about 160 considering the scale we use. So we are scaling down the values.
         if (defaultFrequency > Integer.MAX_VALUE / LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) {
             return (defaultFrequency / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY)
                     * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY;
-        } else {
-            return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY)
-                    / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY;
         }
+        return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY)
+                / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY;
     }
 
     private void addWordsLocked(final Cursor cursor) {
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 5eb338e..6530e6b 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -353,9 +353,8 @@
         if (size() <= 1) {
             return mCapitalizedMode == CAPS_MODE_AUTO_SHIFT_LOCKED
                     || mCapitalizedMode == CAPS_MODE_MANUAL_SHIFT_LOCKED;
-        } else {
-            return mCapsCount == size();
         }
+        return mCapsCount == size();
     }
 
     public boolean wasShiftedNoLock() {
diff --git a/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java b/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java
index a87785b..d4be0e3 100644
--- a/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java
+++ b/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java
@@ -44,7 +44,7 @@
  * A class to read a local file as a dictionary for debugging purposes.
  */
 public class ExternalDictionaryGetterForDebug {
-    private static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath()
+    static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath()
             + "/Download";
 
     private static String[] findDictionariesInTheDownloadedFolder() {
@@ -142,8 +142,7 @@
                 }).create().show();
     }
 
-    private static void installFile(final Context context, final File file,
-            final DictionaryHeader header) {
+    static void installFile(final Context context, final File file, final DictionaryHeader header) {
         BufferedOutputStream outputStream = null;
         File tempFile = null;
         try {
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 5cc61db..359ea12 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -75,7 +75,7 @@
     private static final String TAG = InputLogic.class.getSimpleName();
 
     // TODO : Remove this member when we can.
-    private final LatinIME mLatinIME;
+    final LatinIME mLatinIME;
     private final SuggestionStripViewAccessor mSuggestionStripViewAccessor;
 
     // Never null.
@@ -1512,12 +1512,6 @@
             }
         }
         final int[] codePoints = StringUtils.toCodePointArray(typedWord);
-        // We want the context of preceding words for suggestion. If we have chars in the word
-        // before the cursor, then we want the word before that, hence 2; otherwise,
-        // we want the word immediately before the cursor, hence 1.
-        final NgramContext ngramContext = getNgramContextFromNthPreviousWordForSuggestion(
-                settingsValues.mSpacingAndPunctuations,
-                0 == numberOfCharsInWordBeforeCursor ? 1 : 2);
         mWordComposer.setComposingWord(codePoints,
                 mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
         mWordComposer.setCursorPositionWithinWord(
@@ -1533,8 +1527,7 @@
                     SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
                         @Override
                         public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
-                            mIsAutoCorrectionIndicatorOn = false;
-                            mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
+                            doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords);
                         }});
         } else {
             // We found suggestion spans in the word. We'll create the SuggestedWords out of
@@ -1545,11 +1538,15 @@
                     null /* rawSuggestions */, typedWord, false /* typedWordValid */,
                     false /* willAutoCorrect */, false /* isObsoleteSuggestions */,
                     SuggestedWords.INPUT_STYLE_RECORRECTION, SuggestedWords.NOT_A_SEQUENCE_NUMBER);
-            mIsAutoCorrectionIndicatorOn = false;
-            mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
+            doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords);
         }
     }
 
+    void doShowSuggestionsAndClearAutoCorrectionIndicator(final SuggestedWords suggestedWords) {
+        mIsAutoCorrectionIndicatorOn = false;
+        mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
+    }
+
     /**
      * Reverts a previous commit with auto-correction.
      *
@@ -1761,12 +1758,12 @@
             // word information from textview.
             return mConnection.getNgramContextFromNthPreviousWord(
                     spacingAndPunctuations, nthPreviousWord);
-        } else {
-            return LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord ?
-                    NgramContext.BEGINNING_OF_SENTENCE :
-                            new NgramContext(new NgramContext.WordInfo(
-                                    mLastComposedWord.mCommittedWord.toString()));
         }
+        if (LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord) {
+            return NgramContext.BEGINNING_OF_SENTENCE;
+        }
+        return new NgramContext(new NgramContext.WordInfo(
+                mLastComposedWord.mCommittedWord.toString()));
     }
 
     /**
@@ -1819,9 +1816,8 @@
         // If no code point, #getCodePointBeforeCursor returns NOT_A_CODE_POINT.
         if (Constants.CODE_PERIOD == codePointBeforeCursor) {
             return text.substring(1);
-        } else {
-            return text;
         }
+        return text;
     }
 
     /**
@@ -1877,7 +1873,7 @@
      * @param previousSuggestedWords The previously suggested words.
      * @return Obsolete suggestions with the newly typed word.
      */
-    private SuggestedWords retrieveOlderSuggestions(final String typedWord,
+    static SuggestedWords retrieveOlderSuggestions(final String typedWord,
             final SuggestedWords previousSuggestedWords) {
         final SuggestedWords oldSuggestedWords = previousSuggestedWords.isPunctuationSuggestions()
                 ? SuggestedWords.getEmptyInstance() : previousSuggestedWords;
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
index c6f83d0..5f391dd 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
@@ -23,7 +23,6 @@
 import com.android.inputmethod.compat.LooperCompatUtils;
 import com.android.inputmethod.latin.InputPointers;
 import com.android.inputmethod.latin.LatinIME;
-import com.android.inputmethod.latin.Suggest;
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
 
@@ -62,7 +61,7 @@
                 final OnGetSuggestedWordsCallback callback) {}
     };
 
-    private InputLogicHandler() {
+    InputLogicHandler() {
         mNonUIThreadHandler = null;
         mLatinIME = null;
         mInputLogic = null;
@@ -134,30 +133,38 @@
                 return;
             }
             mInputLogic.mWordComposer.setBatchInputPointers(batchPointers);
+            final OnGetSuggestedWordsCallback callback = new OnGetSuggestedWordsCallback() {
+                @Override
+                public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
+                    showGestureSuggestionsWithPreviewVisuals(suggestedWords, isTailBatchInput);
+                }
+            };
             getSuggestedWords(isTailBatchInput ? SuggestedWords.INPUT_STYLE_TAIL_BATCH
-                    : SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber,
-                    new OnGetSuggestedWordsCallback() {
-                        @Override
-                        public void onGetSuggestedWords(SuggestedWords suggestedWords) {
-                            // We're now inside the callback. This always runs on the Non-UI thread,
-                            // no matter what thread updateBatchInput was originally called on.
-                            if (suggestedWords.isEmpty()) {
-                                // Use old suggestions if we don't have any new ones.
-                                // Previous suggestions are found in InputLogic#mSuggestedWords.
-                                // Since these are the most recent ones and we just recomputed
-                                // new ones to update them, then the previous ones are there.
-                                suggestedWords = mInputLogic.mSuggestedWords;
-                            }
-                            mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWords,
-                                    isTailBatchInput /* dismissGestureFloatingPreviewText */);
-                            if (isTailBatchInput) {
-                                mInBatchInput = false;
-                                // The following call schedules onEndBatchInputInternal
-                                // to be called on the UI thread.
-                                mLatinIME.mHandler.showTailBatchInputResult(suggestedWords);
-                            }
-                        }
-                    });
+                    : SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber, callback);
+        }
+    }
+
+    void showGestureSuggestionsWithPreviewVisuals(final SuggestedWords suggestedWordsForBatchInput,
+            final boolean isTailBatchInput) {
+        final SuggestedWords suggestedWordsToShowSuggestions;
+        // We're now inside the callback. This always runs on the Non-UI thread,
+        // no matter what thread updateBatchInput was originally called on.
+        if (suggestedWordsForBatchInput.isEmpty()) {
+            // Use old suggestions if we don't have any new ones.
+            // Previous suggestions are found in InputLogic#mSuggestedWords.
+            // Since these are the most recent ones and we just recomputed
+            // new ones to update them, then the previous ones are there.
+            suggestedWordsToShowSuggestions = mInputLogic.mSuggestedWords;
+        } else {
+            suggestedWordsToShowSuggestions = suggestedWordsForBatchInput;
+        }
+        mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWordsToShowSuggestions,
+                isTailBatchInput /* dismissGestureFloatingPreviewText */);
+        if (isTailBatchInput) {
+            mInBatchInput = false;
+            // The following call schedules onEndBatchInputInternal
+            // to be called on the UI thread.
+            mLatinIME.mHandler.showTailBatchInputResult(suggestedWordsToShowSuggestions);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java b/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java
index 5fcbb63..03c2ece 100644
--- a/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java
+++ b/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java
@@ -40,11 +40,8 @@
         if (probabilityInfo2 == null) {
             return probabilityInfo1;
         }
-        if (probabilityInfo1.mProbability > probabilityInfo2.mProbability) {
-            return probabilityInfo1;
-        } else {
-            return probabilityInfo2;
-        }
+        return (probabilityInfo1.mProbability > probabilityInfo2.mProbability) ? probabilityInfo1
+                : probabilityInfo2;
     }
 
     public ProbabilityInfo(final int probability) {
@@ -67,9 +64,8 @@
     public int hashCode() {
         if (hasHistoricalInfo()) {
             return Arrays.hashCode(new Object[] { mProbability, mTimestamp, mLevel, mCount });
-        } else {
-            return Arrays.hashCode(new Object[] { mProbability });
         }
+        return Arrays.hashCode(new Object[] { mProbability });
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
index 5c6d8f5..b129c3e 100644
--- a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
+++ b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
@@ -18,6 +18,7 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.BinaryDictionary;
+import com.android.inputmethod.latin.Dictionary;
 import com.android.inputmethod.latin.NgramContext;
 import com.android.inputmethod.latin.NgramContext.WordInfo;
 import com.android.inputmethod.latin.utils.CombinedFormatUtils;
@@ -61,10 +62,8 @@
         } else {
             mNgrams = new ArrayList<>();
             final NgramContext ngramContext = new NgramContext(new WordInfo(mWord));
-            if (bigrams != null) {
-                for (final WeightedString bigramTarget : bigrams) {
-                    mNgrams.add(new NgramProperty(bigramTarget, ngramContext));
-                }
+            for (final WeightedString bigramTarget : bigrams) {
+                mNgrams.add(new NgramProperty(bigramTarget, ngramContext));
             }
         }
         mIsBeginningOfSentence = false;
@@ -104,7 +103,8 @@
 
         final int relatedNgramCount = ngramTargets.size();
         final WordInfo currentWordInfo =
-                mIsBeginningOfSentence ? WordInfo.BEGINNING_OF_SENTENCE : new WordInfo(mWord);
+                mIsBeginningOfSentence ? WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO
+                        : new WordInfo(mWord);
         final NgramContext ngramContext = new NgramContext(currentWordInfo);
         for (int i = 0; i < relatedNgramCount; i++) {
             final String ngramTargetString =
@@ -202,7 +202,7 @@
 
     @UsedForTesting
     public boolean isValid() {
-        return getProbability() != BinaryDictionary.NOT_A_PROBABILITY;
+        return getProbability() != Dictionary.NOT_A_PROBABILITY;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java b/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java
index e2d24fd..079d07e 100644
--- a/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java
+++ b/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java
@@ -85,12 +85,11 @@
                     throw new AuthException(mConnection.getResponseMessage());
                 }
                 throw new HttpException(responseCode);
-            } else {
-                if (DEBUG) {
-                    Log.d(TAG, "request executed successfully");
-                }
-                return responseProcessor.onSuccess(mConnection.getInputStream());
             }
+            if (DEBUG) {
+                Log.d(TAG, "request executed successfully");
+            }
+            return responseProcessor.onSuccess(mConnection.getInputStream());
         } finally {
             mConnection.disconnect();
         }
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 1ba7b36..78b51d9 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -39,14 +39,10 @@
     public static final int FREQUENCY_FOR_WORDS_IN_DICTS = FREQUENCY_FOR_TYPED;
     public static final int FREQUENCY_FOR_WORDS_NOT_IN_DICTS = Dictionary.NOT_A_PROBABILITY;
 
-    /** The locale for this dictionary. */
-    public final Locale mLocale;
-
     protected DecayingExpandableBinaryDictionaryBase(final Context context,
             final String dictName, final Locale locale, final String dictionaryType,
             final File dictFile) {
         super(context, dictName, locale, dictionaryType, dictFile);
-        mLocale = locale;
         if (mLocale != null && mLocale.toString().length() > 1) {
             reloadDictionaryIfRequired();
         }
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index 5976154..e777c0b 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -17,7 +17,6 @@
 package com.android.inputmethod.latin.personalization;
 
 import android.content.Context;
-import android.text.TextUtils;
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.Constants;
@@ -35,7 +34,6 @@
  */
 public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase {
     /* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName();
-    private final static int SUPPORTED_NGRAM = 2; // TODO: 3
 
     // TODO: Make this constructor private
     /* package */ UserHistoryDictionary(final Context context, final Locale locale) {
diff --git a/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java
index c07b60a..01398f4 100644
--- a/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java
+++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java
@@ -259,6 +259,7 @@
             mSubtype = (InputMethodSubtype)source.readParcelable(null);
         }
 
+        @SuppressWarnings("hiding")
         public static final Parcelable.Creator<SavedState> CREATOR =
                 new Parcelable.Creator<SavedState>() {
                     @Override
diff --git a/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java
index 832fbf6..22b0655 100644
--- a/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java
@@ -16,7 +16,6 @@
 
 package com.android.inputmethod.latin.settings;
 
-import android.content.SharedPreferences;
 import android.os.Bundle;
 
 import com.android.inputmethod.latin.R;
diff --git a/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java
index b71f882..c5930db 100644
--- a/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java
@@ -20,8 +20,6 @@
 
 import com.android.inputmethod.latin.R;
 
-import java.util.ArrayList;
-
 /**
  * "Multilingual options" settings sub screen.
  *
diff --git a/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java b/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java
index c173d47..9144460 100644
--- a/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java
+++ b/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java
@@ -43,9 +43,7 @@
     private final View.OnClickListener mClickListener = new View.OnClickListener() {
         @Override
         public void onClick(final View v) {
-            if (mListener != null) {
-                mListener.onRadioButtonClicked(RadioButtonPreference.this);
-            }
+            callListenerOnRadioButtonClicked();
         }
     };
 
@@ -67,6 +65,12 @@
         mListener = listener;
     }
 
+    void callListenerOnRadioButtonClicked() {
+        if (mListener != null) {
+            mListener.onRadioButtonClicked(this);
+        }
+    }
+
     @Override
     protected void onBindView(final View view) {
         super.onBindView(view);
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 660b4e0..5b99652 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -273,9 +273,8 @@
         final RichInputMethodManager imm = RichInputMethodManager.getInstance();
         if (mIncludesOtherImesInLanguageSwitchList) {
             return imm.hasMultipleEnabledIMEsOrSubtypes(false /* include aux subtypes */);
-        } else {
-            return imm.hasMultipleEnabledSubtypesInThisIme(false /* include aux subtypes */);
         }
+        return imm.hasMultipleEnabledSubtypesInThisIme(false /* include aux subtypes */);
     }
 
     public boolean isSameInputType(final EditorInfo editorInfo) {
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 2a4e14c..f5c7131 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -50,9 +50,6 @@
  */
 public final class AndroidSpellCheckerService extends SpellCheckerService
         implements SharedPreferences.OnSharedPreferenceChangeListener {
-    private static final String TAG = AndroidSpellCheckerService.class.getSimpleName();
-    private static final boolean DBG = false;
-
     public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts";
 
     private static final int SPELLCHECKER_DUMMY_KEYBOARD_WIDTH = 480;
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index 7b6aacd..06adf4b 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -312,11 +312,10 @@
             // Don't kill the keyboard if there is a bug in the spell checker
             if (DBG) {
                 throw e;
-            } else {
-                Log.e(TAG, "Exception while spellcheking", e);
-                return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
-                        false /* reportAsTypo */);
             }
+            Log.e(TAG, "Exception while spellcheking", e);
+            return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
+                    false /* reportAsTypo */);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java b/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java
index 9ddee86..3c9f261 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java
@@ -16,7 +16,9 @@
 
 package com.android.inputmethod.latin.spellcheck;
 
+import android.annotation.TargetApi;
 import android.content.res.Resources;
+import android.os.Build;
 import android.view.textservice.SentenceSuggestionsInfo;
 import android.view.textservice.SuggestionsInfo;
 import android.view.textservice.TextInfo;
@@ -76,19 +78,19 @@
     private static class WordIterator {
         private final SpacingAndPunctuations mSpacingAndPunctuations;
         public WordIterator(final Resources res, final Locale locale) {
-            final RunInLocale<SpacingAndPunctuations> job
-                    = new RunInLocale<SpacingAndPunctuations>() {
+            final RunInLocale<SpacingAndPunctuations> job =
+                    new RunInLocale<SpacingAndPunctuations>() {
                 @Override
-                protected SpacingAndPunctuations job(final Resources res) {
-                    return new SpacingAndPunctuations(res);
+                protected SpacingAndPunctuations job(final Resources r) {
+                    return new SpacingAndPunctuations(r);
                 }
             };
             mSpacingAndPunctuations = job.runInLocale(res, locale);
         }
 
-        public int getEndOfWord(final CharSequence sequence, int index) {
+        public int getEndOfWord(final CharSequence sequence, final int fromIndex) {
             final int length = sequence.length();
-            index = index < 0 ? 0 : Character.offsetByCodePoints(sequence, index, 1);
+            int index = fromIndex < 0 ? 0 : Character.offsetByCodePoints(sequence, fromIndex, 1);
             while (index < length) {
                 final int codePoint = Character.codePointAt(sequence, index);
                 if (mSpacingAndPunctuations.isWordSeparator(codePoint)) {
@@ -111,12 +113,12 @@
             return index;
         }
 
-        public int getBeginningOfNextWord(final CharSequence sequence, int index) {
+        public int getBeginningOfNextWord(final CharSequence sequence, final int fromIndex) {
             final int length = sequence.length();
-            if (index >= length) {
+            if (fromIndex >= length) {
                 return -1;
             }
-            index = index < 0 ? 0 : Character.offsetByCodePoints(sequence, index, 1);
+            int index = fromIndex < 0 ? 0 : Character.offsetByCodePoints(sequence, fromIndex, 1);
             while (index < length) {
                 final int codePoint = Character.codePointAt(sequence, index);
                 if (!mSpacingAndPunctuations.isWordSeparator(codePoint)) {
@@ -140,7 +142,7 @@
         final int cookie = originalTextInfo.getCookie();
         final int start = -1;
         final int end = originalText.length();
-        final ArrayList<SentenceWordItem> wordItems = new ArrayList<SentenceWordItem>();
+        final ArrayList<SentenceWordItem> wordItems = new ArrayList<>();
         int wordStart = wordIterator.getBeginningOfNextWord(originalText, start);
         int wordEnd = wordIterator.getEndOfWord(originalText, wordStart);
         while (wordStart <= end && wordEnd != -1 && wordStart != -1) {
@@ -158,6 +160,7 @@
         return new SentenceTextInfoParams(originalTextInfo, wordItems);
     }
 
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     public static SentenceSuggestionsInfo reconstructSuggestions(
             SentenceTextInfoParams originalTextInfoParams, SuggestionsInfo[] results) {
         if (results == null || results.length == 0) {
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index 7b66bbb..27a0f62 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -50,10 +50,8 @@
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import com.android.inputmethod.latin.define.DebugFlags;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.settings.SettingsValues;
-import com.android.inputmethod.latin.utils.AutoCorrectionUtils;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 import com.android.inputmethod.latin.utils.ViewLayoutUtils;
@@ -380,6 +378,7 @@
 
         final int countInStrip = mSuggestionsCountInStrip;
         mMoreSuggestionsAvailable = (wordCountToShow > countInStrip);
+        @SuppressWarnings("unused")
         int x = 0;
         for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) {
             if (positionInStrip != 0) {
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
index cf2014a..9d89d57 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
@@ -177,12 +177,11 @@
             return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
                     QUERY_SELECTION_ALL_LOCALES, null,
                     "UPPER(" + UserDictionary.Words.WORD + ")");
-        } else {
-            final String queryLocale = null != locale ? locale : Locale.getDefault().toString();
-            return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
-                    QUERY_SELECTION, new String[] { queryLocale },
-                    "UPPER(" + UserDictionary.Words.WORD + ")");
         }
+        final String queryLocale = null != locale ? locale : Locale.getDefault().toString();
+        return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
+                QUERY_SELECTION, new String[] { queryLocale },
+                "UPPER(" + UserDictionary.Words.WORD + ")");
     }
 
     private ListAdapter createAdapter() {
diff --git a/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java b/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java
index d12aad6..952ac2a 100644
--- a/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java
+++ b/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java
@@ -59,11 +59,7 @@
      */
     public E get(final E defaultValue, final long timeOut) {
         try {
-            if (mLatch.await(timeOut, TimeUnit.MILLISECONDS)) {
-                return mResult;
-            } else {
-                return defaultValue;
-            }
+            return mLatch.await(timeOut, TimeUnit.MILLISECONDS) ? mResult : defaultValue;
         } catch (InterruptedException e) {
             return defaultValue;
         }
diff --git a/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java b/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java
index cba7695..120cffb 100644
--- a/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java
@@ -24,7 +24,6 @@
 public final class AutoCorrectionUtils {
     private static final boolean DBG = DebugFlags.DEBUG_ENABLED;
     private static final String TAG = AutoCorrectionUtils.class.getSimpleName();
-    private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
 
     private AutoCorrectionUtils() {
         // Purely static class: can't instantiate.
diff --git a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
index fb36b7c..d0df724 100644
--- a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
@@ -18,9 +18,6 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.TreeMap;
 
 public final class CollectionUtils {
     private CollectionUtils() {
@@ -47,7 +44,7 @@
      * @param c Collection to test.
      * @return Whether c contains no elements.
      */
-    public static boolean isNullOrEmpty(final Collection c) {
+    public static boolean isNullOrEmpty(final Collection<?> c) {
         return c == null || c.isEmpty();
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java
index e056189..6c1449c 100644
--- a/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java
@@ -24,6 +24,7 @@
 import android.os.Build;
 import android.text.Layout;
 import android.text.Spannable;
+import android.text.Spanned;
 import android.view.View;
 import android.view.ViewParent;
 import android.view.inputmethod.CursorAnchorInfo;
@@ -149,7 +150,7 @@
             final Object[] spans = spannable.getSpans(0, text.length(), Object.class);
             for (Object span : spans) {
                 final int spanFlag = spannable.getSpanFlags(span);
-                if ((spanFlag & Spannable.SPAN_COMPOSING) != 0) {
+                if ((spanFlag & Spanned.SPAN_COMPOSING) != 0) {
                     composingTextStart = Math.min(composingTextStart,
                             spannable.getSpanStart(span));
                     composingTextEnd = Math.max(composingTextEnd, spannable.getSpanEnd(span));
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java
index df6e970..4c99fed 100644
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java
+++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java
@@ -41,10 +41,9 @@
             // This filter treats entries that are already in the dictionary as non-distracters
             // because they have passed the filtering in the past.
             return false;
-        } else {
-            return mDistracterFilter.isDistracterToWordsInDictionaries(
-                    ngramContext, testedWord, locale);
         }
+        return mDistracterFilter.isDistracterToWordsInDictionaries(
+                ngramContext, testedWord, locale);
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java
index 61da1b7..e77f6fd 100644
--- a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java
@@ -27,7 +27,7 @@
  * Utilities to manage executors.
  */
 public class ExecutorUtils {
-    private static final ConcurrentHashMap<String, ExecutorService> sExecutorMap =
+    static final ConcurrentHashMap<String, ExecutorService> sExecutorMap =
             new ConcurrentHashMap<>();
 
     private static class ThreadFactoryWithId implements ThreadFactory {
@@ -49,7 +49,7 @@
     public static ExecutorService getExecutor(final String id) {
         ExecutorService executor = sExecutorMap.get(id);
         if (executor == null) {
-            synchronized(sExecutorMap) {
+            synchronized (sExecutorMap) {
                 executor = sExecutorMap.get(id);
                 if (executor == null) {
                     executor = Executors.newSingleThreadExecutor(new ThreadFactoryWithId(id));
@@ -65,7 +65,7 @@
      */
     @UsedForTesting
     public static void shutdownAllExecutors() {
-        synchronized(sExecutorMap) {
+        synchronized (sExecutorMap) {
             for (final ExecutorService executor : sExecutorMap.values()) {
                 executor.execute(new Runnable() {
                     @Override
diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
index 5560d2f..3e5cb33 100644
--- a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
+++ b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
@@ -20,7 +20,6 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.DictionaryFacilitator;
 import com.android.inputmethod.latin.NgramContext;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 import com.android.inputmethod.latin.utils.DistracterFilter.HandlingType;
diff --git a/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java b/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java
index 34eeac2..95a1f0f 100644
--- a/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java
@@ -74,20 +74,20 @@
             }
             // If we can't find (n + i) words, the context is beginning-of-sentence.
             if (focusedWordIndex < 0) {
-                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
+                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
                 break;
             }
             final String focusedWord = w[focusedWordIndex];
             // If the word is, the context is beginning-of-sentence.
             final int length = focusedWord.length();
             if (length <= 0) {
-                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
+                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
                 break;
             }
             // If ends in a sentence separator, the context is beginning-of-sentence.
             final char lastChar = focusedWord.charAt(length - 1);
             if (spacingAndPunctuations.isSentenceSeparator(lastChar)) {
-                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
+                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
                 break;
             }
             // If ends in a word separator or connector, the context is unclear.
diff --git a/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java b/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java
index 38164cb..cea1d1d 100644
--- a/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java
@@ -51,7 +51,7 @@
             // of a word. But the spans have been split into two by the getText{Before,After}Cursor
             // methods, so after concatenation they may end in the middle of a word.
             // Since we don't use them, we can just remove them and avoid crashing.
-            fl &= ~Spannable.SPAN_PARAGRAPH;
+            fl &= ~Spanned.SPAN_PARAGRAPH;
 
             int st = source.getSpanStart(spans[i]);
             int en = source.getSpanEnd(spans[i]);
diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
index 61661cd..352d6cd 100644
--- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
@@ -39,7 +39,7 @@
   */
 // TODO: consolidate this into RichInputMethodSubtype
 public final class SubtypeLocaleUtils {
-    private static final String TAG = SubtypeLocaleUtils.class.getSimpleName();
+    static final String TAG = SubtypeLocaleUtils.class.getSimpleName();
 
     // This reference class {@link Constants} must be located in the same package as LatinIME.java.
     private static final String RESOURCE_PACKAGE_NAME = Constants.class.getPackage().getName();
@@ -245,9 +245,8 @@
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
                 && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
             return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
-        } else {
-            return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
         }
+        return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
     }
 
     public static String getSubtypeDisplayNameInSystemLocale(final InputMethodSubtype subtype) {
diff --git a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
index 4e2e396..b319aeb 100644
--- a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
+++ b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
@@ -66,8 +66,7 @@
         return super.addAll(e);
     }
 
-    private static final class SuggestedWordInfoComparator
-            implements Comparator<SuggestedWordInfo> {
+    static final class SuggestedWordInfoComparator implements Comparator<SuggestedWordInfo> {
         // This comparator ranks the word info with the higher frequency first. That's because
         // that's the order we want our elements in.
         @Override
diff --git a/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java b/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java
index 319302c..67e7646 100644
--- a/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java
+++ b/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java
@@ -20,7 +20,6 @@
 import android.os.Build;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.style.StyleSpan;
@@ -72,141 +71,141 @@
             final SpannableString text = new SpannableString("0123456789");
             LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
             assertSpanCount(1, text);
-            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if only LocaleSpans are updated.
         {
             final SpannableString text = new SpannableString("0123456789");
             final StyleSpan styleSpan = new StyleSpan(Typeface.BOLD);
-            text.setSpan(styleSpan, 0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            text.setSpan(styleSpan, 0, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
             assertSpanCount(2, text);
             assertSpanEquals(styleSpan, text, 0);
-            assertLocaleSpan(text, 1, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 1, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if two jointed spans are merged into one span.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE);
             assertSpanCount(1, text);
-            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if two overlapped spans are merged into one span.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE);
             assertSpanCount(1, text);
-            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if three overlapped spans are merged into one span.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 8, Locale.JAPANESE);
             assertSpanCount(1, text);
-            assertLocaleSpan(text, 0, 1, 8, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 8, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if disjoint spans remain disjoint.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 8, 9, Locale.JAPANESE);
             assertSpanCount(3, text);
-            assertLocaleSpan(text, 0, 1, 3, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 1, 5, 6, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 2, 8, 9, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 3, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 1, 5, 6, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 2, 8, 9, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if existing span flags are preserved during merge.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 5,
-                    Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 4, Locale.JAPANESE);
             assertSpanCount(1, text);
             assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE,
-                    Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
         }
 
         // Test if existing span flags are preserved even when partially overlapped (leading edge).
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 5,
-                    Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 7, Locale.JAPANESE);
             assertSpanCount(1, text);
             assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE,
-                    Spannable.SPAN_INCLUSIVE_EXCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_INCLUSIVE_EXCLUSIVE | Spanned.SPAN_INTERMEDIATE);
         }
 
         // Test if existing span flags are preserved even when partially overlapped (trailing edge).
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 3, 7,
-                    Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
             assertSpanCount(1, text);
             assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE,
-                    Spannable.SPAN_EXCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_EXCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
         }
 
         // Test if existing locale span will be removed when the locale doesn't match.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 5,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 7, Locale.JAPANESE);
             assertSpanCount(1, text);
-            assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if existing locale span will be removed when the locale doesn't match. (case 2)
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 6, Locale.JAPANESE);
             assertSpanCount(3, text);
-            assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 1, 6, 7, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 2, 5, 6, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 1, 6, 7, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 2, 5, 6, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if existing locale span will be removed when the locale doesn't match. (case 3)
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 5, Locale.JAPANESE);
             assertSpanCount(2, text);
-            assertLocaleSpan(text, 0, 5, 7, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 1, 2, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 5, 7, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 1, 2, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if existing locale span will be removed when the locale doesn't match. (case 3)
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 8, Locale.JAPANESE);
             assertSpanCount(2, text);
-            assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 1, 5, 8, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 1, 5, 8, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java
index 6c0d749..ffef911 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java
@@ -78,6 +78,7 @@
         assertArrayEquals(message, expected, actual);
     }
 
+    @SuppressWarnings("static-method")
     public void testEmptyEntry() {
         assertInsertAdditionalMoreKeys("null more keys and null additons",
                 null,
@@ -106,6 +107,7 @@
                 new String[] { "a", "A", "b", "B", "c", "d" });
     }
 
+    @SuppressWarnings("static-method")
     public void testInsertAdditionalMoreKeys() {
         // Escaped marker.
         assertInsertAdditionalMoreKeys("escaped marker",
@@ -306,6 +308,7 @@
         assertArrayEquals(message, expected, actual);
     }
 
+    @SuppressWarnings("static-method")
     public void testGetBooleanValue() {
         assertGetBooleanValue("Has label", HAS_LABEL,
                 new String[] { HAS_LABEL, "a", "b", "c" },
@@ -345,6 +348,7 @@
         assertArrayEquals(message, expected, actual);
     }
 
+    @SuppressWarnings("static-method")
     public void testGetIntValue() {
         assertGetIntValue("Fixed column order 3", FIXED_COLUMN_ORDER, -1,
                 new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" },
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
index 83e523c..07622c1 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
@@ -174,13 +174,12 @@
         if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
                 LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) {
             return file;
-        } else {
-            throw new IOException("Empty dictionary " + file.getAbsolutePath()
-                    + " cannot be created. Foramt version: " + formatVersion);
         }
+        throw new IOException("Empty dictionary " + file.getAbsolutePath()
+                + " cannot be created. Foramt version: " + formatVersion);
     }
 
-    private BinaryDictionary getBinaryDictionary(final File dictFile) {
+    private static BinaryDictionary getBinaryDictionary(final File dictFile) {
         return new BinaryDictionary(dictFile.getAbsolutePath(),
                 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
                 Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
@@ -683,7 +682,7 @@
         final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
 
         binaryDictionary.addUnigramEntry("", DUMMY_PROBABILITY, "" /* shortcutTarget */,
-                BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
+                Dictionary.NOT_A_PROBABILITY /* shortcutProbability */,
                 true /* isBeginningOfSentence */, true /* isNotAWord */,
                 false /* isPossiblyOffensive */, mCurrentTime);
         final NgramContext beginningOfSentenceContext = NgramContext.BEGINNING_OF_SENTENCE;
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index 0a1f5a3..5d63789 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -111,13 +111,12 @@
         if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
                 Locale.ENGLISH, attributeMap)) {
             return file;
-        } else {
-            throw new IOException("Empty dictionary " + file.getAbsolutePath()
-                    + " cannot be created. Format version: " + formatVersion);
         }
+        throw new IOException("Empty dictionary " + file.getAbsolutePath()
+                + " cannot be created. Format version: " + formatVersion);
     }
 
-    private BinaryDictionary getBinaryDictionary(final File dictFile) {
+    private static BinaryDictionary getBinaryDictionary(final File dictFile) {
         return new BinaryDictionary(dictFile.getAbsolutePath(),
                 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
                 Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
@@ -211,15 +210,14 @@
 
         assertEquals(probability, binaryDictionary.getFrequency("aaa"));
         assertEquals(updatedProbability, binaryDictionary.getFrequency(validLongWord));
-        assertEquals(BinaryDictionary.NOT_A_PROBABILITY,
-                binaryDictionary.getFrequency(invalidLongWord));
+        assertEquals(Dictionary.NOT_A_PROBABILITY, binaryDictionary.getFrequency(invalidLongWord));
         assertEquals(updatedProbability, binaryDictionary.getFrequency("abc"));
     }
 
     private static void addUnigramWord(final BinaryDictionary binaryDictionary, final String word,
             final int probability) {
         binaryDictionary.addUnigramEntry(word, probability, "" /* shortcutTarget */,
-                BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
+                Dictionary.NOT_A_PROBABILITY /* shortcutProbability */,
                 false /* isBeginningOfSentence */, false /* isNotAWord */,
                 false /* isPossiblyOffensive */,
                 BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
@@ -975,7 +973,7 @@
             final boolean isPossiblyOffensive = random.nextBoolean();
             // TODO: Add tests for historical info.
             binaryDictionary.addUnigramEntry(word, unigramProbability,
-                    null /* shortcutTarget */, BinaryDictionary.NOT_A_PROBABILITY,
+                    null /* shortcutTarget */, Dictionary.NOT_A_PROBABILITY,
                     false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive,
                     BinaryDictionary.NOT_A_VALID_TIMESTAMP);
             if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
@@ -1264,7 +1262,7 @@
         WordProperty wordProperty = binaryDictionary.getWordProperty("ddd", false);
         assertEquals(true, wordProperty.mIsPossiblyOffensive);
     }
-    
+
     public void testDictMigration() {
         for (final int formatVersion : DICT_FORMAT_VERSIONS) {
             testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
diff --git a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
index ae5cc5c..5146ea8 100644
--- a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
+++ b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
@@ -61,7 +61,6 @@
     public void testBlueUnderlineOnBackspace() {
         final String STRING_TO_TYPE = "tgis";
         final int typedLength = STRING_TO_TYPE.length();
-        final int EXPECTED_SUGGESTION_SPAN_START = -1;
         final int EXPECTED_UNDERLINE_SPAN_START = 0;
         final int EXPECTED_UNDERLINE_SPAN_END = 3;
         type(STRING_TO_TYPE);
diff --git a/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java b/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java
index ed3929d..3ad659a 100644
--- a/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java
+++ b/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java
@@ -47,7 +47,7 @@
                 getContext(), MAX_CACHE_SIZE_LARGE, ""));
     }
 
-    private void testGetFacilitator(final DictionaryFacilitatorLruCache cache) {
+    private static void testGetFacilitator(final DictionaryFacilitatorLruCache cache) {
         final DictionaryFacilitator dictionaryFacilitatorEnUs = cache.get(Locale.US);
         assertNotNull(dictionaryFacilitatorEnUs);
         assertTrue(dictionaryFacilitatorEnUs.isForLocales(new Locale[] { Locale.US }));
@@ -68,7 +68,7 @@
                 getContext(), MAX_CACHE_SIZE_LARGE, ""));
     }
 
-    private void testSetUseContactsDictionary(final DictionaryFacilitatorLruCache cache) {
+    private static void testSetUseContactsDictionary(final DictionaryFacilitatorLruCache cache) {
         assertNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
         cache.setUseContactsDictionary(true /* useContactsDictionary */);
         assertNotNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java
index afe7dbe..f9ab1ac 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java
@@ -25,7 +25,7 @@
 @LargeTest
 public class InputLogicTestsDeadKeys extends InputTestsBase {
     // A helper class for readability
-    private static class EventList extends ArrayList<Event> {
+    static class EventList extends ArrayList<Event> {
         public EventList addCodePoint(final int codePoint, final boolean isDead) {
             final Event event;
             if (isDead) {
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
index ab69c85..1372514 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
@@ -80,7 +80,6 @@
 @LargeTest
 // These tests are inactive until the combining code for Myanmar Reordering is sorted out.
 @Suppress
-@SuppressWarnings("rawtypes")
 public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
     // The tests are formatted as follows.
     // Each test is an entry in the array of Pair arrays.
@@ -90,7 +89,7 @@
     // member is stored the string that should be in the text view after this
     // key press.
 
-    private static final Pair[][] TESTS = {
+    private static final Pair<?, ?>[][] TESTS = {
 
         // Tests for U+1031 MYANMAR VOWEL SIGN E : ေ
         new Pair[] { // Type : U+1031 U+1000 U+101F ေ က ဟ
@@ -206,13 +205,12 @@
         */
     };
 
-    @SuppressWarnings("unchecked")
-    private void doMyanmarTest(final int testNumber, final Pair[] test) {
+    private void doMyanmarTest(final int testNumber, final Pair<?, ?>[] test) {
         int stepNumber = 0;
-        for (final Pair<int[], String> step : test) {
+        for (final Pair<?, ?> step : test) {
             ++stepNumber;
-            final int[] input = step.first;
-            final String expectedResult = step.second;
+            final int[] input = (int[]) step.first;
+            final String expectedResult = (String) step.second;
             if (input.length > 1) {
                 mLatinIME.onTextInput(new String(input, 0, input.length));
             } else {
@@ -226,7 +224,7 @@
     public void testMyanmarReordering() {
         int testNumber = 0;
         changeLanguage("my_MM", "CombiningRules=MyanmarReordering");
-        for (final Pair[] test : TESTS) {
+        for (final Pair<?, ?>[] test : TESTS) {
             // Small trick to reset LatinIME : setText("") and send updateSelection with values
             // LatinIME has never seen, and cursor pos 0,0.
             mEditText.setText("");
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index dd900a2..f58dad9 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -40,7 +40,6 @@
 import com.android.inputmethod.event.Event;
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.latin.Dictionary;
 import com.android.inputmethod.latin.Dictionary.PhonyDictionary;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.settings.DebugSettings;
@@ -250,7 +249,7 @@
     // Now, Looper#loop() never exits in normal operation unless the Looper#quit() method
     // is called, which has a lot of bad side effects. We can however just throw an exception
     // in the runnable which will unwind the stack and allow us to exit.
-    private final class InterruptRunMessagesException extends RuntimeException {
+    final class InterruptRunMessagesException extends RuntimeException {
         // Empty class
     }
     protected void runMessages() {
@@ -284,7 +283,7 @@
         } else {
             final int x = key.getX() + key.getWidth() / 2;
             final int y = key.getY() + key.getHeight() / 2;
-            event = mLatinIME.createSoftwareKeypressEvent(codePoint, x, y, isKeyRepeat);
+            event = LatinIME.createSoftwareKeypressEvent(codePoint, x, y, isKeyRepeat);
         }
         mLatinIME.onEvent(event);
         // Also see the comment at the top of this function about onReleaseKey
@@ -309,9 +308,8 @@
         final Key key = mKeyboard.getKey(codePoint);
         if (key == null) {
             throw new RuntimeException("Code point not on the keyboard");
-        } else {
-            return new Point(key.getX() + key.getWidth() / 2, key.getY() + key.getHeight() / 2);
         }
+        return new Point(key.getX() + key.getWidth() / 2, key.getY() + key.getHeight() / 2);
     }
 
     protected void gesture(final String stringToGesture) {
@@ -386,7 +384,7 @@
                 false /* isAuxiliary */,
                 false /* overridesImplicitlyEnabledSubtype */,
                 0 /* id */);
-        SubtypeSwitcher.getInstance().forceSubtype(subtype);
+        SubtypeSwitcher.forceSubtype(subtype);
         mLatinIME.onCurrentInputMethodSubtypeChanged(subtype);
         runMessages();
         mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();
diff --git a/tests/src/com/android/inputmethod/latin/NgramContextTests.java b/tests/src/com/android/inputmethod/latin/NgramContextTests.java
index ecc2c63..ab1819d 100644
--- a/tests/src/com/android/inputmethod/latin/NgramContextTests.java
+++ b/tests/src/com/android/inputmethod/latin/NgramContextTests.java
@@ -25,8 +25,8 @@
 public class NgramContextTests extends AndroidTestCase {
     public void testConstruct() {
         assertEquals(new NgramContext(new WordInfo("a")), new NgramContext(new WordInfo("a")));
-        assertEquals(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE),
-                new NgramContext(WordInfo.BEGINNING_OF_SENTENCE));
+        assertEquals(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO),
+                new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO));
         assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
                 new NgramContext(WordInfo.EMPTY_WORD_INFO));
         assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
@@ -35,17 +35,18 @@
 
     public void testIsBeginningOfSentenceContext() {
         assertFalse(new NgramContext().isBeginningOfSentenceContext());
-        assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE)
+        assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
                 .isBeginningOfSentenceContext());
         assertTrue(NgramContext.BEGINNING_OF_SENTENCE.isBeginningOfSentenceContext());
         assertFalse(new NgramContext(new WordInfo("a")).isBeginningOfSentenceContext());
         assertFalse(new NgramContext(new WordInfo("")).isBeginningOfSentenceContext());
         assertFalse(new NgramContext(WordInfo.EMPTY_WORD_INFO).isBeginningOfSentenceContext());
-        assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE, new WordInfo("a"))
+        assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO, new WordInfo("a"))
                 .isBeginningOfSentenceContext());
-        assertFalse(new NgramContext(new WordInfo("a"), WordInfo.BEGINNING_OF_SENTENCE)
+        assertFalse(new NgramContext(new WordInfo("a"), WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
                 .isBeginningOfSentenceContext());
-        assertFalse(new NgramContext(WordInfo.EMPTY_WORD_INFO, WordInfo.BEGINNING_OF_SENTENCE)
+        assertFalse(new NgramContext(
+                WordInfo.EMPTY_WORD_INFO, WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
                 .isBeginningOfSentenceContext());
     }
 
@@ -56,7 +57,7 @@
         assertEquals("b", ngramContext_b_a.getNthPrevWord(1));
         assertEquals("a", ngramContext_b_a.getNthPrevWord(2));
         final NgramContext ngramContext_bos_b =
-                ngramContext_b_a.getNextNgramContext(WordInfo.BEGINNING_OF_SENTENCE);
+                ngramContext_b_a.getNextNgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
         assertTrue(ngramContext_bos_b.isBeginningOfSentenceContext());
         assertEquals("b", ngramContext_bos_b.getNthPrevWord(2));
         final NgramContext ngramContext_c_bos =
diff --git a/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java b/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
index 7a32336..28c41f2 100644
--- a/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
+++ b/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
@@ -136,7 +136,7 @@
         }
     }
 
-    private class MockInputMethodService extends InputMethodService {
+    static class MockInputMethodService extends InputMethodService {
         private MockConnection mMockConnection;
         public void setInputConnection(final MockConnection mockConnection) {
             mMockConnection = mockConnection;
@@ -221,7 +221,6 @@
                 mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
         final SpacingAndPunctuations TAB = new SpacingAndPunctuations(
                 mSpacingAndPunctuations, new int[] { Constants.CODE_TAB });
-        final int[] SPACE_TAB = StringUtils.toSortedCodePointArray(" \t");
         // A character that needs surrogate pair to represent its code point (U+2008A).
         final String SUPPLEMENTARY_CHAR_STRING = "\uD840\uDC8A";
         final SpacingAndPunctuations SUPPLEMENTARY_CHAR = new SpacingAndPunctuations(
diff --git a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
index 8ba0174..a445f61 100644
--- a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
+++ b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
@@ -16,14 +16,10 @@
 
 package com.android.inputmethod.latin;
 
-import android.os.Build;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.text.TextUtils;
 import android.view.inputmethod.EditorInfo;
 
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.WordComposer;
-
 @LargeTest
 public class ShiftModeTests extends InputTestsBase {
 
diff --git a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
index 221541e..90db75e 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
@@ -60,7 +60,7 @@
     }
 
     // Helper for testGetTransformedWordInfo
-    private SuggestedWordInfo transformWordInfo(final String info,
+    private static SuggestedWordInfo transformWordInfo(final String info,
             final int trailingSingleQuotesCount) {
         final SuggestedWordInfo suggestedWordInfo = createTypedWordInfo(info);
         final SuggestedWordInfo returnedWordInfo =
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
index 05616d8..d1cb141 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
@@ -117,7 +117,7 @@
         super.tearDown();
     }
 
-    private void generateWords(final int number, final Random random) {
+    private static void generateWords(final int number, final Random random) {
         final int[] codePointSet = CodePointUtils.generateCodePointSet(DEFAULT_CODE_POINT_SET_SIZE,
                 random);
         final Set<String> wordSet = new HashSet<>();
@@ -138,7 +138,7 @@
     /**
      * Adds unigrams to the dictionary.
      */
-    private void addUnigrams(final int number, final FusionDictionary dict,
+    private static void addUnigrams(final int number, final FusionDictionary dict,
             final List<String> words, final HashMap<String, List<String>> shortcutMap) {
         for (int i = 0; i < number; ++i) {
             final String word = words.get(i);
@@ -154,7 +154,7 @@
         }
     }
 
-    private void addBigrams(final FusionDictionary dict,
+    private static void addBigrams(final FusionDictionary dict,
             final List<String> words,
             final SparseArray<List<Integer>> bigrams) {
         for (int i = 0; i < bigrams.size(); ++i) {
@@ -173,7 +173,7 @@
 //                new java.io.FileWriter(new File(filename)), dict);
 //    }
 
-    private long timeWritingDictToFile(final File file, final FusionDictionary dict,
+    private static long timeWritingDictToFile(final File file, final FusionDictionary dict,
             final FormatSpec.FormatOptions formatOptions) {
 
         long now = -1, diff = -1;
@@ -196,7 +196,7 @@
         return diff;
     }
 
-    private void checkDictionary(final FusionDictionary dict, final List<String> words,
+    private static void checkDictionary(final FusionDictionary dict, final List<String> words,
             final SparseArray<List<Integer>> bigrams,
             final HashMap<String, List<String>> shortcutMap) {
         assertNotNull(dict);
@@ -231,16 +231,16 @@
         }
     }
 
-    private String outputOptions(final int bufferType,
+    private static String outputOptions(final int bufferType,
             final FormatSpec.FormatOptions formatOptions) {
-        String result = " : buffer type = "
+        final String result = " : buffer type = "
                 + ((bufferType == BinaryDictUtils.USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
         return result + " : version = " + formatOptions.mVersion;
     }
 
     // Tests for readDictionaryBinary and writeDictionaryBinary
 
-    private long timeReadingAndCheckDict(final File file, final List<String> words,
+    private static long timeReadingAndCheckDict(final File file, final List<String> words,
             final SparseArray<List<Integer>> bigrams,
             final HashMap<String, List<String>> shortcutMap, final int bufferType) {
         long now, diff = -1;
@@ -385,7 +385,7 @@
 
     // Tests for readUnigramsAndBigramsBinary
 
-    private void checkWordMap(final List<String> expectedWords,
+    private static void checkWordMap(final List<String> expectedWords,
             final SparseArray<List<Integer>> expectedBigrams,
             final TreeMap<Integer, String> resultWords,
             final TreeMap<Integer, Integer> resultFrequencies,
@@ -434,9 +434,9 @@
         assertEquals(actBigrams, expBigrams);
     }
 
-    private long timeAndCheckReadUnigramsAndBigramsBinary(final File file, final List<String> words,
-            final SparseArray<List<Integer>> bigrams, final int bufferType,
-            final boolean checkProbability) {
+    private static long timeAndCheckReadUnigramsAndBigramsBinary(final File file,
+            final List<String> words, final SparseArray<List<Integer>> bigrams,
+            final int bufferType, final boolean checkProbability) {
         final TreeMap<Integer, String> resultWords = new TreeMap<>();
         final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams = new TreeMap<>();
         final TreeMap<Integer, Integer> resultFreqs = new TreeMap<>();
@@ -519,7 +519,7 @@
     }
 
     // Tests for getTerminalPosition
-    private String getWordFromBinary(final DictDecoder dictDecoder, final int address) {
+    private static String getWordFromBinary(final DictDecoder dictDecoder, final int address) {
         if (dictDecoder.getPosition() != 0) dictDecoder.setPosition(0);
 
         DictionaryHeader fileHeader = null;
@@ -535,7 +535,7 @@
                 address).mWord;
     }
 
-    private long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
+    private static long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
             final boolean contained) {
         long diff = -1;
         int position = -1;
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
index 1f3ee19..21411f2 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
@@ -113,15 +113,16 @@
         /**
          * Helper method to find out whether this code fits on one byte
          */
-        private static boolean fitsOnOneByte(int character,
+        private static boolean fitsOnOneByte(final int character,
                 final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+            int codePoint = character;
             if (codePointToOneByteCodeMap != null) {
                 if (codePointToOneByteCodeMap.containsKey(character)) {
-                    character = codePointToOneByteCodeMap.get(character);
+                    codePoint = codePointToOneByteCodeMap.get(character);
                 }
             }
-            return character >= FormatSpec.MINIMAL_ONE_BYTE_CHARACTER_VALUE
-                    && character <= FormatSpec.MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
+            return codePoint >= FormatSpec.MINIMAL_ONE_BYTE_CHARACTER_VALUE
+                    && codePoint <= FormatSpec.MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
         }
 
         /**
@@ -168,8 +169,9 @@
          * @param codePointToOneByteCodeMap the map to convert the code point.
          * @return the index after the last character.
          */
-        static int writeCharArray(final int[] codePoints, final byte[] buffer, int index,
+        static int writeCharArray(final int[] codePoints, final byte[] buffer, final int fromIndex,
                 final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+            int index = fromIndex;
             for (int codePoint : codePoints) {
                 if (codePointToOneByteCodeMap != null) {
                     if (codePointToOneByteCodeMap.containsKey(codePoint)) {
@@ -293,10 +295,9 @@
         final int msb = dictBuffer.readUnsignedByte();
         if (FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT >= msb) {
             return msb;
-        } else {
-            return ((FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT & msb) << 8)
-                    + dictBuffer.readUnsignedByte();
         }
+        return ((FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT & msb) << 8)
+                + dictBuffer.readUnsignedByte();
     }
 
     /**
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
index 09bf221..a3a71a4 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
@@ -199,8 +199,9 @@
         }
     }
 
-    static int writeUIntToBuffer(final byte[] buffer, int position, final int value,
+    static int writeUIntToBuffer(final byte[] buffer, final int fromPosition, final int value,
             final int size) {
+        int position = fromPosition;
         switch(size) {
             case 4:
                 buffer[position++] = (byte) ((value >> 24) & 0xFF);
@@ -324,11 +325,9 @@
             return targetNodeArray.mCachedAddressAfterUpdate
                     - (currentNodeArray.mCachedAddressAfterUpdate
                             + offsetFromStartOfCurrentNodeArray);
-        } else {
-            return targetNodeArray.mCachedAddressBeforeUpdate
-                    - (currentNodeArray.mCachedAddressBeforeUpdate
-                            + offsetFromStartOfCurrentNodeArray);
         }
+        return targetNodeArray.mCachedAddressBeforeUpdate
+                - (currentNodeArray.mCachedAddressBeforeUpdate + offsetFromStartOfCurrentNodeArray);
     }
 
     /**
@@ -356,9 +355,8 @@
             final int newOffsetBasePoint = currentNodeArray.mCachedAddressAfterUpdate
                     + offsetFromStartOfCurrentNodeArray;
             return targetPtNode.mCachedAddressAfterUpdate - newOffsetBasePoint;
-        } else {
-            return targetPtNode.mCachedAddressBeforeUpdate - oldOffsetBasePoint;
         }
+        return targetPtNode.mCachedAddressBeforeUpdate - oldOffsetBasePoint;
     }
 
     /**
@@ -541,8 +539,9 @@
      * @param position the position to write.
      * @return the size in bytes the address actually took.
      */
-    /* package */ static int writeChildrenPosition(final byte[] buffer, int index,
+    /* package */ static int writeChildrenPosition(final byte[] buffer, final int fromIndex,
             final int position) {
+        int index = fromIndex;
         switch (getByteSize(position)) {
         case 1:
             buffer[index++] = (byte)position;
@@ -623,7 +622,7 @@
      * @return the flags
      */
     /* package */ static final int makeBigramFlags(final boolean more, final int offset,
-            int bigramFrequency, final int unigramFrequency, final String word) {
+            final int bigramFrequency, final int unigramFrequency, final String word) {
         int bigramFlags = (more ? FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT : 0)
                 + (offset < 0 ? FormatSpec.FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE : 0);
         switch (getByteSize(offset)) {
@@ -639,13 +638,16 @@
         default:
             throw new RuntimeException("Strange offset size");
         }
+        final int frequency;
         if (unigramFrequency > bigramFrequency) {
             MakedictLog.e("Unigram freq is superior to bigram freq for \"" + word
                     + "\". Bigram freq is " + bigramFrequency + ", unigram freq for "
                     + word + " is " + unigramFrequency);
-            bigramFrequency = unigramFrequency;
+            frequency = unigramFrequency;
+        } else {
+            frequency = bigramFrequency;
         }
-        bigramFlags += getBigramFrequencyDiff(unigramFrequency, bigramFrequency)
+        bigramFlags += getBigramFrequencyDiff(unigramFrequency, frequency)
                 & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY;
         return bigramFlags;
     }
@@ -722,7 +724,6 @@
      * @param ptNodeArray the node array to write.
      * @param codePointToOneByteCodeMap the map to convert the code points.
      */
-    @SuppressWarnings("unused")
     /* package */ static void writePlacedPtNodeArray(final FusionDictionary dict,
             final DictEncoder dictEncoder, final PtNodeArray ptNodeArray,
             final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
index 9c3b373..5e90387 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
@@ -206,11 +206,7 @@
                     if (same) {
                         // found the PtNode matches the word.
                         if (wordPos + currentInfo.mCharacters.length == wordLen) {
-                            if (!currentInfo.isTerminal()) {
-                                return FormatSpec.NOT_VALID_WORD;
-                            } else {
-                                return ptNodePos;
-                            }
+                            return currentInfo.isTerminal() ? ptNodePos : FormatSpec.NOT_VALID_WORD;
                         }
                         wordPos += currentInfo.mCharacters.length;
                         if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) {
diff --git a/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index ea5bc56..5581d68 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -142,11 +142,7 @@
         }
 
         public int getProbability() {
-            if (isTerminal()) {
-                return mProbabilityInfo.mProbability;
-            } else {
-                return NOT_A_TERMINAL;
-            }
+            return isTerminal() ? mProbabilityInfo.mProbability : NOT_A_TERMINAL;
         }
 
         public boolean getIsNotAWord() {
@@ -235,7 +231,7 @@
          * the existing ones if any. Note: unigram, bigram, and shortcut frequencies are only
          * updated if they are higher than the existing ones.
          */
-        private void update(final ProbabilityInfo probabilityInfo,
+        void update(final ProbabilityInfo probabilityInfo,
                 final ArrayList<WeightedString> shortcutTargets,
                 final ArrayList<WeightedString> bigrams,
                 final boolean isNotAWord, final boolean isPossiblyOffensive) {
@@ -337,15 +333,15 @@
      * This method checks that all PtNodes in a node array are ordered as expected.
      * If they are, nothing happens. If they aren't, an exception is thrown.
      */
-    private void checkStack(PtNodeArray ptNodeArray) {
+    private static void checkStack(PtNodeArray ptNodeArray) {
         ArrayList<PtNode> stack = ptNodeArray.mData;
         int lastValue = -1;
         for (int i = 0; i < stack.size(); ++i) {
             int currentValue = stack.get(i).mChars[0];
-            if (currentValue <= lastValue)
+            if (currentValue <= lastValue) {
                 throw new RuntimeException("Invalid stack");
-            else
-                lastValue = currentValue;
+            }
+            lastValue = currentValue;
         }
     }
 
@@ -521,14 +517,14 @@
      * is ignored.
      * This comparator imposes orderings that are inconsistent with equals.
      */
-    static private final class PtNodeComparator implements java.util.Comparator<PtNode> {
+    static final class PtNodeComparator implements java.util.Comparator<PtNode> {
         @Override
         public int compare(PtNode p1, PtNode p2) {
             if (p1.mChars[0] == p2.mChars[0]) return 0;
             return p1.mChars[0] < p2.mChars[0] ? -1 : 1;
         }
     }
-    final static private PtNodeComparator PTNODE_COMPARATOR = new PtNodeComparator();
+    final static PtNodeComparator PTNODE_COMPARATOR = new PtNodeComparator();
 
     /**
      * Finds the insertion index of a character within a node array.
@@ -559,7 +555,8 @@
     /**
      * Helper method to find a word in a given branch.
      */
-    public static PtNode findWordInTree(PtNodeArray nodeArray, final String string) {
+    public static PtNode findWordInTree(final PtNodeArray rootNodeArray, final String string) {
+        PtNodeArray nodeArray = rootNodeArray;
         int index = 0;
         final StringBuilder checker = DBG ? new StringBuilder() : null;
         final int[] codePoints = getCodePoints(string);
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
index 7894f0b..457e7af 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
@@ -36,17 +36,17 @@
     /**
      * A utility class for reading a PtNode.
      */
-    protected static class PtNodeReader {
-        private static ProbabilityInfo readProbabilityInfo(final DictBuffer dictBuffer) {
+    static class PtNodeReader {
+        static ProbabilityInfo readProbabilityInfo(final DictBuffer dictBuffer) {
             // Ver2 dicts don't contain historical information.
             return new ProbabilityInfo(dictBuffer.readUnsignedByte());
         }
 
-        protected static int readPtNodeOptionFlags(final DictBuffer dictBuffer) {
+        static int readPtNodeOptionFlags(final DictBuffer dictBuffer) {
             return dictBuffer.readUnsignedByte();
         }
 
-        protected static int readChildrenAddress(final DictBuffer dictBuffer,
+        static int readChildrenAddress(final DictBuffer dictBuffer,
                 final int ptNodeFlags) {
             switch (ptNodeFlags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) {
                 case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE:
@@ -62,7 +62,7 @@
         }
 
         // Reads shortcuts and returns the read length.
-        protected static int readShortcut(final DictBuffer dictBuffer,
+        static int readShortcut(final DictBuffer dictBuffer,
                 final ArrayList<WeightedString> shortcutTargets) {
             final int pointerBefore = dictBuffer.position();
             dictBuffer.readUnsignedShort(); // skip the size
@@ -76,7 +76,7 @@
             return dictBuffer.position() - pointerBefore;
         }
 
-        protected static int readBigramAddresses(final DictBuffer dictBuffer,
+        static int readBigramAddresses(final DictBuffer dictBuffer,
                 final ArrayList<PendingAttribute> bigrams, final int baseAddress) {
             int readLength = 0;
             int bigramCount = 0;
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java
index 988cd37..7d85876 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java
@@ -27,14 +27,12 @@
 
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
 
 /**
  * Unit tests for Ver2DictEncoder
  */
 @LargeTest
 public class Ver2DictEncoderTests extends AndroidTestCase {
-    private static final String TAG = Ver2DictEncoderTests.class.getSimpleName();
     private static final int UNIGRAM_FREQ = 10;
 
     public void testCodePointTable() {
@@ -75,7 +73,7 @@
     /**
      * Adds unigrams to the dictionary.
      */
-    private void addUnigrams(final FusionDictionary dict, final List<String> words,
+    private static void addUnigrams(final FusionDictionary dict, final List<String> words,
             final HashMap<String, List<String>> shortcutMap) {
         for (final String word : words) {
             final ArrayList<WeightedString> shortcuts = new ArrayList<>();
diff --git a/tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java b/tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java
index fed8be9..8f24cdb 100644
--- a/tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java
+++ b/tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java
@@ -128,7 +128,7 @@
         assertTrue("ResponseProcessor was not invoked", processor.mInvoked);
     }
 
-    private static class FakeErrorResponseProcessor implements ResponseProcessor<Void> {
+    static class FakeErrorResponseProcessor implements ResponseProcessor<Void> {
         @Override
         public Void onSuccess(InputStream response) {
             fail("Expected an error but received success");
diff --git a/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java
index 0113099..f07dac7 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java
@@ -34,8 +34,6 @@
  */
 @LargeTest
 public class ContextualDictionaryTests extends AndroidTestCase {
-    private static final String TAG = ContextualDictionaryTests.class.getSimpleName();
-
     private static final Locale LOCALE_EN_US = new Locale("en", "US");
 
     private DictionaryFacilitator getDictionaryFacilitator() {
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
index 7666273..778f6e8 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
@@ -67,14 +67,14 @@
         FileUtils.deleteFilteredFiles(dictFile.getParentFile(), filenameFilter);
     }
 
-    private void printAllFiles(final File dir) {
+    private static void printAllFiles(final File dir) {
         Log.d(TAG, dir.getAbsolutePath());
         for (final File file : dir.listFiles()) {
             Log.d(TAG, "  " + file.getName());
         }
     }
 
-    private void checkExistenceAndRemoveDictFile(final UserHistoryDictionary dict,
+    private static void checkExistenceAndRemoveDictFile(final UserHistoryDictionary dict,
             final File dictFile) {
         Log.d(TAG, "waiting for writing ...");
         dict.waitAllTasksForTests();
@@ -193,7 +193,7 @@
      * Clear all entries in the user history dictionary.
      * @param dict the user history dictionary.
      */
-    private void clearHistory(final UserHistoryDictionary dict) {
+    private static void clearHistory(final UserHistoryDictionary dict) {
         dict.waitAllTasksForTests();
         dict.clear();
         dict.close();
diff --git a/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
index 2ef8b54..36e9672 100644
--- a/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
+++ b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
@@ -17,7 +17,7 @@
 package com.android.inputmethod.latin.settings;
 
 import android.app.AlertDialog;
-import android.app.Dialog;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -33,8 +33,6 @@
     private static final String FRAG_NAME = AccountsSettingsFragment.class.getName();
     private static final long TEST_TIMEOUT_MILLIS = 5000;
 
-    private AlertDialog mDialog;
-
     public AccountsSettingsFragmentTests() {
         super(TestFragmentActivity.class);
     }
@@ -58,21 +56,29 @@
         }
     }
 
+    private static class DialogHolder {
+        AlertDialog mDialog;
+        DialogHolder() {}
+    }
+
     public void testMultipleAccounts_noCurrentAccount() {
         final AccountsSettingsFragment fragment =
                 (AccountsSettingsFragment) getActivity().mFragment;
+        final DialogHolder dialogHolder = new DialogHolder();
         final CountDownLatch latch = new CountDownLatch(1);
+
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mDialog = fragment.createAccountPicker(
+                final AlertDialog dialog = fragment.createAccountPicker(
                         new String[] {
                                 "1@example.com",
                                 "2@example.com",
                                 "3@example.com",
                                 "4@example.com"},
                         null);
-                mDialog.show();
+                dialog.show();
+                dialogHolder.mDialog = dialog;
                 latch.countDown();
             }
         });
@@ -83,32 +89,38 @@
             fail();
         }
         getInstrumentation().waitForIdleSync();
-        final ListView lv = mDialog.getListView();
+        final AlertDialog dialog = dialogHolder.mDialog;
+        final ListView lv = dialog.getListView();
         // The 1st account should be checked by default.
         assertEquals("checked-item", 0, lv.getCheckedItemPosition());
         // There should be 4 accounts in the list.
         assertEquals("count", 4, lv.getCount());
         // The sign-out button shouldn't exist
-        assertEquals(View.GONE, mDialog.getButton(Dialog.BUTTON_NEUTRAL).getVisibility());
-        assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_NEGATIVE).getVisibility());
-        assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_POSITIVE).getVisibility());
+        assertEquals(View.GONE,
+                dialog.getButton(DialogInterface.BUTTON_NEUTRAL).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_POSITIVE).getVisibility());
     }
 
     public void testMultipleAccounts_currentAccount() {
         final AccountsSettingsFragment fragment =
                 (AccountsSettingsFragment) getActivity().mFragment;
+        final DialogHolder dialogHolder = new DialogHolder();
         final CountDownLatch latch = new CountDownLatch(1);
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mDialog = fragment.createAccountPicker(
+                final AlertDialog dialog = fragment.createAccountPicker(
                         new String[] {
                                 "1@example.com",
                                 "2@example.com",
                                 "3@example.com",
                                 "4@example.com"},
                         "3@example.com");
-                mDialog.show();
+                dialog.show();
+                dialogHolder.mDialog = dialog;
                 latch.countDown();
             }
         });
@@ -119,14 +131,18 @@
             fail();
         }
         getInstrumentation().waitForIdleSync();
-        final ListView lv = mDialog.getListView();
+        final AlertDialog dialog = dialogHolder.mDialog;
+        final ListView lv = dialog.getListView();
         // The 3rd account should be checked by default.
         assertEquals("checked-item", 2, lv.getCheckedItemPosition());
         // There should be 4 accounts in the list.
         assertEquals("count", 4, lv.getCount());
         // The sign-out button should be shown
-        assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_NEUTRAL).getVisibility());
-        assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_NEGATIVE).getVisibility());
-        assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_POSITIVE).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_NEUTRAL).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_POSITIVE).getVisibility());
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java b/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
index 1501e94..170d643 100644
--- a/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
@@ -22,14 +22,14 @@
 
 @MediumTest
 public class AsyncResultHolderTests extends AndroidTestCase {
-    private static final String TAG = AsyncResultHolderTests.class.getSimpleName();
+    static final String TAG = AsyncResultHolderTests.class.getSimpleName();
 
     private static final int TIMEOUT_IN_MILLISECONDS = 500;
     private static final int MARGIN_IN_MILLISECONDS = 250;
     private static final int DEFAULT_VALUE = 2;
     private static final int SET_VALUE = 1;
 
-    private <T> void setAfterGivenTime(final AsyncResultHolder<T> holder, final T value,
+    private static <T> void setAfterGivenTime(final AsyncResultHolder<T> holder, final T value,
             final long time) {
         new Thread(new Runnable() {
             @Override
diff --git a/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java
index a333ee9..131865a 100644
--- a/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java
@@ -39,10 +39,8 @@
             final int formatVersion) throws IOException {
         if (formatVersion == FormatSpec.VERSION4) {
             return createEmptyVer4DictionaryAndGetFile(dictId);
-        } else {
-            throw new IOException("Dictionary format version " + formatVersion
-                    + " is not supported.");
         }
+        throw new IOException("Dictionary format version " + formatVersion + " is not supported.");
     }
 
     private File createEmptyVer4DictionaryAndGetFile(final String dictId) throws IOException {
@@ -59,10 +57,8 @@
         if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), FormatSpec.VERSION4,
                 LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) {
             return file;
-        } else {
-            throw new IOException("Empty dictionary " + file.getAbsolutePath()
-                    + " cannot be created.");
         }
+        throw new IOException("Empty dictionary " + file.getAbsolutePath() + " cannot be created.");
     }
 
     private File getDictFile(final String dictId) {
diff --git a/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
index 76e2828..8bda672 100644
--- a/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
@@ -47,7 +47,7 @@
      */
     public void testIsNullOrEmpty() {
         assertTrue(CollectionUtils.isNullOrEmpty(null));
-        assertTrue(CollectionUtils.isNullOrEmpty(new ArrayList()));
+        assertTrue(CollectionUtils.isNullOrEmpty(new ArrayList<>()));
         assertTrue(CollectionUtils.isNullOrEmpty(Collections.EMPTY_SET));
         assertFalse(CollectionUtils.isNullOrEmpty(Collections.singleton("Not empty")));
     }
diff --git a/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java b/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java
index 8f58e68..7519bec 100644
--- a/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java
@@ -79,13 +79,13 @@
     public void testGet() {
         final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
         try {
-            final int value = src.get(0);
+            src.get(0);
             fail("get(0) shouldn't succeed");
         } catch (ArrayIndexOutOfBoundsException e) {
             // success
         }
         try {
-            final int value = src.get(DEFAULT_CAPACITY);
+            src.get(DEFAULT_CAPACITY);
             fail("get(DEFAULT_CAPACITY) shouldn't succeed");
         } catch (ArrayIndexOutOfBoundsException e) {
             // success
@@ -98,7 +98,7 @@
         assertEquals("value after add at " + index, valueAddAt, src.get(index));
         assertEquals("value after add at 0", 0, src.get(0));
         try {
-            final int value = src.get(src.getLength());
+            src.get(src.getLength());
             fail("get(length) shouldn't succeed");
         } catch (ArrayIndexOutOfBoundsException e) {
             // success
diff --git a/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
index fa6ad16..11d10aa 100644
--- a/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
@@ -21,7 +21,6 @@
 import android.text.style.SuggestionSpan;
 import android.text.style.URLSpan;
 import android.text.SpannableStringBuilder;
-import android.text.Spannable;
 import android.text.Spanned;
 
 @SmallTest
@@ -34,8 +33,8 @@
         for (int i = 0; i < N; ++i) {
             // Put a PARAGRAPH-flagged span that should not be found in the result.
             s.setSpan(new SuggestionSpan(getContext(),
-                    new String[] {"" + i}, Spannable.SPAN_PARAGRAPH),
-                    i * 12, i * 12 + 12, Spannable.SPAN_PARAGRAPH);
+                    new String[] {"" + i}, Spanned.SPAN_PARAGRAPH),
+                    i * 12, i * 12 + 12, Spanned.SPAN_PARAGRAPH);
             // Put a normal suggestion span that should be found in the result.
             s.setSpan(new SuggestionSpan(getContext(), new String[] {"" + i}, 0), i, i * 2, 0);
             // Put a URL span than should not be found in the result.
@@ -51,7 +50,7 @@
         for (int i = 0; i < spans.length; i++) {
             final int flags = result.getSpanFlags(spans[i]);
             assertEquals("Should not find a span with PARAGRAPH flag",
-                    flags & Spannable.SPAN_PARAGRAPH, 0);
+                    flags & Spanned.SPAN_PARAGRAPH, 0);
             assertTrue("Should be a SuggestionSpan", spans[i] instanceof SuggestionSpan);
         }
     }
diff --git a/tools/dicttool/compat/android/text/TextUtils.java b/tools/dicttool/compat/android/text/TextUtils.java
index 5a94b7d..8248331 100644
--- a/tools/dicttool/compat/android/text/TextUtils.java
+++ b/tools/dicttool/compat/android/text/TextUtils.java
@@ -25,10 +25,7 @@
      * @return true if str is null or zero length
      */
     public static boolean isEmpty(CharSequence str) {
-        if (str == null || str.length() == 0)
-            return true;
-        else
-            return false;
+        return (str == null || str.length() == 0);
     }
 
     /**
@@ -45,12 +42,11 @@
         if (a != null && b != null && (length = a.length()) == b.length()) {
             if (a instanceof String && b instanceof String) {
                 return a.equals(b);
-            } else {
-                for (int i = 0; i < length; i++) {
-                    if (a.charAt(i) != b.charAt(i)) return false;
-                }
-                return true;
             }
+            for (int i = 0; i < length; i++) {
+                if (a.charAt(i) != b.charAt(i)) return false;
+            }
+            return true;
         }
         return false;
     }
@@ -90,7 +86,7 @@
      * @param tokens an array objects to be joined. Strings will be formed from
      *     the objects by calling object.toString().
      */
-    public static String join(CharSequence delimiter, Iterable tokens) {
+    public static String join(CharSequence delimiter, Iterable<?> tokens) {
         StringBuilder sb = new StringBuilder();
         boolean firstTime = true;
         for (Object token: tokens) {
diff --git a/tools/dicttool/compat/android/util/Pair.java b/tools/dicttool/compat/android/util/Pair.java
index ab6096e..e61e896 100644
--- a/tools/dicttool/compat/android/util/Pair.java
+++ b/tools/dicttool/compat/android/util/Pair.java
@@ -16,7 +16,6 @@
 
 package android.util;
 
-import java.util.Arrays;
 import java.util.Objects;
 
 public class Pair<T1, T2> {
diff --git a/tools/dicttool/compat/android/view/inputmethod/CompletionInfo.java b/tools/dicttool/compat/android/view/inputmethod/CompletionInfo.java
index fbce725..e2f769e 100644
--- a/tools/dicttool/compat/android/view/inputmethod/CompletionInfo.java
+++ b/tools/dicttool/compat/android/view/inputmethod/CompletionInfo.java
@@ -16,6 +16,7 @@
 
 package android.view.inputmethod;
 
+@SuppressWarnings("static-method")
 public class CompletionInfo {
     public final String getText() { return ""; }
 }
diff --git a/tools/dicttool/compat/com/android/inputmethod/keyboard/Key.java b/tools/dicttool/compat/com/android/inputmethod/keyboard/Key.java
index 1e63bb5..9259406 100644
--- a/tools/dicttool/compat/com/android/inputmethod/keyboard/Key.java
+++ b/tools/dicttool/compat/com/android/inputmethod/keyboard/Key.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.keyboard;
 
+@SuppressWarnings("static-method")
 public class Key {
     public final int getX() { return 0; }
     public final int getY() { return 0; }
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 5dfb7bf..2925fdc 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
@@ -37,7 +37,6 @@
 import java.io.FileNotFoundException;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.Arrays;
 import java.util.LinkedList;
@@ -126,7 +125,7 @@
             }
         }
 
-        private void displayHelp() {
+        private static void displayHelp() {
             MakedictLog.i(getHelp());
         }
 
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
index 1f67982..47ea706 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
@@ -16,10 +16,8 @@
 
 package com.android.inputmethod.latin.dicttool;
 
-import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
index 86bc20e..1a4f096 100644
--- a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
+++ b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
@@ -67,17 +67,18 @@
         }
     }
 
-    private void checkDictionary(final FusionDictionary dict, final ArrayList<String> words,
-            int limit) {
+    private static void checkDictionary(final FusionDictionary dict, final ArrayList<String> words,
+            final int limit) {
         assertNotNull(dict);
+        int count = limit;
         for (final String word : words) {
-            if (--limit < 0) return;
+            if (--count < 0) return;
             final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, word);
             assertNotNull(ptNode);
         }
     }
 
-    private String dumpWord(final String word) {
+    private static String dumpWord(final String word) {
         final StringBuilder sb = new StringBuilder("");
         for (int i = 0; i < word.length(); i = word.offsetByCodePoints(i, 1)) {
             sb.append(word.codePointAt(i));
@@ -86,7 +87,7 @@
         return sb.toString();
     }
 
-    private void dumpDict(final FusionDictionary dict) {
+    private static void dumpDict(final FusionDictionary dict) {
         for (WordProperty wordProperty : dict) {
             System.out.println("Word " + dumpWord(wordProperty.mWord));
         }