Remove shortcut support from LatinIME.

Note this change does not affect the native decoder interface.

Change-Id: I73b7dc008a5acaf75a31a36a2d332b5afabd82d0
diff --git a/common/src/com/android/inputmethod/latin/common/Constants.java b/common/src/com/android/inputmethod/latin/common/Constants.java
index baa8592..a2d21a8 100644
--- a/common/src/com/android/inputmethod/latin/common/Constants.java
+++ b/common/src/com/android/inputmethod/latin/common/Constants.java
@@ -16,11 +16,20 @@
 
 package com.android.inputmethod.latin.common;
 
+import android.os.Build;
+
 import com.android.inputmethod.annotations.UsedForTesting;
 
 import javax.annotation.Nonnull;
 
 public final class Constants {
+
+    public static final boolean JELLY_BEAN_OR_HIGHER =
+            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
+
+    public static final boolean JELLY_BEAN_MR1_OR_HIGHER =
+            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
+
     public static final class Color {
         /**
          * The alpha value for fully opaque.
diff --git a/java/res/layout/user_dictionary_add_word_fullscreen.xml b/java/res/layout/user_dictionary_add_word_fullscreen.xml
index 9bcb189..cbdfba6 100644
--- a/java/res/layout/user_dictionary_add_word_fullscreen.xml
+++ b/java/res/layout/user_dictionary_add_word_fullscreen.xml
@@ -44,26 +44,6 @@
         android:columnCount="2" >
 
         <TextView
-            android:id="@+id/user_dictionary_add_shortcut_label"
-            style="?android:attr/textAppearanceSmall"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="start|center_vertical"
-            android:text="@string/user_dict_settings_add_shortcut_option_name" />
-
-        <EditText
-            android:id="@+id/user_dictionary_add_shortcut"
-            android:layout_width="wrap_content"
-            android:layout_gravity="fill_horizontal|center_vertical"
-            android:layout_marginBottom="8dip"
-            android:layout_marginStart="8dip"
-            android:layout_marginTop="8dip"
-            android:hint="@string/user_dict_settings_add_shortcut_hint"
-            android:imeOptions="flagNoFullscreen"
-            android:inputType="textNoSuggestions"
-            android:maxLength="@integer/config_user_dictionary_max_word_length" />
-
-        <TextView
             android:id="@+id/user_dictionary_add_locale_label"
             style="?android:attr/textAppearanceSmall"
             android:layout_width="wrap_content"
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index b0072ee..48aef4b 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -35,6 +35,7 @@
 import com.android.inputmethod.compat.SettingsSecureCompatUtils;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.InputTypeUtils;
 
 public final class AccessibilityUtils {
@@ -221,7 +222,7 @@
 
         // Platforms starting at SDK version 16 (Build.VERSION_CODES.JELLY_BEAN) should use
         // announce events.
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+        if (Constants.JELLY_BEAN_OR_HIGHER) {
             event.setEventType(AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
         } else {
             event.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
index 58ad4bd..8538308 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
@@ -38,7 +38,7 @@
                     int.class, int.class, String.class, String.class, String.class, boolean.class,
                     boolean.class, int.class);
     static {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+        if (Constants.JELLY_BEAN_MR1_OR_HIGHER) {
             if (CONSTRUCTOR_INPUT_METHOD_SUBTYPE == null) {
                 android.util.Log.w(TAG, "Warning!!! Constructor is not defined.");
             }
@@ -59,8 +59,7 @@
     public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale,
             String mode, String extraValue, boolean isAuxiliary,
             boolean overridesImplicitlyEnabledSubtype, int id) {
-        if (CONSTRUCTOR_INPUT_METHOD_SUBTYPE == null
-                || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
+        if (CONSTRUCTOR_INPUT_METHOD_SUBTYPE == null || !Constants.JELLY_BEAN_MR1_OR_HIGHER) {
             return new InputMethodSubtype(nameId, iconId, locale, mode, extraValue, isAuxiliary,
                     overridesImplicitlyEnabledSubtype);
         }
diff --git a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
index 70ab972..0646558 100644
--- a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
@@ -17,7 +17,8 @@
 package com.android.inputmethod.compat;
 
 import android.app.Notification;
-import android.os.Build;
+
+import com.android.inputmethod.latin.common.Constants;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
@@ -73,7 +74,7 @@
 
     @SuppressWarnings("deprecation")
     public static Notification build(final Notification.Builder builder) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+        if (Constants.JELLY_BEAN_OR_HIGHER) {
             // #build was added in API level 16, JELLY_BEAN
             return (Notification) CompatUtils.invoke(builder, null, METHOD_build);
         }
diff --git a/java/src/com/android/inputmethod/compat/UserDictionaryCompatUtils.java b/java/src/com/android/inputmethod/compat/UserDictionaryCompatUtils.java
deleted file mode 100644
index b78c357..0000000
--- a/java/src/com/android/inputmethod/compat/UserDictionaryCompatUtils.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.compat;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.os.Build;
-import android.provider.UserDictionary;
-
-import java.util.Locale;
-
-public final class UserDictionaryCompatUtils {
-    @SuppressWarnings("deprecation")
-    public static void addWord(final Context context, final String word,
-            final int freq, final String shortcut, final Locale locale) {
-        if (BuildCompatUtils.EFFECTIVE_SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            addWordWithShortcut(context, word, freq, shortcut, locale);
-            return;
-        }
-        // Fall back to the pre-JellyBean method.
-        final Locale currentLocale = context.getResources().getConfiguration().locale;
-        final int localeType = currentLocale.equals(locale)
-                ? UserDictionary.Words.LOCALE_TYPE_CURRENT : UserDictionary.Words.LOCALE_TYPE_ALL;
-        UserDictionary.Words.addWord(context, word, freq, localeType);
-    }
-
-    // {@link UserDictionary.Words#addWord(Context,String,int,String,Locale)} was introduced
-    // in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    private static void addWordWithShortcut(final Context context, final String word,
-            final int freq, final String shortcut, final Locale locale) {
-        UserDictionary.Words.addWord(context, word, freq, shortcut, locale);
-    }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 46476e2..fca5ecb 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -40,13 +40,11 @@
 import com.android.inputmethod.latin.settings.SettingsValues;
 import com.android.inputmethod.latin.utils.CapsModeUtils;
 import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
-import com.android.inputmethod.latin.utils.NetworkConnectivityUtils;
 import com.android.inputmethod.latin.utils.RecapitalizeStatus;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 import com.android.inputmethod.latin.utils.ScriptUtils;
 
-public final class KeyboardSwitcher implements KeyboardState.SwitchActions,
-        NetworkConnectivityUtils.NetworkStateChangeListener {
+public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
     private static final String TAG = KeyboardSwitcher.class.getSimpleName();
 
     private InputView mCurrentInputView;
@@ -412,15 +410,6 @@
         return mCurrentInputView;
     }
 
-    // {@link NetworkConnectivityUtils.NetworkStateChangeListener#onNetworkStateChanged(boolean)}.
-    @Override
-    public void onNetworkStateChanged() {
-        if (mKeyboardView == null) {
-            return;
-        }
-        mKeyboardView.updateShortcutKey(mRichImm.isShortcutImeReady());
-    }
-
     public int getKeyboardShiftMode() {
         final Keyboard keyboard = getKeyboard();
         if (keyboard == null) {
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index ab8b751..ce4bb74 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -694,25 +694,25 @@
     }
 
     @Override
-    public boolean onTouchEvent(final MotionEvent me) {
+    public boolean onTouchEvent(final MotionEvent event) {
         if (getKeyboard() == null) {
             return false;
         }
         if (mNonDistinctMultitouchHelper != null) {
-            if (me.getPointerCount() > 1 && mTimerHandler.isInKeyRepeat()) {
+            if (event.getPointerCount() > 1 && mTimerHandler.isInKeyRepeat()) {
                 // Key repeating timer will be canceled if 2 or more keys are in action.
                 mTimerHandler.cancelKeyRepeatTimers();
             }
             // Non distinct multitouch screen support
-            mNonDistinctMultitouchHelper.processMotionEvent(me, mKeyDetector);
+            mNonDistinctMultitouchHelper.processMotionEvent(event, mKeyDetector);
             return true;
         }
-        return processMotionEvent(me);
+        return processMotionEvent(event);
     }
 
-    public boolean processMotionEvent(final MotionEvent me) {
-        final int index = me.getActionIndex();
-        final int id = me.getPointerId(index);
+    public boolean processMotionEvent(final MotionEvent event) {
+        final int index = event.getActionIndex();
+        final int id = event.getPointerId(index);
         final PointerTracker tracker = PointerTracker.getPointerTracker(id);
         // When a more keys panel is showing, we should ignore other fingers' single touch events
         // other than the finger that is showing the more keys panel.
@@ -720,7 +720,7 @@
                 && PointerTracker.getActivePointerTrackerCount() == 1) {
             return true;
         }
-        tracker.processMotionEvent(me, mKeyDetector);
+        tracker.processMotionEvent(event, mKeyDetector);
         return true;
     }
 
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 7e4d665..7ec964d 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -74,7 +74,7 @@
     private static final int FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX = 0;
     private static final int FORMAT_WORD_PROPERTY_IS_POSSIBLY_OFFENSIVE_INDEX = 1;
     private static final int FORMAT_WORD_PROPERTY_HAS_NGRAMS_INDEX = 2;
-    private static final int FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX = 3;
+    private static final int FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX = 3; // DEPRECATED
     private static final int FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX = 4;
 
     // Format to get probability and historical info from native side via getWordPropertyNative().
@@ -410,11 +410,9 @@
                 outFlags[FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX],
                 outFlags[FORMAT_WORD_PROPERTY_IS_POSSIBLY_OFFENSIVE_INDEX],
                 outFlags[FORMAT_WORD_PROPERTY_HAS_NGRAMS_INDEX],
-                outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX],
                 outFlags[FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX], outProbabilityInfo,
                 outNgramPrevWordsArray, outNgramPrevWordIsBeginningOfSentenceArray,
-                outNgramTargets, outNgramProbabilityInfo, outShortcutTargets,
-                outShortcutProbabilities);
+                outNgramTargets, outNgramProbabilityInfo);
     }
 
     public static class GetNextWordPropertyResult {
@@ -442,19 +440,16 @@
     }
 
     // Add a unigram entry to binary dictionary with unigram attributes in native code.
-    public boolean addUnigramEntry(final String word, final int probability,
-            final String shortcutTarget, final int shortcutProbability,
-            final boolean isBeginningOfSentence, final boolean isNotAWord,
-            final boolean isPossiblyOffensive, final int timestamp) {
+    public boolean addUnigramEntry(
+            final String word, final int probability, final boolean isBeginningOfSentence,
+            final boolean isNotAWord, final boolean isPossiblyOffensive, final int timestamp) {
         if (word == null || (word.isEmpty() && !isBeginningOfSentence)) {
             return false;
         }
         final int[] codePoints = StringUtils.toCodePointArray(word);
-        final int[] shortcutTargetCodePoints = (shortcutTarget != null) ?
-                StringUtils.toCodePointArray(shortcutTarget) : null;
-        if (!addUnigramEntryNative(mNativeDict, codePoints, probability, shortcutTargetCodePoints,
-                shortcutProbability, isBeginningOfSentence, isNotAWord, isPossiblyOffensive,
-                timestamp)) {
+        if (!addUnigramEntryNative(mNativeDict, codePoints, probability,
+                null /* shortcutTargetCodePoints */, 0 /* shortcutProbability */,
+                isBeginningOfSentence, isNotAWord, isPossiblyOffensive, timestamp)) {
             return false;
         }
         mHasUpdated = true;
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 22fd907..66a21ec 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -139,8 +139,8 @@
                 Log.d(TAG, "loadAccountVocabulary: " + word);
             }
             runGCIfRequiredLocked(true /* mindsBlockByGC */);
-            addUnigramLocked(word, FREQUENCY_FOR_CONTACTS, null /* shortcut */,
-                    0 /* shortcutFreq */, false /* isNotAWord */, false /* isPossiblyOffensive */,
+            addUnigramLocked(word, FREQUENCY_FOR_CONTACTS,
+                    false /* isNotAWord */, false /* isPossiblyOffensive */,
                     BinaryDictionary.NOT_A_VALID_TIMESTAMP);
         }
     }
@@ -239,8 +239,7 @@
                         Log.d(TAG, "addName " + name + ", " + word + ", "  + ngramContext);
                     }
                     runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                    addUnigramLocked(word, FREQUENCY_FOR_CONTACTS,
-                            null /* shortcut */, 0 /* shortcutFreq */, false /* isNotAWord */,
+                    addUnigramLocked(word, FREQUENCY_FOR_CONTACTS, false /* isNotAWord */,
                             false /* isPossiblyOffensive */,
                             BinaryDictionary.NOT_A_VALID_TIMESTAMP);
                     if (!ngramContext.isValid() && mUseFirstLastBigrams) {
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 413c5b8..8c78002 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -297,21 +297,18 @@
      * Adds unigram information of a word to the dictionary. May overwrite an existing entry.
      */
     public void addUnigramEntry(final String word, final int frequency,
-            final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord,
-            final boolean isPossiblyOffensive, final int timestamp) {
+            final boolean isNotAWord, final boolean isPossiblyOffensive, final int timestamp) {
         updateDictionaryWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                addUnigramLocked(word, frequency, shortcutTarget, shortcutFreq,
-                        isNotAWord, isPossiblyOffensive, timestamp);
+                addUnigramLocked(word, frequency, isNotAWord, isPossiblyOffensive, timestamp);
             }
         });
     }
 
     protected void addUnigramLocked(final String word, final int frequency,
-            final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord,
-            final boolean isPossiblyOffensive, final int timestamp) {
-        if (!mBinaryDictionary.addUnigramEntry(word, frequency, shortcutTarget, shortcutFreq,
+            final boolean isNotAWord, final boolean isPossiblyOffensive, final int timestamp) {
+        if (!mBinaryDictionary.addUnigramEntry(word, frequency,
                 false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive, timestamp)) {
             Log.e(TAG, "Cannot add unigram entry. word: " + word);
         }
@@ -368,31 +365,6 @@
     }
 
     /**
-     * Dynamically remove the n-gram entry in the dictionary.
-     */
-    @UsedForTesting
-    public void removeNgramDynamically(@Nonnull final NgramContext ngramContext,
-            final String word) {
-        reloadDictionaryIfRequired();
-        asyncExecuteTaskWithWriteLock(new Runnable() {
-            @Override
-            public void run() {
-                final BinaryDictionary binaryDictionary = getBinaryDictionary();
-                if (binaryDictionary == null) {
-                    return;
-                }
-                runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                if (!binaryDictionary.removeNgramEntry(ngramContext, word)) {
-                    if (DEBUG) {
-                        Log.i(TAG, "Cannot remove n-gram entry.");
-                        Log.i(TAG, "  NgramContext: " + ngramContext + ", word: " + word);
-                    }
-                }
-            }
-        });
-    }
-
-    /**
      * Update dictionary for the word with the ngramContext.
      */
     public void updateEntriesForWord(@Nonnull final NgramContext ngramContext,
@@ -408,20 +380,29 @@
                         isValidWord, count, timestamp)) {
                     if (DEBUG) {
                         Log.e(TAG, "Cannot update counter. word: " + word
-                                + " context: "+ ngramContext.toString());
+                                + " context: " + ngramContext.toString());
                     }
                 }
             }
         });
     }
 
+    /**
+     * Used by Sketch.
+     * {@see https://cs.corp.google.com/#android/vendor/unbundled_google/packages/LatinIMEGoogle/tools/sketch/ime-simulator/src/com/android/inputmethod/sketch/imesimulator/ImeSimulator.java&q=updateEntriesForInputEventsCallback&l=286}
+     */
+    @UsedForTesting
     public interface UpdateEntriesForInputEventsCallback {
         public void onFinished();
     }
 
     /**
      * Dynamically update entries according to input events.
+     *
+     * Used by Sketch.
+     * {@see https://cs.corp.google.com/#android/vendor/unbundled_google/packages/LatinIMEGoogle/tools/sketch/ime-simulator/src/com/android/inputmethod/sketch/imesimulator/ImeSimulator.java&q=updateEntriesForInputEventsCallback&l=286}
      */
+    @UsedForTesting
     public void updateEntriesForInputEvents(
             @Nonnull final ArrayList<WordInputEventForPersonalization> inputEvents,
             final UpdateEntriesForInputEventsCallback callback) {
@@ -533,11 +514,6 @@
     }
 
 
-    protected boolean isValidNgramLocked(final NgramContext ngramContext, final String word) {
-        if (mBinaryDictionary == null) return false;
-        return mBinaryDictionary.isValidNgram(ngramContext, word);
-    }
-
     /**
      * Loads the current binary dictionary from internal storage. Assumes the dictionary file
      * exists.
@@ -551,6 +527,7 @@
                 Thread.sleep(15000);
                 Log.w(TAG, "End stress in loading");
             } catch (InterruptedException e) {
+                Log.w("Interrupted while loading: " + mDictName, e);
             }
         }
         final BinaryDictionary oldBinaryDictionary = mBinaryDictionary;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index c118e4a..a1ab5c0 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -87,7 +87,6 @@
 import com.android.inputmethod.latin.utils.IntentUtils;
 import com.android.inputmethod.latin.utils.JniUtils;
 import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
-import com.android.inputmethod.latin.utils.NetworkConnectivityUtils;
 import com.android.inputmethod.latin.utils.StatsUtils;
 import com.android.inputmethod.latin.utils.StatsUtilsManager;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
@@ -565,8 +564,6 @@
         loadSettings();
         resetDictionaryFacilitatorIfNecessary();
 
-        NetworkConnectivityUtils.onCreate(this /* context */, mKeyboardSwitcher /* listener */);
-
         // Register to receive ringer mode change.
         final IntentFilter filter = new IntentFilter();
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
@@ -703,7 +700,6 @@
     public void onDestroy() {
         mDictionaryFacilitator.closeDictionaries();
         mSettings.onDestroy();
-        NetworkConnectivityUtils.onDestroy(this /* context */);
         unregisterReceiver(mRingerModeChangeReceiver);
         unregisterReceiver(mDictionaryPackInstallReceiver);
         unregisterReceiver(mDictionaryDumpBroadcastReceiver);
@@ -717,7 +713,6 @@
         unregisterReceiver(mDictionaryPackInstallReceiver);
         unregisterReceiver(mDictionaryDumpBroadcastReceiver);
         unregisterReceiver(mRingerModeChangeReceiver);
-        NetworkConnectivityUtils.onDestroy(this /* context */);
         mInputLogic.recycle();
     }
 
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 0210d7e..f020c25 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -899,7 +899,7 @@
      * On platforms on which this method is not present, this is a no-op.
      */
     public void maybeMoveTheCursorAroundAndRestoreToWorkaroundABug() {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+        if (!Constants.JELLY_BEAN_OR_HIGHER) {
             if (mExpectedSelStart > 0) {
                 mIC.setSelection(mExpectedSelStart - 1, mExpectedSelStart - 1);
             } else {
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index 64a7cf3..c8e0b93 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -17,7 +17,6 @@
 package com.android.inputmethod.latin;
 
 import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
-import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY;
 
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -36,7 +35,6 @@
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
 import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
-import com.android.inputmethod.latin.utils.NetworkConnectivityUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.util.Collections;
@@ -288,24 +286,20 @@
     }
 
     public boolean checkIfSubtypeBelongsToThisImeAndEnabled(final InputMethodSubtype subtype) {
-        return checkIfSubtypeBelongsToImeAndEnabled(getInputMethodInfoOfThisIme(), subtype);
+        return checkIfSubtypeBelongsToList(subtype,
+                getEnabledInputMethodSubtypeList(
+                        getInputMethodInfoOfThisIme(),
+                        true /* allowsImplicitlySelectedSubtypes */));
     }
 
     public boolean checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(
             final InputMethodSubtype subtype) {
         final boolean subtypeEnabled = checkIfSubtypeBelongsToThisImeAndEnabled(subtype);
-        final boolean subtypeExplicitlyEnabled = checkIfSubtypeBelongsToList(
-                subtype, getMyEnabledInputMethodSubtypeList(
-                        false /* allowsImplicitlySelectedSubtypes */));
+        final boolean subtypeExplicitlyEnabled = checkIfSubtypeBelongsToList(subtype,
+                getMyEnabledInputMethodSubtypeList(false /* allowsImplicitlySelectedSubtypes */));
         return subtypeEnabled && !subtypeExplicitlyEnabled;
     }
 
-    public boolean checkIfSubtypeBelongsToImeAndEnabled(final InputMethodInfo imi,
-            final InputMethodSubtype subtype) {
-        return checkIfSubtypeBelongsToList(subtype, getEnabledInputMethodSubtypeList(imi,
-                true /* allowsImplicitlySelectedSubtypes */));
-    }
-
     private static boolean checkIfSubtypeBelongsToList(final InputMethodSubtype subtype,
             final List<InputMethodSubtype> subtypes) {
         return getSubtypeIndexInList(subtype, subtypes) != INDEX_NOT_FOUND;
@@ -564,16 +558,6 @@
         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
-    public boolean isShortcutImeEnabled() {
-        if (mShortcutInputMethodInfo == null) {
-            return false;
-        }
-        if (mShortcutSubtype == null) {
-            return true;
-        }
-        return checkIfSubtypeBelongsToImeAndEnabled(mShortcutInputMethodInfo, mShortcutSubtype);
-    }
-
     public boolean isShortcutImeReady() {
         if (mShortcutInputMethodInfo == null) {
             return false;
@@ -581,9 +565,6 @@
         if (mShortcutSubtype == null) {
             return true;
         }
-        if (mShortcutSubtype.containsExtraValueKey(REQ_NETWORK_CONNECTIVITY)) {
-            return NetworkConnectivityUtils.isNetworkConnected();
-        }
         return true;
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 1ed2103..fe24ccf 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -22,7 +22,6 @@
 import android.database.Cursor;
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
-import android.os.Build;
 import android.provider.UserDictionary.Words;
 import android.text.TextUtils;
 import android.util.Log;
@@ -47,19 +46,8 @@
     private static final String USER_DICTIONARY_ALL_LANGUAGES = "";
     private static final int HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY = 250;
     private static final int LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY = 160;
-    // Shortcut frequency is 0~15, with 15 = whitelist. We don't want user dictionary entries
-    // to auto-correct, so we set this to the highest frequency that won't, i.e. 14.
-    private static final int USER_DICT_SHORTCUT_FREQUENCY = 14;
 
-    private static final String[] PROJECTION_QUERY_WITH_SHORTCUT = new String[] {
-            Words.WORD,
-            Words.SHORTCUT,
-            Words.FREQUENCY,
-    };
-    private static final String[] PROJECTION_QUERY_WITHOUT_SHORTCUT = new String[] {
-            Words.WORD,
-            Words.FREQUENCY,
-    };
+    private static final String[] PROJECTION_QUERY = new String[] {Words.WORD, Words.FREQUENCY};
 
     private static final String NAME = "userunigram";
 
@@ -171,20 +159,7 @@
             requestArguments = localeElements;
         }
         final String requestString = request.toString();
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            try {
-                addWordsFromProjectionLocked(PROJECTION_QUERY_WITH_SHORTCUT, requestString,
-                        requestArguments);
-            } catch (IllegalArgumentException e) {
-                // This may happen on some non-compliant devices where the declared API is JB+ but
-                // the SHORTCUT column is not present for some reason.
-                addWordsFromProjectionLocked(PROJECTION_QUERY_WITHOUT_SHORTCUT, requestString,
-                        requestArguments);
-            }
-        } else {
-            addWordsFromProjectionLocked(PROJECTION_QUERY_WITHOUT_SHORTCUT, requestString,
-                    requestArguments);
-        }
+        addWordsFromProjectionLocked(PROJECTION_QUERY, requestString, requestArguments);
     }
 
     private void addWordsFromProjectionLocked(final String[] query, String request,
@@ -219,31 +194,20 @@
     }
 
     private void addWordsLocked(final Cursor cursor) {
-        final boolean hasShortcutColumn = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
         if (cursor == null) return;
         if (cursor.moveToFirst()) {
             final int indexWord = cursor.getColumnIndex(Words.WORD);
-            final int indexShortcut = hasShortcutColumn ? cursor.getColumnIndex(Words.SHORTCUT) : 0;
             final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
             while (!cursor.isAfterLast()) {
                 final String word = cursor.getString(indexWord);
-                final String shortcut = hasShortcutColumn ? cursor.getString(indexShortcut) : null;
                 final int frequency = cursor.getInt(indexFrequency);
                 final int adjustedFrequency = scaleFrequencyFromDefaultToLatinIme(frequency);
                 // Safeguard against adding really long words.
                 if (word.length() <= MAX_WORD_LENGTH) {
                     runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                    addUnigramLocked(word, adjustedFrequency, null /* shortcutTarget */,
-                            0 /* shortcutFreq */, false /* isNotAWord */,
+                    addUnigramLocked(word, adjustedFrequency, false /* isNotAWord */,
                             false /* isPossiblyOffensive */,
                             BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-                    if (null != shortcut && shortcut.length() <= MAX_WORD_LENGTH) {
-                        runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                        addUnigramLocked(shortcut, adjustedFrequency, word,
-                                USER_DICT_SHORTCUT_FREQUENCY, true /* isNotAWord */,
-                                false /* isPossiblyOffensive */,
-                                BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-                    }
                 }
                 cursor.moveToNext();
             }
diff --git a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
index 388d578..264e757 100644
--- a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
+++ b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
@@ -37,13 +37,11 @@
 public final class WordProperty implements Comparable<WordProperty> {
     public final String mWord;
     public final ProbabilityInfo mProbabilityInfo;
-    public final ArrayList<WeightedString> mShortcutTargets;
     public final ArrayList<NgramProperty> mNgrams;
     // TODO: Support mIsBeginningOfSentence.
     public final boolean mIsBeginningOfSentence;
     public final boolean mIsNotAWord;
     public final boolean mIsPossiblyOffensive;
-    public final boolean mHasShortcuts;
     public final boolean mHasNgrams;
 
     private int mHashCode = 0;
@@ -51,12 +49,10 @@
     // TODO: Support n-gram.
     @UsedForTesting
     public WordProperty(final String word, final ProbabilityInfo probabilityInfo,
-            final ArrayList<WeightedString> shortcutTargets,
             @Nullable final ArrayList<WeightedString> bigrams,
             final boolean isNotAWord, final boolean isPossiblyOffensive) {
         mWord = word;
         mProbabilityInfo = probabilityInfo;
-        mShortcutTargets = shortcutTargets;
         if (null == bigrams) {
             mNgrams = null;
         } else {
@@ -70,7 +66,6 @@
         mIsNotAWord = isNotAWord;
         mIsPossiblyOffensive = isPossiblyOffensive;
         mHasNgrams = bigrams != null && !bigrams.isEmpty();
-        mHasShortcuts = shortcutTargets != null && !shortcutTargets.isEmpty();
     }
 
     private static ProbabilityInfo createProbabilityInfoFromArray(final int[] probabilityInfo) {
@@ -84,21 +79,17 @@
     // Construct word property using information from native code.
     // This represents invalid word when the probability is BinaryDictionary.NOT_A_PROBABILITY.
     public WordProperty(final int[] codePoints, final boolean isNotAWord,
-            final boolean isPossiblyOffensive, final boolean hasBigram, final boolean hasShortcuts,
+            final boolean isPossiblyOffensive, final boolean hasBigram,
             final boolean isBeginningOfSentence, final int[] probabilityInfo,
             final ArrayList<int[][]> ngramPrevWordsArray,
             final ArrayList<boolean[]> ngramPrevWordIsBeginningOfSentenceArray,
-            final ArrayList<int[]> ngramTargets, final ArrayList<int[]> ngramProbabilityInfo,
-            final ArrayList<int[]> shortcutTargets,
-            final ArrayList<Integer> shortcutProbabilities) {
+            final ArrayList<int[]> ngramTargets, final ArrayList<int[]> ngramProbabilityInfo) {
         mWord = StringUtils.getStringFromNullTerminatedCodePointArray(codePoints);
         mProbabilityInfo = createProbabilityInfoFromArray(probabilityInfo);
-        mShortcutTargets = new ArrayList<>();
         final ArrayList<NgramProperty> ngrams = new ArrayList<>();
         mIsBeginningOfSentence = isBeginningOfSentence;
         mIsNotAWord = isNotAWord;
         mIsPossiblyOffensive = isPossiblyOffensive;
-        mHasShortcuts = hasShortcuts;
         mHasNgrams = hasBigram;
 
         final int relatedNgramCount = ngramTargets.size();
@@ -121,14 +112,6 @@
             ngrams.add(new NgramProperty(ngramTarget, ngramContext));
         }
         mNgrams = ngrams.isEmpty() ? null : ngrams;
-
-        final int shortcutTargetCount = shortcutTargets.size();
-        for (int i = 0; i < shortcutTargetCount; i++) {
-            final String shortcutTargetString =
-                    StringUtils.getStringFromNullTerminatedCodePointArray(shortcutTargets.get(i));
-            mShortcutTargets.add(
-                    new WeightedString(shortcutTargetString, shortcutProbabilities.get(i)));
-        }
     }
 
     // TODO: Remove
@@ -154,7 +137,6 @@
         return Arrays.hashCode(new Object[] {
                 word.mWord,
                 word.mProbabilityInfo,
-                word.mShortcutTargets,
                 word.mNgrams,
                 word.mIsNotAWord,
                 word.mIsPossiblyOffensive
@@ -185,10 +167,10 @@
         if (o == this) return true;
         if (!(o instanceof WordProperty)) return false;
         WordProperty w = (WordProperty)o;
-        return mProbabilityInfo.equals(w.mProbabilityInfo) && mWord.equals(w.mWord)
-                && mShortcutTargets.equals(w.mShortcutTargets) && equals(mNgrams, w.mNgrams)
+        return mProbabilityInfo.equals(w.mProbabilityInfo)
+                && mWord.equals(w.mWord) && equals(mNgrams, w.mNgrams)
                 && mIsNotAWord == w.mIsNotAWord && mIsPossiblyOffensive == w.mIsPossiblyOffensive
-                && mHasNgrams == w.mHasNgrams && mHasShortcuts && w.mHasNgrams;
+                && mHasNgrams == w.mHasNgrams;
     }
 
     // TDOO: Have a utility method like java.util.Objects.equals.
diff --git a/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
index 975396d..c5e80f2 100644
--- a/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
@@ -25,6 +25,7 @@
 import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.common.Constants;
 
 /**
  * "Preferences" settings sub screen.
@@ -72,11 +73,9 @@
         final Preference voiceInputKeyOption = findPreference(Settings.PREF_VOICE_INPUT_KEY);
         if (voiceInputKeyOption != null) {
             RichInputMethodManager.getInstance().refreshSubtypeCaches();
-            final boolean isShortcutImeEnabled = RichInputMethodManager.getInstance()
-                    .isShortcutImeEnabled();
-            voiceInputKeyOption.setEnabled(isShortcutImeEnabled);
-            voiceInputKeyOption.setSummary(
-                    isShortcutImeEnabled ? null : getText(R.string.voice_input_disabled_summary));
+            voiceInputKeyOption.setEnabled(Constants.JELLY_BEAN_OR_HIGHER);
+            voiceInputKeyOption.setSummary(Constants.JELLY_BEAN_OR_HIGHER
+                    ? null : getText(R.string.voice_input_disabled_summary));
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 9a1bb77..e523246 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -28,6 +28,7 @@
 import com.android.inputmethod.latin.InputAttributes;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.AsyncResultHolder;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask;
@@ -136,7 +137,7 @@
                 DebugSettings.PREF_SLIDING_KEY_INPUT_PREVIEW, true);
         mShowsVoiceInputKey = needsToShowVoiceInputKey(prefs, res)
                 && mInputAttributes.mShouldShowVoiceInputKey
-                && RichInputMethodManager.getInstance().isShortcutImeEnabled();
+                && Constants.JELLY_BEAN_OR_HIGHER;
         final String autoCorrectionThresholdRawValue = prefs.getString(
                 Settings.PREF_AUTO_CORRECTION_THRESHOLD,
                 res.getString(R.string.auto_correction_threshold_mode_index_modest));
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
index 69029c5..cb615f3 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
@@ -26,7 +26,6 @@
 import android.view.View;
 import android.widget.EditText;
 
-import com.android.inputmethod.compat.UserDictionaryCompatUtils;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.common.LocaleUtils;
 
@@ -47,10 +46,7 @@
 public class UserDictionaryAddWordContents {
     public static final String EXTRA_MODE = "mode";
     public static final String EXTRA_WORD = "word";
-    public static final String EXTRA_SHORTCUT = "shortcut";
     public static final String EXTRA_LOCALE = "locale";
-    public static final String EXTRA_ORIGINAL_WORD = "originalWord";
-    public static final String EXTRA_ORIGINAL_SHORTCUT = "originalShortcut";
 
     public static final int MODE_EDIT = 0;
     public static final int MODE_INSERT = 1;
@@ -63,20 +59,12 @@
 
     private final int mMode; // Either MODE_EDIT or MODE_INSERT
     private final EditText mWordEditText;
-    private final EditText mShortcutEditText;
     private String mLocale;
     private final String mOldWord;
-    private final String mOldShortcut;
     private String mSavedWord;
-    private String mSavedShortcut;
 
     /* package */ UserDictionaryAddWordContents(final View view, final Bundle args) {
         mWordEditText = (EditText)view.findViewById(R.id.user_dictionary_add_word_text);
-        mShortcutEditText = (EditText)view.findViewById(R.id.user_dictionary_add_shortcut);
-        if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
-            mShortcutEditText.setVisibility(View.GONE);
-            view.findViewById(R.id.user_dictionary_add_shortcut_label).setVisibility(View.GONE);
-        }
         final String word = args.getString(EXTRA_WORD);
         if (null != word) {
             mWordEditText.setText(word);
@@ -84,17 +72,6 @@
             // it's too long to be edited.
             mWordEditText.setSelection(mWordEditText.getText().length());
         }
-        final String shortcut;
-        if (UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
-            shortcut = args.getString(EXTRA_SHORTCUT);
-            if (null != shortcut && null != mShortcutEditText) {
-                mShortcutEditText.setText(shortcut);
-            }
-            mOldShortcut = args.getString(EXTRA_SHORTCUT);
-        } else {
-            shortcut = null;
-            mOldShortcut = null;
-        }
         mMode = args.getInt(EXTRA_MODE); // default return value for #getInt() is 0 = MODE_EDIT
         mOldWord = args.getString(EXTRA_WORD);
         updateLocale(args.getString(EXTRA_LOCALE));
@@ -103,10 +80,8 @@
     /* package */ UserDictionaryAddWordContents(final View view,
             final UserDictionaryAddWordContents oldInstanceToBeEdited) {
         mWordEditText = (EditText)view.findViewById(R.id.user_dictionary_add_word_text);
-        mShortcutEditText = (EditText)view.findViewById(R.id.user_dictionary_add_shortcut);
         mMode = MODE_EDIT;
         mOldWord = oldInstanceToBeEdited.mSavedWord;
-        mOldShortcut = oldInstanceToBeEdited.mSavedShortcut;
         updateLocale(mLocale);
     }
 
@@ -118,13 +93,6 @@
 
     /* package */ void saveStateIntoBundle(final Bundle outState) {
         outState.putString(EXTRA_WORD, mWordEditText.getText().toString());
-        outState.putString(EXTRA_ORIGINAL_WORD, mOldWord);
-        if (null != mShortcutEditText) {
-            outState.putString(EXTRA_SHORTCUT, mShortcutEditText.getText().toString());
-        }
-        if (null != mOldShortcut) {
-            outState.putString(EXTRA_ORIGINAL_SHORTCUT, mOldShortcut);
-        }
         outState.putString(EXTRA_LOCALE, mLocale);
     }
 
@@ -132,7 +100,7 @@
         if (MODE_EDIT == mMode && !TextUtils.isEmpty(mOldWord)) {
             // Mode edit: remove the old entry.
             final ContentResolver resolver = context.getContentResolver();
-            UserDictionarySettings.deleteWord(mOldWord, mOldShortcut, resolver);
+            UserDictionarySettings.deleteWord(mOldWord, resolver);
         }
         // If we are in add mode, nothing was added, so we don't need to do anything.
     }
@@ -143,50 +111,31 @@
         final ContentResolver resolver = context.getContentResolver();
         if (MODE_EDIT == mMode && !TextUtils.isEmpty(mOldWord)) {
             // Mode edit: remove the old entry.
-            UserDictionarySettings.deleteWord(mOldWord, mOldShortcut, resolver);
+            UserDictionarySettings.deleteWord(mOldWord, resolver);
         }
         final String newWord = mWordEditText.getText().toString();
-        final String newShortcut;
-        if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
-            newShortcut = null;
-        } else if (null == mShortcutEditText) {
-            newShortcut = null;
-        } else {
-            final String tmpShortcut = mShortcutEditText.getText().toString();
-            if (TextUtils.isEmpty(tmpShortcut)) {
-                newShortcut = null;
-            } else {
-                newShortcut = tmpShortcut;
-            }
-        }
         if (TextUtils.isEmpty(newWord)) {
             // If the word is somehow empty, don't insert it.
             return CODE_CANCEL;
         }
         mSavedWord = newWord;
-        mSavedShortcut = newShortcut;
-        // If there is no shortcut, and the word already exists in the database, then we
-        // should not insert, because either A. the word exists with no shortcut, in which
-        // case the exact same thing we want to insert is already there, or B. the word
-        // exists with at least one shortcut, in which case it has priority on our word.
-        if (TextUtils.isEmpty(newShortcut) && hasWord(newWord, context)) {
+        // If the word already exists in the database, then we should not insert.
+        if (hasWord(newWord, context)) {
             return CODE_ALREADY_PRESENT;
         }
 
-        // Disallow duplicates. If the same word with no shortcut is defined, remove it; if
-        // the same word with the same shortcut is defined, remove it; but we don't mind if
-        // there is the same word with a different, non-empty shortcut.
-        UserDictionarySettings.deleteWord(newWord, null, resolver);
-        if (!TextUtils.isEmpty(newShortcut)) {
-            // If newShortcut is empty we just deleted this, no need to do it again
-            UserDictionarySettings.deleteWord(newWord, newShortcut, resolver);
-        }
+        // Disallow duplicates. If the same word is defined, remove it.
+        UserDictionarySettings.deleteWord(newWord, resolver);
 
         // In this class we use the empty string to represent 'all locales' and mLocale cannot
         // be null. However the addWord method takes null to mean 'all locales'.
-        UserDictionaryCompatUtils.addWord(context, newWord.toString(),
-                FREQUENCY_FOR_USER_DICTIONARY_ADDS, newShortcut, TextUtils.isEmpty(mLocale) ?
-                        null : LocaleUtils.constructLocaleFromString(mLocale));
+        final Locale locale = TextUtils.isEmpty(mLocale) ?
+                null : LocaleUtils.constructLocaleFromString(mLocale);
+        final Locale currentLocale = context.getResources().getConfiguration().locale;
+        final boolean useCurrentLocale = currentLocale.equals(locale);
+        UserDictionary.Words.addWord(context, newWord.toString(),
+                FREQUENCY_FOR_USER_DICTIONARY_ADDS, null /* shortcut */,
+                useCurrentLocale ? Locale.getDefault() : null);
 
         return CODE_WORD_ADDED;
     }
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
index 6254b54..c43463c 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
@@ -31,6 +31,7 @@
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.common.LocaleUtils;
 
 import java.util.List;
@@ -74,7 +75,7 @@
         } finally {
             cursor.close();
         }
-        if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
+        if (!Constants.JELLY_BEAN_OR_HIGHER) {
             // For ICS, we need to show "For all languages" in case that the keyboard locale
             // is different from the system locale
             localeSet.add("");
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
index fabd49f..3ccd1b3 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
@@ -48,42 +48,18 @@
 
 public class UserDictionarySettings extends ListFragment {
 
-    public static final boolean IS_SHORTCUT_API_SUPPORTED =
-            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
-
-    private static final String[] QUERY_PROJECTION_SHORTCUT_UNSUPPORTED =
-            { UserDictionary.Words._ID, UserDictionary.Words.WORD};
-    private static final String[] QUERY_PROJECTION_SHORTCUT_SUPPORTED =
-            { UserDictionary.Words._ID, UserDictionary.Words.WORD, UserDictionary.Words.SHORTCUT};
-    private static final String[] QUERY_PROJECTION =
-            IS_SHORTCUT_API_SUPPORTED ?
-                    QUERY_PROJECTION_SHORTCUT_SUPPORTED : QUERY_PROJECTION_SHORTCUT_UNSUPPORTED;
-
-    // The index of the shortcut in the above array.
-    private static final int INDEX_SHORTCUT = 2;
-
-    private static final String[] ADAPTER_FROM_SHORTCUT_UNSUPPORTED = {
-        UserDictionary.Words.WORD,
+    private static final String[] QUERY_PROJECTION = {
+            UserDictionary.Words._ID, UserDictionary.Words.WORD
     };
 
-    private static final String[] ADAPTER_FROM_SHORTCUT_SUPPORTED = {
-        UserDictionary.Words.WORD, UserDictionary.Words.SHORTCUT
+    private static final String[] ADAPTER_FROM = {
+            UserDictionary.Words.WORD, UserDictionary.Words.SHORTCUT
     };
 
-    private static final String[] ADAPTER_FROM = IS_SHORTCUT_API_SUPPORTED ?
-            ADAPTER_FROM_SHORTCUT_SUPPORTED : ADAPTER_FROM_SHORTCUT_UNSUPPORTED;
-
-    private static final int[] ADAPTER_TO_SHORTCUT_UNSUPPORTED = {
+    private static final int[] ADAPTER_TO = {
         android.R.id.text1,
     };
 
-    private static final int[] ADAPTER_TO_SHORTCUT_SUPPORTED = {
-        android.R.id.text1, android.R.id.text2
-    };
-
-    private static final int[] ADAPTER_TO = IS_SHORTCUT_API_SUPPORTED ?
-            ADAPTER_TO_SHORTCUT_SUPPORTED : ADAPTER_TO_SHORTCUT_UNSUPPORTED;
-
     // Either the locale is empty (means the word is applicable to all locales)
     // or the word equals our current locale
     private static final String QUERY_SELECTION =
@@ -91,13 +67,7 @@
     private static final String QUERY_SELECTION_ALL_LOCALES =
             UserDictionary.Words.LOCALE + " is null";
 
-    private static final String DELETE_SELECTION_WITH_SHORTCUT = UserDictionary.Words.WORD
-            + "=? AND " + UserDictionary.Words.SHORTCUT + "=?";
-    private static final String DELETE_SELECTION_WITHOUT_SHORTCUT = UserDictionary.Words.WORD
-            + "=? AND " + UserDictionary.Words.SHORTCUT + " is null OR "
-            + UserDictionary.Words.SHORTCUT + "=''";
-    private static final String DELETE_SELECTION_SHORTCUT_UNSUPPORTED =
-            UserDictionary.Words.WORD + "=?";
+    private static final String DELETE_SELECTION = UserDictionary.Words.WORD + "=?";
 
     private static final int OPTIONS_MENU_ADD = Menu.FIRST;
 
@@ -192,20 +162,18 @@
     @Override
     public void onListItemClick(ListView l, View v, int position, long id) {
         final String word = getWord(position);
-        final String shortcut = getShortcut(position);
         if (word != null) {
-            showAddOrEditDialog(word, shortcut);
+            showAddOrEditDialog(word);
         }
     }
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
             final Locale systemLocale = getResources().getConfiguration().locale;
             if (!TextUtils.isEmpty(mLocale) && !mLocale.equals(systemLocale.toString())) {
                 // Hide the add button for ICS because it doesn't support specifying a locale
-                // for an entry. This new "locale"-aware API has been added in conjunction
-                // with the shortcut API.
+                // for an entry.
                 return;
             }
         }
@@ -219,7 +187,7 @@
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         if (item.getItemId() == OPTIONS_MENU_ADD) {
-            showAddOrEditDialog(null, null);
+            showAddOrEditDialog(null);
             return true;
         }
         return false;
@@ -228,18 +196,15 @@
     /**
      * Add or edit a word. If editingWord is null, it's an add; otherwise, it's an edit.
      * @param editingWord the word to edit, or null if it's an add.
-     * @param editingShortcut the shortcut for this entry, or null if none.
      */
-    private void showAddOrEditDialog(final String editingWord, final String editingShortcut) {
+    private void showAddOrEditDialog(final String editingWord) {
         final Bundle args = new Bundle();
         args.putInt(UserDictionaryAddWordContents.EXTRA_MODE, null == editingWord
                 ? UserDictionaryAddWordContents.MODE_INSERT
                 : UserDictionaryAddWordContents.MODE_EDIT);
         args.putString(UserDictionaryAddWordContents.EXTRA_WORD, editingWord);
-        args.putString(UserDictionaryAddWordContents.EXTRA_SHORTCUT, editingShortcut);
         args.putString(UserDictionaryAddWordContents.EXTRA_LOCALE, mLocale);
-        android.preference.PreferenceActivity pa =
-                (android.preference.PreferenceActivity)getActivity();
+        getActivity();
     }
 
     private String getWord(final int position) {
@@ -252,31 +217,8 @@
                 mCursor.getColumnIndexOrThrow(UserDictionary.Words.WORD));
     }
 
-    private String getShortcut(final int position) {
-        if (!IS_SHORTCUT_API_SUPPORTED) return null;
-        if (null == mCursor) return null;
-        mCursor.moveToPosition(position);
-        // Handle a possible race-condition
-        if (mCursor.isAfterLast()) return null;
-
-        return mCursor.getString(
-                mCursor.getColumnIndexOrThrow(UserDictionary.Words.SHORTCUT));
-    }
-
-    public static void deleteWord(final String word, final String shortcut,
-            final ContentResolver resolver) {
-        if (!IS_SHORTCUT_API_SUPPORTED) {
-            resolver.delete(UserDictionary.Words.CONTENT_URI, DELETE_SELECTION_SHORTCUT_UNSUPPORTED,
-                    new String[] { word });
-        } else if (TextUtils.isEmpty(shortcut)) {
-            resolver.delete(
-                    UserDictionary.Words.CONTENT_URI, DELETE_SELECTION_WITHOUT_SHORTCUT,
-                    new String[] { word });
-        } else {
-            resolver.delete(
-                    UserDictionary.Words.CONTENT_URI, DELETE_SELECTION_WITH_SHORTCUT,
-                    new String[] { word, shortcut });
-        }
+    public static void deleteWord(final String word, final ContentResolver resolver) {
+        resolver.delete(UserDictionary.Words.CONTENT_URI, DELETE_SELECTION, new String[] { word });
     }
 
     private static class MyAdapter extends SimpleCursorAdapter implements SectionIndexer {
@@ -286,22 +228,7 @@
 
             @Override
             public boolean setViewValue(final View v, final Cursor c, final int columnIndex) {
-                if (!IS_SHORTCUT_API_SUPPORTED) {
-                    // just let SimpleCursorAdapter set the view values
-                    return false;
-                }
-                if (columnIndex == INDEX_SHORTCUT) {
-                    final String shortcut = c.getString(INDEX_SHORTCUT);
-                    if (TextUtils.isEmpty(shortcut)) {
-                        v.setVisibility(View.GONE);
-                    } else {
-                        ((TextView)v).setText(shortcut);
-                        v.setVisibility(View.VISIBLE);
-                    }
-                    v.invalidate();
-                    return true;
-                }
-
+                // just let SimpleCursorAdapter set the view values
                 return false;
             }
         };
diff --git a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
index 476c134..5c0c432 100644
--- a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
@@ -19,7 +19,6 @@
 import com.android.inputmethod.latin.makedict.DictionaryHeader;
 import com.android.inputmethod.latin.makedict.NgramProperty;
 import com.android.inputmethod.latin.makedict.ProbabilityInfo;
-import com.android.inputmethod.latin.makedict.WeightedString;
 import com.android.inputmethod.latin.makedict.WordProperty;
 
 import java.util.HashMap;
@@ -29,7 +28,6 @@
     public static final String BIGRAM_TAG = "bigram";
     public static final String NGRAM_TAG = "ngram";
     public static final String NGRAM_PREV_WORD_TAG = "prev_word";
-    public static final String SHORTCUT_TAG = "shortcut";
     public static final String PROBABILITY_TAG = "f";
     public static final String HISTORICAL_INFO_TAG = "historicalInfo";
     public static final String HISTORICAL_INFO_SEPARATOR = ":";
@@ -71,14 +69,6 @@
             builder.append("," + POSSIBLY_OFFENSIVE_TAG + "=" + TRUE_VALUE);
         }
         builder.append("\n");
-        if (wordProperty.mHasShortcuts) {
-            for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-                builder.append("  " + SHORTCUT_TAG + "=" + shortcutTarget.mWord);
-                builder.append(",");
-                builder.append(formatProbabilityInfo(shortcutTarget.mProbabilityInfo));
-                builder.append("\n");
-            }
-        }
         if (wordProperty.mHasNgrams) {
             for (final NgramProperty ngramProperty : wordProperty.mNgrams) {
                 builder.append(" " + NGRAM_TAG + "=" + ngramProperty.mTargetWord.mWord);
diff --git a/java/src/com/android/inputmethod/latin/utils/NetworkConnectivityUtils.java b/java/src/com/android/inputmethod/latin/utils/NetworkConnectivityUtils.java
deleted file mode 100644
index 101c550..0000000
--- a/java/src/com/android/inputmethod/latin/utils/NetworkConnectivityUtils.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.latin.utils;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-
-import javax.annotation.Nonnull;
-
-/**
- * This class keeps track of the network connectivity state by receiving the system intent
- * {@link ConnectivityManager#CONNECTIVITY_ACTION}, and invokes an registered call back to notify
- * changes of the network connectivity state.
- */
-public final class NetworkConnectivityUtils {
-    private static NetworkConnectivityReceiver sNetworkConnectivityReceiver;
-
-    public interface NetworkStateChangeListener {
-        /**
-         * Called when the network connectivity state has changed.
-         */
-        public void onNetworkStateChanged();
-    }
-
-    private static class NetworkConnectivityReceiver extends BroadcastReceiver {
-        @Nonnull
-        private final NetworkStateChangeListener mListener;
-        private boolean mIsNetworkConnected;
-
-        public NetworkConnectivityReceiver(@Nonnull final NetworkStateChangeListener listener,
-                final boolean isNetworkConnected) {
-            mListener = listener;
-            mIsNetworkConnected = isNetworkConnected;
-        }
-
-        public synchronized boolean isNetworkConnected() {
-            return mIsNetworkConnected;
-        }
-
-        @Override
-        public void onReceive(final Context context, final Intent intent) {
-            final String action = intent.getAction();
-            if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
-                final boolean noConnection = intent.getBooleanExtra(
-                        ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
-                synchronized (this) {
-                    mIsNetworkConnected = !noConnection;
-                }
-                mListener.onNetworkStateChanged();
-            }
-        }
-    }
-
-    private NetworkConnectivityUtils() {
-        // This utility class is not publicly instantiable.
-    }
-
-    public static void onCreate(@Nonnull final Context context,
-            @Nonnull final NetworkStateChangeListener listener) {
-        final ConnectivityManager connectivityManager =
-                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
-        final NetworkInfo info = connectivityManager.getActiveNetworkInfo();
-        final boolean isNetworkConnected = (info != null && info.isConnected());
-
-        // Register {@link BroadcastReceiver} for the network connectivity state change.
-        final NetworkConnectivityReceiver receiver = new NetworkConnectivityReceiver(
-                listener, isNetworkConnected);
-        final IntentFilter filter = new IntentFilter();
-        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
-        context.registerReceiver(receiver, filter);
-
-        sNetworkConnectivityReceiver = receiver;
-    }
-
-    public static void onDestroy(final Context context) {
-        context.unregisterReceiver(sNetworkConnectivityReceiver);
-    }
-
-    public static boolean isNetworkConnected() {
-        final NetworkConnectivityReceiver receiver = sNetworkConnectivityReceiver;
-        return receiver != null && receiver.isNetworkConnected();
-    }
-}
diff --git a/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java b/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java
index 67e7646..d75e61a 100644
--- a/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java
+++ b/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java
@@ -17,19 +17,20 @@
 package com.android.inputmethod.compat;
 
 import android.graphics.Typeface;
-import android.os.Build;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.style.StyleSpan;
 
+import com.android.inputmethod.latin.common.Constants;
+
 import java.util.Locale;
 
 @SmallTest
 public class LocaleSpanCompatUtilsTests extends AndroidTestCase {
     public void testInstantiatable() {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
+        if (!Constants.JELLY_BEAN_MR1_OR_HIGHER) {
             // LocaleSpan isn't yet available.
             return;
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/DevanagariLetterConstants.java b/tests/src/com/android/inputmethod/keyboard/layout/DevanagariLetterConstants.java
index bcf06f0..557cc21 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/DevanagariLetterConstants.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/DevanagariLetterConstants.java
@@ -16,15 +16,14 @@
 
 package com.android.inputmethod.keyboard.layout;
 
-import android.os.Build;
+import com.android.inputmethod.latin.common.Constants;
 
 /**
  * This class offers label strings of Devanagari letters that need the dotted circle to draw
  * its glyph.
  */
 class DevanagariLetterConstants {
-    private static final boolean NEEDS_DOTTED_CIRCLE =
-            Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN;
+    private static final boolean NEEDS_DOTTED_CIRCLE = !Constants.JELLY_BEAN_OR_HIGHER;
     // U+25CC: "◌" DOTTED CIRCLE
     private static final String DOTTED_CIRCLE = NEEDS_DOTTED_CIRCLE ? "\u25CC" : "";
 
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
index baac088..a51558e 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
@@ -700,8 +700,7 @@
         final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
         final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
 
-        binaryDictionary.addUnigramEntry("", DUMMY_PROBABILITY, "" /* shortcutTarget */,
-                Dictionary.NOT_A_PROBABILITY /* shortcutProbability */,
+        binaryDictionary.addUnigramEntry("", DUMMY_PROBABILITY,
                 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 a8f0d81..1618798 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -182,8 +182,7 @@
         addUnigramWord(binaryDictionary, validLongWord, probability);
         addUnigramWord(binaryDictionary, invalidLongWord, probability);
         // Too long short cut.
-        binaryDictionary.addUnigramEntry("a", probability, invalidLongWord,
-                10 /* shortcutProbability */, false /* isBeginningOfSentence */,
+        binaryDictionary.addUnigramEntry("a", probability, false /* isBeginningOfSentence */,
                 false /* isNotAWord */, false /* isPossiblyOffensive */,
                 BinaryDictionary.NOT_A_VALID_TIMESTAMP);
         addUnigramWord(binaryDictionary, "abc", probability);
@@ -201,8 +200,7 @@
 
     private static void addUnigramWord(final BinaryDictionary binaryDictionary, final String word,
             final int probability) {
-        binaryDictionary.addUnigramEntry(word, probability, "" /* shortcutTarget */,
-                Dictionary.NOT_A_PROBABILITY /* shortcutProbability */,
+        binaryDictionary.addUnigramEntry(word, probability,
                 false /* isBeginningOfSentence */, false /* isNotAWord */,
                 false /* isPossiblyOffensive */,
                 BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
@@ -884,7 +882,6 @@
             final boolean isPossiblyOffensive = random.nextBoolean();
             // TODO: Add tests for historical info.
             binaryDictionary.addUnigramEntry(word, unigramProbability,
-                    null /* shortcutTarget */, Dictionary.NOT_A_PROBABILITY,
                     false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive,
                     BinaryDictionary.NOT_A_VALID_TIMESTAMP);
             if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
@@ -899,9 +896,7 @@
             assertEquals(isNotAWord, wordProperty.mIsNotAWord);
             assertEquals(isPossiblyOffensive, wordProperty.mIsPossiblyOffensive);
             assertEquals(false, wordProperty.mHasNgrams);
-            assertEquals(false, wordProperty.mHasShortcuts);
             assertEquals(unigramProbability, wordProperty.mProbabilityInfo.mProbability);
-            assertTrue(wordProperty.mShortcutTargets.isEmpty());
         }
 
         for (int i = 0; i < BIGRAM_COUNT; i++) {
@@ -1035,137 +1030,10 @@
         assertTrue(bigramSet.isEmpty());
     }
 
-    public void testAddShortcuts() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddShortcuts(formatVersion);
-        }
-    }
-
-    private void testAddShortcuts(final int formatVersion) {
-        final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(formatVersion);
-
-        final int unigramProbability = 100;
-        final int shortcutProbability = 10;
-        binaryDictionary.addUnigramEntry("aaa", unigramProbability, "zzz",
-                shortcutProbability, false /* isBeginningOfSentence */,
-                false /* isNotAWord */, false /* isPossiblyOffensive */, 0 /* timestamp */);
-        WordProperty wordProperty = binaryDictionary.getWordProperty("aaa",
-                false /* isBeginningOfSentence */);
-        assertEquals(1, wordProperty.mShortcutTargets.size());
-        assertEquals("zzz", wordProperty.mShortcutTargets.get(0).mWord);
-        assertEquals(shortcutProbability, wordProperty.mShortcutTargets.get(0).getProbability());
-        final int updatedShortcutProbability = 2;
-        binaryDictionary.addUnigramEntry("aaa", unigramProbability, "zzz",
-                updatedShortcutProbability, false /* isBeginningOfSentence */,
-                false /* isNotAWord */, false /* isPossiblyOffensive */, 0 /* timestamp */);
-        wordProperty = binaryDictionary.getWordProperty("aaa",
-                false /* isBeginningOfSentence */);
-        assertEquals(1, wordProperty.mShortcutTargets.size());
-        assertEquals("zzz", wordProperty.mShortcutTargets.get(0).mWord);
-        assertEquals(updatedShortcutProbability,
-                wordProperty.mShortcutTargets.get(0).getProbability());
-        binaryDictionary.addUnigramEntry("aaa", unigramProbability, "yyy",
-                shortcutProbability, false /* isBeginningOfSentence */, false /* isNotAWord */,
-                false /* isPossiblyOffensive */, 0 /* timestamp */);
-        final HashMap<String, Integer> shortcutTargets = new HashMap<>();
-        shortcutTargets.put("zzz", updatedShortcutProbability);
-        shortcutTargets.put("yyy", shortcutProbability);
-        wordProperty = binaryDictionary.getWordProperty("aaa",
-                false /* isBeginningOfSentence */);
-        assertEquals(2, wordProperty.mShortcutTargets.size());
-        for (WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-            assertTrue(shortcutTargets.containsKey(shortcutTarget.mWord));
-            assertEquals((int)shortcutTargets.get(shortcutTarget.mWord),
-                    shortcutTarget.getProbability());
-            shortcutTargets.remove(shortcutTarget.mWord);
-        }
-        shortcutTargets.put("zzz", updatedShortcutProbability);
-        shortcutTargets.put("yyy", shortcutProbability);
-        binaryDictionary.flushWithGC();
-        wordProperty = binaryDictionary.getWordProperty("aaa",
-                false /* isBeginningOfSentence */);
-        assertEquals(2, wordProperty.mShortcutTargets.size());
-        for (WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-            assertTrue(shortcutTargets.containsKey(shortcutTarget.mWord));
-            assertEquals((int)shortcutTargets.get(shortcutTarget.mWord),
-                    shortcutTarget.getProbability());
-            shortcutTargets.remove(shortcutTarget.mWord);
-        }
-    }
-
-    public void testAddManyShortcuts() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddManyShortcuts(formatVersion);
-        }
-    }
-
-    private void testAddManyShortcuts(final int formatVersion) {
-        final long seed = System.currentTimeMillis();
-        final Random random = new Random(seed);
-        final int UNIGRAM_COUNT = 1000;
-        final int SHORTCUT_COUNT = 10000;
-        final int codePointSetSize = 20;
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
-        final ArrayList<String> words = new ArrayList<>();
-        final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
-        final HashMap<String, HashMap<String, Integer>> shortcutTargets = new HashMap<>();
-        final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(formatVersion);
-
-        for (int i = 0; i < UNIGRAM_COUNT; i++) {
-            final String word = CodePointUtils.generateWord(random, codePointSet);
-            final int unigramProbability = random.nextInt(0xFF);
-            addUnigramWord(binaryDictionary, word, unigramProbability);
-            words.add(word);
-            unigramProbabilities.put(word, unigramProbability);
-            if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                binaryDictionary.flushWithGC();
-            }
-        }
-        for (int i = 0; i < SHORTCUT_COUNT; i++) {
-            final String shortcutTarget = CodePointUtils.generateWord(random, codePointSet);
-            final int shortcutProbability = random.nextInt(0xF);
-            final String word = words.get(random.nextInt(words.size()));
-            final int unigramProbability = unigramProbabilities.get(word);
-            binaryDictionary.addUnigramEntry(word, unigramProbability, shortcutTarget,
-                    shortcutProbability, false /* isBeginningOfSentence */, false /* isNotAWord */,
-                    false /* isPossiblyOffensive */, 0 /* timestamp */);
-            if (shortcutTargets.containsKey(word)) {
-                final HashMap<String, Integer> shortcutTargetsOfWord = shortcutTargets.get(word);
-                shortcutTargetsOfWord.put(shortcutTarget, shortcutProbability);
-            } else {
-                final HashMap<String, Integer> shortcutTargetsOfWord = new HashMap<>();
-                shortcutTargetsOfWord.put(shortcutTarget, shortcutProbability);
-                shortcutTargets.put(word, shortcutTargetsOfWord);
-            }
-            if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                binaryDictionary.flushWithGC();
-            }
-        }
-
-        for (final String word : words) {
-            final WordProperty wordProperty = binaryDictionary.getWordProperty(word,
-                    false /* isBeginningOfSentence */);
-            assertEquals((int)unigramProbabilities.get(word),
-                    wordProperty.mProbabilityInfo.mProbability);
-            if (!shortcutTargets.containsKey(word)) {
-                // The word does not have shortcut targets.
-                continue;
-            }
-            assertEquals(shortcutTargets.get(word).size(), wordProperty.mShortcutTargets.size());
-            for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-                final String targetCodePonts = shortcutTarget.mWord;
-                assertEquals((int)shortcutTargets.get(word).get(targetCodePonts),
-                        shortcutTarget.getProbability());
-            }
-        }
-    }
-
     public void testPossiblyOffensiveAttributeMaintained() {
         final BinaryDictionary binaryDictionary =
                 getEmptyBinaryDictionary(FormatSpec.VERSION403);
-        binaryDictionary.addUnigramEntry("ddd", 100, null, Dictionary.NOT_A_PROBABILITY,
-                false, true, true, 0);
+        binaryDictionary.addUnigramEntry("ddd", 100, false, true, true, 0);
         WordProperty wordProperty = binaryDictionary.getWordProperty("ddd", false);
         assertEquals(true, wordProperty.mIsPossiblyOffensive);
     }
@@ -1184,11 +1052,11 @@
         final int bigramProbability = 150;
         addBigramWords(binaryDictionary, "aaa", "bbb", bigramProbability);
         final int shortcutProbability = 10;
-        binaryDictionary.addUnigramEntry("ccc", unigramProbability, "xxx", shortcutProbability,
+        binaryDictionary.addUnigramEntry("ccc", unigramProbability,
                 false /* isBeginningOfSentence */, false /* isNotAWord */,
                 false /* isPossiblyOffensive */, 0 /* timestamp */);
-        binaryDictionary.addUnigramEntry("ddd", unigramProbability, null /* shortcutTarget */,
-                Dictionary.NOT_A_PROBABILITY, false /* isBeginningOfSentence */,
+        binaryDictionary.addUnigramEntry("ddd", unigramProbability,
+                false /* isBeginningOfSentence */,
                 true /* isNotAWord */, true /* isPossiblyOffensive */, 0 /* timestamp */);
         binaryDictionary.addNgramEntry(NgramContext.BEGINNING_OF_SENTENCE,
                 "aaa", bigramProbability, 0 /* timestamp */);
@@ -1207,8 +1075,6 @@
         assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
         WordProperty wordProperty = binaryDictionary.getWordProperty("ccc",
                 false /* isBeginningOfSentence */);
-        assertEquals(1, wordProperty.mShortcutTargets.size());
-        assertEquals("xxx", wordProperty.mShortcutTargets.get(0).mWord);
         wordProperty = binaryDictionary.getWordProperty("ddd",
                 false /* isBeginningOfSentence */);
         assertTrue(wordProperty.mIsPossiblyOffensive);
diff --git a/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java b/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
index 07d7c32..6c6f628 100644
--- a/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
@@ -35,19 +35,19 @@
         FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
                 new DictionaryOptions(new HashMap<String,String>()));
 
-        dict.add("abc", new ProbabilityInfo(10), null, false /* isNotAWord */,
+        dict.add("abc", new ProbabilityInfo(10), false /* isNotAWord */,
                 false /* isPossiblyOffensive */);
         assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
         assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "abc"));
 
-        dict.add("aa", new ProbabilityInfo(10), null, false /* isNotAWord */,
+        dict.add("aa", new ProbabilityInfo(10), false /* isNotAWord */,
                 false /* isPossiblyOffensive */);
         assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
         assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aa"));
 
-        dict.add("babcd", new ProbabilityInfo(10), null, false /* isNotAWord */,
+        dict.add("babcd", new ProbabilityInfo(10), false /* isNotAWord */,
                 false /* isPossiblyOffensive */);
-        dict.add("bacde", new ProbabilityInfo(10), null, false /* isNotAWord */,
+        dict.add("bacde", new ProbabilityInfo(10), false /* isNotAWord */,
                 false /* isPossiblyOffensive */);
         assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "ba"));
         assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "babcd"));
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
index d833b97..39da9fc 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
@@ -57,15 +57,12 @@
     private static final int UNIGRAM_FREQ = 10;
     private static final int BIGRAM_FREQ = 50;
     private static final int TOLERANCE_OF_BIGRAM_FREQ = 5;
-    private static final int NUM_OF_NODES_HAVING_SHORTCUTS = 50;
-    private static final int NUM_OF_SHORTCUTS = 5;
 
     private static final ArrayList<String> sWords = new ArrayList<>();
     private static final ArrayList<String> sWordsWithVariousCodePoints = new ArrayList<>();
     private static final SparseArray<List<Integer>> sEmptyBigrams = new SparseArray<>();
     private static final SparseArray<List<Integer>> sStarBigrams = new SparseArray<>();
     private static final SparseArray<List<Integer>> sChainBigrams = new SparseArray<>();
-    private static final HashMap<String, List<String>> sShortcuts = new HashMap<>();
 
     final Random mRandom;
 
@@ -95,16 +92,6 @@
         for (int i = 1; i < maxBigrams; ++i) {
             sStarBigrams.get(0).add(i);
         }
-
-        sShortcuts.clear();
-        for (int i = 0; i < NUM_OF_NODES_HAVING_SHORTCUTS; ++i) {
-            final int from = Math.abs(mRandom.nextInt()) % sWords.size();
-            sShortcuts.put(sWords.get(from), new ArrayList<String>());
-            for (int j = 0; j < NUM_OF_SHORTCUTS; ++j) {
-                final int to = Math.abs(mRandom.nextInt()) % sWords.size();
-                sShortcuts.get(sWords.get(from)).add(sWords.get(to));
-            }
-        }
     }
 
     @Override
@@ -142,17 +129,11 @@
      * Adds unigrams to the dictionary.
      */
     private static void addUnigrams(final int number, final FusionDictionary dict,
-            final List<String> words, final HashMap<String, List<String>> shortcutMap) {
+            final List<String> words) {
         for (int i = 0; i < number; ++i) {
             final String word = words.get(i);
             final ArrayList<WeightedString> shortcuts = new ArrayList<>();
-            if (shortcutMap != null && shortcutMap.containsKey(word)) {
-                for (final String shortcut : shortcutMap.get(word)) {
-                    shortcuts.add(new WeightedString(shortcut, UNIGRAM_FREQ));
-                }
-            }
-            dict.add(word, new ProbabilityInfo(UNIGRAM_FREQ),
-                    (shortcutMap == null) ? null : shortcuts, false /* isNotAWord */,
+            dict.add(word, new ProbabilityInfo(UNIGRAM_FREQ), false /* isNotAWord */,
                     false /* isPossiblyOffensive */);
         }
     }
@@ -200,8 +181,7 @@
     }
 
     private static void checkDictionary(final FusionDictionary dict, final List<String> words,
-            final SparseArray<List<Integer>> bigrams,
-            final HashMap<String, List<String>> shortcutMap) {
+            final SparseArray<List<Integer>> bigrams) {
         assertNotNull(dict);
 
         // check unigram
@@ -219,19 +199,6 @@
                 assertNotNull(words.get(w1) + "," + words.get(w2), ptNode.getBigram(words.get(w2)));
             }
         }
-
-        // check shortcut
-        if (shortcutMap != null) {
-            for (final Entry<String, List<String>> entry : shortcutMap.entrySet()) {
-                assertTrue(words.contains(entry.getKey()));
-                final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray,
-                        entry.getKey());
-                for (final String word : entry.getValue()) {
-                    assertNotNull("shortcut not found: " + entry.getKey() + ", " + word,
-                            ptNode.getShortcut(word));
-                }
-            }
-        }
     }
 
     private static String outputOptions(final int bufferType,
@@ -244,8 +211,7 @@
     // Tests for readDictionaryBinary and writeDictionaryBinary
 
     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) {
+            final SparseArray<List<Integer>> bigrams, final int bufferType) {
         long now, diff = -1;
 
         FusionDictionary dict = null;
@@ -261,13 +227,13 @@
             Log.e(TAG, "Unsupported format", e);
         }
 
-        checkDictionary(dict, words, bigrams, shortcutMap);
+        checkDictionary(dict, words, bigrams);
         return diff;
     }
 
     // Tests for readDictionaryBinary and writeDictionaryBinary
     private String runReadAndWrite(final List<String> words,
-            final SparseArray<List<Integer>> bigrams, final HashMap<String, List<String>> shortcuts,
+            final SparseArray<List<Integer>> bigrams,
             final int bufferType, final FormatSpec.FormatOptions formatOptions,
             final String message) {
 
@@ -278,12 +244,12 @@
 
         final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
                 BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(words.size(), dict, words, shortcuts);
+        addUnigrams(words.size(), dict, words);
         addBigrams(dict, words, bigrams);
-        checkDictionary(dict, words, bigrams, shortcuts);
+        checkDictionary(dict, words, bigrams);
 
         final long write = timeWritingDictToFile(file, dict, formatOptions);
-        final long read = timeReadingAndCheckDict(file, words, bigrams, shortcuts, bufferType);
+        final long read = timeReadingAndCheckDict(file, words, bigrams, bufferType);
 
         return "PROF: read=" + read + "ms, write=" + write + "ms :" + message
                 + " : " + outputOptions(bufferType, formatOptions);
@@ -291,20 +257,20 @@
 
     private void runReadAndWriteTests(final List<String> results, final int bufferType,
             final FormatSpec.FormatOptions formatOptions) {
-        results.add(runReadAndWrite(sWords, sEmptyBigrams, null /* shortcuts */, bufferType,
+        results.add(runReadAndWrite(sWords, sEmptyBigrams, bufferType,
                 formatOptions, "unigram"));
-        results.add(runReadAndWrite(sWords, sChainBigrams, null /* shortcuts */, bufferType,
+        results.add(runReadAndWrite(sWords, sChainBigrams, bufferType,
                 formatOptions, "chain"));
-        results.add(runReadAndWrite(sWords, sStarBigrams, null /* shortcuts */, bufferType,
+        results.add(runReadAndWrite(sWords, sStarBigrams, bufferType,
                 formatOptions, "star"));
-        results.add(runReadAndWrite(sWords, sEmptyBigrams, sShortcuts, bufferType, formatOptions,
+        results.add(runReadAndWrite(sWords, sEmptyBigrams, bufferType, formatOptions,
                 "unigram with shortcuts"));
-        results.add(runReadAndWrite(sWords, sChainBigrams, sShortcuts, bufferType, formatOptions,
+        results.add(runReadAndWrite(sWords, sChainBigrams, bufferType, formatOptions,
                 "chain with shortcuts"));
-        results.add(runReadAndWrite(sWords, sStarBigrams, sShortcuts, bufferType, formatOptions,
+        results.add(runReadAndWrite(sWords, sStarBigrams, bufferType, formatOptions,
                 "star with shortcuts"));
         results.add(runReadAndWrite(sWordsWithVariousCodePoints, sEmptyBigrams,
-                null /* shortcuts */, bufferType, formatOptions,
+                bufferType, formatOptions,
                 "unigram with various code points"));
     }
 
@@ -326,7 +292,7 @@
                         FormatSpec.MINIMUM_SUPPORTED_STATIC_VERSION);
         final FusionDictionary sourcedict = new FusionDictionary(new PtNodeArray(),
                 BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(words.size(), sourcedict, words, null /* shortcutMap */);
+        addUnigrams(words.size(), sourcedict, words);
         dictEncoder.writeDictionary(sourcedict, formatOptions);
 
         // Read the dictionary
@@ -472,7 +438,7 @@
         // making the dictionary from lists of words.
         final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
                 BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(words.size(), dict, words, null /* shortcutMap */);
+        addUnigrams(words.size(), dict, words);
         addBigrams(dict, words, bigrams);
 
         timeWritingDictToFile(file, dict, formatOptions);
@@ -482,7 +448,7 @@
         // TODO: Abandon the Java code, and implement the v4 dictionary reading code in native.
         long wordMap = timeAndCheckReadUnigramsAndBigramsBinary(file, words, bigrams, bufferType,
                 !formatOptions.mHasTimestamp /* checkProbability */);
-        long fullReading = timeReadingAndCheckDict(file, words, bigrams, null /* shortcutMap */,
+        long fullReading = timeReadingAndCheckDict(file, words, bigrams,
                 bufferType);
 
         return "readDictionaryBinary=" + fullReading + ", readUnigramsAndBigramsBinary=" + wordMap
@@ -567,7 +533,7 @@
 
         final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
                 BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
+        addUnigrams(sWords.size(), dict, sWords);
         addBigrams(dict, words, bigrams);
         timeWritingDictToFile(file, dict, formatOptions);
 
@@ -636,12 +602,11 @@
     public void testVer2DictGetWordProperty() {
         final FormatOptions formatOptions = BinaryDictUtils.STATIC_OPTIONS;
         final ArrayList<String> words = sWords;
-        final HashMap<String, List<String>> shortcuts = sShortcuts;
         final String dictName = "testGetWordProperty";
         final String dictVersion = Long.toString(System.currentTimeMillis());
         final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
                 BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(words.size(), dict, words, shortcuts);
+        addUnigrams(words.size(), dict, words);
         addBigrams(dict, words, sEmptyBigrams);
         final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
                 getContext().getCacheDir());
@@ -655,30 +620,18 @@
                     false /* isBeginningOfSentence */);
             assertEquals(word, wordProperty.mWord);
             assertEquals(UNIGRAM_FREQ, wordProperty.getProbability());
-            if (shortcuts.containsKey(word)) {
-                assertEquals(shortcuts.get(word).size(), wordProperty.mShortcutTargets.size());
-                final List<String> shortcutList = shortcuts.get(word);
-                assertTrue(wordProperty.mHasShortcuts);
-                for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-                    assertTrue(shortcutList.contains(shortcutTarget.mWord));
-                    assertEquals(UNIGRAM_FREQ, shortcutTarget.getProbability());
-                    shortcutList.remove(shortcutTarget.mWord);
-                }
-                assertTrue(shortcutList.isEmpty());
-            }
         }
     }
 
     public void testVer2DictIteration() {
         final FormatOptions formatOptions = BinaryDictUtils.STATIC_OPTIONS;
         final ArrayList<String> words = sWords;
-        final HashMap<String, List<String>> shortcuts = sShortcuts;
         final SparseArray<List<Integer>> bigrams = sEmptyBigrams;
         final String dictName = "testGetWordProperty";
         final String dictVersion = Long.toString(System.currentTimeMillis());
         final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
                 BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(words.size(), dict, words, shortcuts);
+        addUnigrams(words.size(), dict, words);
         addBigrams(dict, words, bigrams);
         final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
                 getContext().getCacheDir());
@@ -708,17 +661,6 @@
             final String word0 = wordProperty.mWord;
             assertEquals(UNIGRAM_FREQ, wordProperty.mProbabilityInfo.mProbability);
             wordSet.remove(word0);
-            if (shortcuts.containsKey(word0)) {
-                assertEquals(shortcuts.get(word0).size(), wordProperty.mShortcutTargets.size());
-                final List<String> shortcutList = shortcuts.get(word0);
-                assertNotNull(wordProperty.mShortcutTargets);
-                for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-                    assertTrue(shortcutList.contains(shortcutTarget.mWord));
-                    assertEquals(UNIGRAM_FREQ, shortcutTarget.getProbability());
-                    shortcutList.remove(shortcutTarget.mWord);
-                }
-                assertTrue(shortcutList.isEmpty());
-            }
             if (wordProperty.mHasNgrams) {
                 for (final WeightedString bigramTarget : wordProperty.getBigrams()) {
                     final String word1 = bigramTarget.mWord;
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
index ce905c4..bd51365 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
@@ -16,9 +16,7 @@
 
 package com.android.inputmethod.latin.makedict;
 
-import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
 import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
 import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
 import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
@@ -92,38 +90,6 @@
     }
 
     /**
-     * Compute the size of a shortcut in bytes.
-     */
-    private static int getShortcutSize(final WeightedString shortcut,
-            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
-        int size = FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE;
-        final String word = shortcut.mWord;
-        final int length = word.length();
-        for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
-            final int codePoint = word.codePointAt(i);
-            size += CharEncoding.getCharSize(codePoint, codePointToOneByteCodeMap);
-        }
-        size += FormatSpec.PTNODE_TERMINATOR_SIZE;
-        return size;
-    }
-
-    /**
-     * Compute the size of a shortcut list in bytes.
-     *
-     * This is known in advance and does not change according to position in the file
-     * like address lists do.
-     */
-    static int getShortcutListSize(final ArrayList<WeightedString> shortcutList,
-            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
-        if (null == shortcutList || shortcutList.isEmpty()) return 0;
-        int size = FormatSpec.PTNODE_SHORTCUT_LIST_SIZE_SIZE;
-        for (final WeightedString shortcut : shortcutList) {
-            size += getShortcutSize(shortcut, codePointToOneByteCodeMap);
-        }
-        return size;
-    }
-
-    /**
      * Compute the maximum size of a PtNode, assuming 3-byte addresses for everything.
      *
      * @param ptNode the PtNode to compute the size of.
@@ -137,8 +103,6 @@
             size += FormatSpec.PTNODE_FREQUENCY_SIZE;
         }
         size += FormatSpec.PTNODE_MAX_ADDRESS_SIZE; // For children address
-        // TODO: Use codePointToOneByteCodeMap for shortcuts.
-        size += getShortcutListSize(ptNode.mShortcutTargets, null /* codePointToOneByteCodeMap */);
         if (null != ptNode.mBigrams) {
             size += (FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE
                     + FormatSpec.PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE)
@@ -241,27 +205,6 @@
         }
     }
 
-    @UsedForTesting
-    static void writeUIntToDictBuffer(final DictBuffer dictBuffer, final int value,
-            final int size) {
-        switch(size) {
-            case 4:
-                dictBuffer.put((byte) ((value >> 24) & 0xFF));
-                /* fall through */
-            case 3:
-                dictBuffer.put((byte) ((value >> 16) & 0xFF));
-                /* fall through */
-            case 2:
-                dictBuffer.put((byte) ((value >> 8) & 0xFF));
-                /* fall through */
-            case 1:
-                dictBuffer.put((byte) (value & 0xFF));
-                break;
-            default:
-                /* nop */
-        }
-    }
-
     // End utility methods
 
     // This method is responsible for finding a nice ordering of the nodes that favors run-time
@@ -391,9 +334,6 @@
                 nodeSize += getByteSize(getOffsetToTargetNodeArrayDuringUpdate(ptNodeArray,
                         nodeSize + size, ptNode.mChildren));
             }
-            // TODO: Use codePointToOneByteCodeMap for shortcuts.
-            nodeSize += getShortcutListSize(ptNode.mShortcutTargets,
-                    null /* codePointToOneByteCodeMap */);
             if (null != ptNode.mBigrams) {
                 for (WeightedString bigram : ptNode.mBigrams) {
                     final int offset = getOffsetToTargetPtNodeDuringUpdate(ptNodeArray,
@@ -568,14 +508,13 @@
      * @param hasMultipleChars whether the PtNode has multiple chars.
      * @param isTerminal whether the PtNode is terminal.
      * @param childrenAddressSize the size of a children address.
-     * @param hasShortcuts whether the PtNode has shortcuts.
      * @param hasBigrams whether the PtNode has bigrams.
      * @param isNotAWord whether the PtNode is not a word.
      * @param isPossiblyOffensive whether the PtNode is a possibly offensive entry.
      * @return the flags
      */
     static int makePtNodeFlags(final boolean hasMultipleChars, final boolean isTerminal,
-            final int childrenAddressSize, final boolean hasShortcuts, final boolean hasBigrams,
+            final int childrenAddressSize, final boolean hasBigrams,
             final boolean isNotAWord, final boolean isPossiblyOffensive) {
         byte flags = 0;
         if (hasMultipleChars) flags |= FormatSpec.FLAG_HAS_MULTIPLE_CHARS;
@@ -596,7 +535,6 @@
             default:
                 throw new RuntimeException("Node with a strange address");
         }
-        if (hasShortcuts) flags |= FormatSpec.FLAG_HAS_SHORTCUT_TARGETS;
         if (hasBigrams) flags |= FormatSpec.FLAG_HAS_BIGRAMS;
         if (isNotAWord) flags |= FormatSpec.FLAG_IS_NOT_A_WORD;
         if (isPossiblyOffensive) flags |= FormatSpec.FLAG_IS_POSSIBLY_OFFENSIVE;
@@ -606,7 +544,6 @@
     /* package */ static byte makePtNodeFlags(final PtNode node, final int childrenOffset) {
         return (byte) makePtNodeFlags(node.mChars.length > 1, node.isTerminal(),
                 getByteSize(childrenOffset),
-                node.mShortcutTargets != null && !node.mShortcutTargets.isEmpty(),
                 node.mBigrams != null && !node.mBigrams.isEmpty(),
                 node.mIsNotAWord, node.mIsPossiblyOffensive);
     }
@@ -621,7 +558,7 @@
      * @param word the second bigram, for debugging purposes
      * @return the flags
      */
-    /* package */ static final int makeBigramFlags(final boolean more, final int offset,
+    /* package */ static int makeBigramFlags(final boolean more, final int offset,
             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);
@@ -690,19 +627,7 @@
         return discretizedFrequency > 0 ? discretizedFrequency : 0;
     }
 
-    /**
-     * Makes the flag value for a shortcut.
-     *
-     * @param more whether there are more attributes after this one.
-     * @param frequency the frequency of the attribute, 0..15
-     * @return the flags
-     */
-    static final int makeShortcutFlags(final boolean more, final int frequency) {
-        return (more ? FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT : 0)
-                + (frequency & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY);
-    }
-
-    /* package */ static final int getChildrenPosition(final PtNode ptNode,
+    /* package */ static int getChildrenPosition(final PtNode ptNode,
             final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
         int positionOfChildrenPosField = ptNode.mCachedAddressAfterUpdate
                 + getNodeHeaderSize(ptNode, codePointToOneByteCodeMap);
diff --git a/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index a42f0a9..52060be 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -82,7 +82,6 @@
     public static final class PtNode {
         private static final int NOT_A_TERMINAL = -1;
         final int mChars[];
-        ArrayList<WeightedString> mShortcutTargets;
         ArrayList<WeightedString> mBigrams;
         // null == mProbabilityInfo indicates this is not a terminal.
         ProbabilityInfo mProbabilityInfo;
@@ -100,26 +99,23 @@
         int mCachedAddressBeforeUpdate; // The address of this PtNode (before update)
         int mCachedAddressAfterUpdate; // The address of this PtNode (after update)
 
-        public PtNode(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
-                final ArrayList<WeightedString> bigrams, final ProbabilityInfo probabilityInfo,
-                final boolean isNotAWord, final boolean isPossiblyOffensive) {
+        public PtNode(final int[] chars, final ArrayList<WeightedString> bigrams,
+                final ProbabilityInfo probabilityInfo, final boolean isNotAWord,
+                final boolean isPossiblyOffensive) {
             mChars = chars;
             mProbabilityInfo = probabilityInfo;
             mTerminalId = probabilityInfo == null ? NOT_A_TERMINAL : probabilityInfo.mProbability;
-            mShortcutTargets = shortcutTargets;
             mBigrams = bigrams;
             mChildren = null;
             mIsNotAWord = isNotAWord;
             mIsPossiblyOffensive = isPossiblyOffensive;
         }
 
-        public PtNode(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
-                final ArrayList<WeightedString> bigrams, final ProbabilityInfo probabilityInfo,
-                final boolean isNotAWord, final boolean isPossiblyOffensive,
-                final PtNodeArray children) {
+        public PtNode(final int[] chars, final ArrayList<WeightedString> bigrams,
+                final ProbabilityInfo probabilityInfo, final boolean isNotAWord,
+                final boolean isPossiblyOffensive, final PtNodeArray children) {
             mChars = chars;
             mProbabilityInfo = probabilityInfo;
-            mShortcutTargets = shortcutTargets;
             mBigrams = bigrams;
             mChildren = children;
             mIsNotAWord = isNotAWord;
@@ -153,14 +149,6 @@
             return mIsPossiblyOffensive;
         }
 
-        public ArrayList<WeightedString> getShortcutTargets() {
-            // We don't want write permission to escape outside the package, so we return a copy
-            if (null == mShortcutTargets) return null;
-            final ArrayList<WeightedString> copyOfShortcutTargets =
-                    new ArrayList<>(mShortcutTargets);
-            return copyOfShortcutTargets;
-        }
-
         public ArrayList<WeightedString> getBigrams() {
             // We don't want write permission to escape outside the package, so we return a copy
             if (null == mBigrams) return null;
@@ -191,24 +179,6 @@
         }
 
         /**
-         * Gets the shortcut target for the given word. Returns null if the word is not in the
-         * shortcut list.
-         */
-        public WeightedString getShortcut(final String word) {
-            // TODO: Don't do a linear search
-            if (mShortcutTargets != null) {
-                final int size = mShortcutTargets.size();
-                for (int i = 0; i < size; ++i) {
-                    WeightedString shortcut = mShortcutTargets.get(i);
-                    if (shortcut.mWord.equals(word)) {
-                        return shortcut;
-                    }
-                }
-            }
-            return null;
-        }
-
-        /**
          * Gets the bigram for the given word.
          * Returns null if the word is not in the bigrams list.
          */
@@ -232,27 +202,9 @@
          * updated if they are higher than the existing ones.
          */
         void update(final ProbabilityInfo probabilityInfo,
-                final ArrayList<WeightedString> shortcutTargets,
                 final ArrayList<WeightedString> bigrams,
                 final boolean isNotAWord, final boolean isPossiblyOffensive) {
             mProbabilityInfo = ProbabilityInfo.max(mProbabilityInfo, probabilityInfo);
-            if (shortcutTargets != null) {
-                if (mShortcutTargets == null) {
-                    mShortcutTargets = shortcutTargets;
-                } else {
-                    final int size = shortcutTargets.size();
-                    for (int i = 0; i < size; ++i) {
-                        final WeightedString shortcut = shortcutTargets.get(i);
-                        final WeightedString existingShortcut = getShortcut(shortcut.mWord);
-                        if (existingShortcut == null) {
-                            mShortcutTargets.add(shortcut);
-                        } else {
-                            existingShortcut.mProbabilityInfo = ProbabilityInfo.max(
-                                    existingShortcut.mProbabilityInfo, shortcut.mProbabilityInfo);
-                        }
-                    }
-                }
-            }
             if (bigrams != null) {
                 if (mBigrams == null) {
                     mBigrams = bigrams;
@@ -312,19 +264,16 @@
      * Helper method to add a word as a string.
      *
      * This method adds a word to the dictionary with the given frequency. Optional
-     * lists of bigrams and shortcuts can be passed here. For each word inside,
+     * lists of bigrams can be passed here. For each word inside,
      * they will be added to the dictionary as necessary.
-     *
-     * @param word the word to add.
+     *  @param word the word to add.
      * @param probabilityInfo probability information of the word.
-     * @param shortcutTargets a list of shortcut targets for this word, or null.
      * @param isNotAWord true if this should not be considered a word (e.g. shortcut only)
      * @param isPossiblyOffensive true if this word is possibly offensive
      */
     public void add(final String word, final ProbabilityInfo probabilityInfo,
-            final ArrayList<WeightedString> shortcutTargets, final boolean isNotAWord,
-            final boolean isPossiblyOffensive) {
-        add(getCodePoints(word), probabilityInfo, shortcutTargets, isNotAWord, isPossiblyOffensive);
+            final boolean isNotAWord, final boolean isPossiblyOffensive) {
+        add(getCodePoints(word), probabilityInfo, isNotAWord, isPossiblyOffensive);
     }
 
     /**
@@ -358,7 +307,7 @@
         if (ptNode0 != null) {
             final PtNode ptNode1 = findWordInTree(mRootNodeArray, word1);
             if (ptNode1 == null) {
-                add(getCodePoints(word1), new ProbabilityInfo(0), null, false /* isNotAWord */,
+                add(getCodePoints(word1), new ProbabilityInfo(0), false /* isNotAWord */,
                         false /* isPossiblyOffensive */);
                 // The PtNode for the first word may have moved by the above insertion,
                 // if word1 and word2 share a common stem that happens not to have been
@@ -376,15 +325,12 @@
      *
      * The shortcuts, if any, have to be in the dictionary already. If they aren't,
      * an exception is thrown.
-     *
-     * @param word the word, as an int array.
+     *  @param word the word, as an int array.
      * @param probabilityInfo the probability information of the word.
-     * @param shortcutTargets an optional list of shortcut targets for this word (null if none).
      * @param isNotAWord true if this is not a word for spellcheking purposes (shortcut only or so)
      * @param isPossiblyOffensive true if this word is possibly offensive
      */
     private void add(final int[] word, final ProbabilityInfo probabilityInfo,
-            final ArrayList<WeightedString> shortcutTargets,
             final boolean isNotAWord, final boolean isPossiblyOffensive) {
         assert(probabilityInfo.mProbability <= FormatSpec.MAX_TERMINAL_FREQUENCY);
         if (word.length >= DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH) {
@@ -414,7 +360,7 @@
             // No node at this point to accept the word. Create one.
             final int insertionIndex = findInsertionIndex(currentNodeArray, word[charIndex]);
             final PtNode newPtNode = new PtNode(Arrays.copyOfRange(word, charIndex, word.length),
-                    shortcutTargets, null /* bigrams */, probabilityInfo, isNotAWord,
+                    null /* bigrams */, probabilityInfo, isNotAWord,
                     isPossiblyOffensive);
             currentNodeArray.mData.add(insertionIndex, newPtNode);
             if (DBG) checkStack(currentNodeArray);
@@ -425,14 +371,14 @@
                     // The new word is a prefix of an existing word, but the node on which it
                     // should end already exists as is. Since the old PtNode was not a terminal,
                     // make it one by filling in its frequency and other attributes
-                    currentPtNode.update(probabilityInfo, shortcutTargets, null, isNotAWord,
+                    currentPtNode.update(probabilityInfo, null, isNotAWord,
                             isPossiblyOffensive);
                 } else {
                     // The new word matches the full old word and extends past it.
                     // We only have to create a new node and add it to the end of this.
                     final PtNode newNode = new PtNode(
                             Arrays.copyOfRange(word, charIndex + differentCharIndex, word.length),
-                                    shortcutTargets, null /* bigrams */, probabilityInfo,
+                                    null /* bigrams */, probabilityInfo,
                                     isNotAWord, isPossiblyOffensive);
                     currentPtNode.mChildren = new PtNodeArray();
                     currentPtNode.mChildren.mData.add(newNode);
@@ -441,7 +387,7 @@
                 if (0 == differentCharIndex) {
                     // Exact same word. Update the frequency if higher. This will also add the
                     // new shortcuts to the existing shortcut list if it already exists.
-                    currentPtNode.update(probabilityInfo, shortcutTargets, null,
+                    currentPtNode.update(probabilityInfo, null,
                             currentPtNode.mIsNotAWord && isNotAWord,
                             currentPtNode.mIsPossiblyOffensive || isPossiblyOffensive);
                 } else {
@@ -450,7 +396,7 @@
                     PtNodeArray newChildren = new PtNodeArray();
                     final PtNode newOldWord = new PtNode(
                             Arrays.copyOfRange(currentPtNode.mChars, differentCharIndex,
-                                    currentPtNode.mChars.length), currentPtNode.mShortcutTargets,
+                                    currentPtNode.mChars.length),
                             currentPtNode.mBigrams, currentPtNode.mProbabilityInfo,
                             currentPtNode.mIsNotAWord, currentPtNode.mIsPossiblyOffensive,
                             currentPtNode.mChildren);
@@ -460,17 +406,17 @@
                     if (charIndex + differentCharIndex >= word.length) {
                         newParent = new PtNode(
                                 Arrays.copyOfRange(currentPtNode.mChars, 0, differentCharIndex),
-                                shortcutTargets, null /* bigrams */, probabilityInfo,
+                                null /* bigrams */, probabilityInfo,
                                 isNotAWord, isPossiblyOffensive, newChildren);
                     } else {
                         newParent = new PtNode(
                                 Arrays.copyOfRange(currentPtNode.mChars, 0, differentCharIndex),
-                                null /* shortcutTargets */, null /* bigrams */,
-                                null /* probabilityInfo */, false /* isNotAWord */,
-                                false /* isPossiblyOffensive */, newChildren);
+                                null /* bigrams */, null /* probabilityInfo */,
+                                false /* isNotAWord */, false /* isPossiblyOffensive */,
+                                newChildren);
                         final PtNode newWord = new PtNode(Arrays.copyOfRange(word,
                                 charIndex + differentCharIndex, word.length),
-                                shortcutTargets, null /* bigrams */, probabilityInfo,
+                                null /* bigrams */, probabilityInfo,
                                 isNotAWord, isPossiblyOffensive);
                         final int addIndex = word[charIndex + differentCharIndex]
                                 > currentPtNode.mChars[differentCharIndex] ? 1 : 0;
@@ -532,7 +478,7 @@
     private static int findInsertionIndex(final PtNodeArray nodeArray, int character) {
         final ArrayList<PtNode> data = nodeArray.mData;
         final PtNode reference = new PtNode(new int[] { character },
-                null /* shortcutTargets */, null /* bigrams */, null /* probabilityInfo */,
+                null /* bigrams */, null /* probabilityInfo */,
                 false /* isNotAWord */, false /* isPossiblyOffensive */);
         int result = Collections.binarySearch(data, reference, PTNODE_COMPARATOR);
         return result >= 0 ? result : -result - 1;
@@ -669,8 +615,7 @@
                     }
                     if (currentPtNode.isTerminal()) {
                         return new WordProperty(mCurrentString.toString(),
-                                currentPtNode.mProbabilityInfo,
-                                currentPtNode.mShortcutTargets, currentPtNode.mBigrams,
+                                currentPtNode.mProbabilityInfo, currentPtNode.mBigrams,
                                 currentPtNode.mIsNotAWord, currentPtNode.mIsPossiblyOffensive);
                     }
                 } else {
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
index 5c261a9..7ee1df9 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
@@ -285,7 +285,7 @@
         // Insert unigrams into the fusion dictionary.
         for (final WordProperty wordProperty : wordProperties) {
             fusionDict.add(wordProperty.mWord, wordProperty.mProbabilityInfo,
-                    wordProperty.mShortcutTargets, wordProperty.mIsNotAWord,
+                    wordProperty.mIsNotAWord,
                     wordProperty.mIsPossiblyOffensive);
         }
         // Insert bigrams into the fusion dictionary.
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
index b52b8c4..c63b972 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
@@ -240,37 +240,6 @@
     }
 
     /**
-     * Write a shortcut attributes list to mBuffer.
-     *
-     * @param shortcuts the shortcut attributes list.
-     */
-    private void writeShortcuts(final ArrayList<WeightedString> shortcuts,
-            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
-        if (null == shortcuts || shortcuts.isEmpty()) return;
-
-        final int indexOfShortcutByteSize = mPosition;
-        mPosition += FormatSpec.PTNODE_SHORTCUT_LIST_SIZE_SIZE;
-        final Iterator<WeightedString> shortcutIterator = shortcuts.iterator();
-        while (shortcutIterator.hasNext()) {
-            final WeightedString target = shortcutIterator.next();
-            final int shortcutFlags = BinaryDictEncoderUtils.makeShortcutFlags(
-                    shortcutIterator.hasNext(),
-                    target.getProbability());
-            mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, shortcutFlags,
-                    FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE);
-            final int shortcutShift = CharEncoding.writeString(mBuffer, mPosition, target.mWord,
-                codePointToOneByteCodeMap);
-            mPosition += shortcutShift;
-        }
-        final int shortcutByteSize = mPosition - indexOfShortcutByteSize;
-        if (shortcutByteSize > FormatSpec.MAX_SHORTCUT_LIST_SIZE_IN_A_PTNODE) {
-            throw new RuntimeException("Shortcut list too large");
-        }
-        BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, indexOfShortcutByteSize, shortcutByteSize,
-                FormatSpec.PTNODE_SHORTCUT_LIST_SIZE_SIZE);
-    }
-
-    /**
      * Write a bigram attributes list to mBuffer.
      *
      * @param bigrams the bigram attributes list.
@@ -305,8 +274,6 @@
         writeCharacters(ptNode.mChars, ptNode.hasSeveralChars(), codePointToOneByteCodeMap);
         writeFrequency(ptNode.getProbability());
         writeChildrenPosition(ptNode, codePointToOneByteCodeMap);
-        // TODO: Use codePointToOneByteCodeMap for shortcuts.
-        writeShortcuts(ptNode.mShortcutTargets, null /* codePointToOneByteCodeMap */);
         writeBigrams(ptNode.mBigrams, dict);
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java
index 7d85876..dbf9b7a 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java
@@ -16,9 +16,7 @@
 
 package com.android.inputmethod.latin.makedict;
 
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map.Entry;
 
@@ -49,7 +47,7 @@
                 new FormatSpec.FormatOptions(FormatSpec.VERSION2);
         final FusionDictionary sourcedict = new FusionDictionary(new PtNodeArray(),
                 BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(sourcedict, words, null /* shortcutMap */);
+        addUnigrams(sourcedict, words);
         final CodePointTable codePointTable = Ver2DictEncoder.makeCodePointTable(sourcedict);
 
         // Check if mCodePointOccurrenceArray is correct
@@ -73,17 +71,10 @@
     /**
      * Adds unigrams to the dictionary.
      */
-    private static void addUnigrams(final FusionDictionary dict, final List<String> words,
-            final HashMap<String, List<String>> shortcutMap) {
+    private static void addUnigrams(final FusionDictionary dict, final List<String> words) {
         for (final String word : words) {
-            final ArrayList<WeightedString> shortcuts = new ArrayList<>();
-            if (shortcutMap != null && shortcutMap.containsKey(word)) {
-                for (final String shortcut : shortcutMap.get(word)) {
-                    shortcuts.add(new WeightedString(shortcut, UNIGRAM_FREQ));
-                }
-            }
             dict.add(word, new ProbabilityInfo(UNIGRAM_FREQ),
-                    (shortcutMap == null) ? null : shortcuts, false /* isNotAWord */,
+                    false /* isNotAWord */,
                     false /* isPossiblyOffensive */);
         }
     }
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
index 63ea89c..746431d 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
@@ -84,7 +84,7 @@
         // Insert unigrams into the fusion dictionary.
         for (final WordProperty wordProperty : wordProperties) {
             fusionDict.add(wordProperty.mWord, wordProperty.mProbabilityInfo,
-                    wordProperty.mShortcutTargets, wordProperty.mIsNotAWord,
+                    wordProperty.mIsNotAWord,
                     wordProperty.mIsPossiblyOffensive);
         }
         // Insert bigrams into the fusion dictionary.
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
index 1e4bd76..6e7b37d 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
@@ -74,26 +74,10 @@
             throw new IOException("Cannot create dictionary file");
         }
         for (final WordProperty wordProperty : dict) {
-            // TODO: switch to addMultipleDictionaryEntries when they support shortcuts
-            if (null == wordProperty.mShortcutTargets || wordProperty.mShortcutTargets.isEmpty()) {
-                if (!binaryDict.addUnigramEntry(wordProperty.mWord, wordProperty.getProbability(),
-                        null /* shortcutTarget */, 0 /* shortcutProbability */,
-                        wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord,
-                        wordProperty.mIsPossiblyOffensive, 0 /* timestamp */)) {
-                    MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord);
-                }
-            } else {
-                for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-                    if (!binaryDict.addUnigramEntry(wordProperty.mWord,
-                            wordProperty.getProbability(),
-                            shortcutTarget.mWord, shortcutTarget.getProbability(),
-                            wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord,
-                            wordProperty.mIsPossiblyOffensive, 0 /* timestamp */)) {
-                        MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord
-                                + ", shortcutTarget: " + shortcutTarget.mWord);
-                        return;
-                    }
-                }
+            if (!binaryDict.addUnigramEntry(wordProperty.mWord, wordProperty.getProbability(),
+                    wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord,
+                    wordProperty.mIsPossiblyOffensive, 0 /* timestamp */)) {
+                MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord);
             }
             if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) {
                 if (!binaryDict.flushWithGC()) {