Merge "Fix tab key's navigation behavior"
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
index c4452a5..5326120 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
@@ -68,12 +68,20 @@
 
         public MoreKeySpec(final String moreKeySpec, boolean needsToUpperCase, Locale locale,
                 final KeyboardCodesSet codesSet) {
-            mCode = toUpperCaseOfCodeForLocale(getCode(moreKeySpec, codesSet),
-                    needsToUpperCase, locale);
             mLabel = toUpperCaseOfStringForLocale(getLabel(moreKeySpec),
                     needsToUpperCase, locale);
-            mOutputText = toUpperCaseOfStringForLocale(getOutputText(moreKeySpec),
+            final int code = toUpperCaseOfCodeForLocale(getCode(moreKeySpec, codesSet),
                     needsToUpperCase, locale);
+            if (code == Keyboard.CODE_UNSPECIFIED) {
+                // Some letter, for example German Eszett (U+00DF: "ß"), has multiple characters
+                // upper case representation ("SS").
+                mCode = Keyboard.CODE_OUTPUT_TEXT;
+                mOutputText = mLabel;
+            } else {
+                mCode = code;
+                mOutputText = toUpperCaseOfStringForLocale(getOutputText(moreKeySpec),
+                        needsToUpperCase, locale);
+            }
             mIconId = getIconId(moreKeySpec);
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 11b4bb1..a2b33e1 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -208,13 +208,13 @@
             final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher;
             switch (msg.what) {
             case MSG_UPDATE_SUGGESTIONS:
-                latinIme.updateSuggestions();
+                latinIme.updateSuggestionsOrPredictions(false /* isPredictions */);
                 break;
             case MSG_UPDATE_SHIFT_STATE:
                 switcher.updateShiftState();
                 break;
             case MSG_SET_BIGRAM_PREDICTIONS:
-                latinIme.updateBigramPredictions();
+                latinIme.updateSuggestionsOrPredictions(true /* isPredictions */);
                 break;
             }
         }
@@ -1003,7 +1003,7 @@
     // the composing word, reset the last composed word, tell the inputconnection about it.
     private void resetEntireInputState() {
         resetComposingState(true /* alsoResetLastComposedWord */);
-        updateSuggestions();
+        updateSuggestionsOrPredictions(false /* isPredictions */);
         mConnection.finishComposingText();
     }
 
@@ -1026,7 +1026,7 @@
                     LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(),
                     separatorCode, prevWord);
         }
-        updateSuggestions();
+        updateSuggestionsOrPredictions(false /* isPredictions */);
     }
 
     public int getCurrentAutoCapsState() {
@@ -1690,7 +1690,15 @@
         }
     }
 
-    public void updateSuggestions() {
+    public void updateSuggestionsOrPredictions(final boolean isPredictions) {
+        if (isPredictions) {
+            updateBigramPredictions();
+        } else {
+            updateSuggestions();
+        }
+    }
+
+    private void updateSuggestions() {
         mHandler.cancelUpdateSuggestions();
         mHandler.cancelUpdateBigramPredictions();
 
@@ -1771,7 +1779,7 @@
         // Complete any pending suggestions query first
         if (mHandler.hasPendingUpdateSuggestions()) {
             mHandler.cancelUpdateSuggestions();
-            updateSuggestions();
+            updateSuggestionsOrPredictions(false /* isPredictions */);
         }
         final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull();
         if (autoCorrection != null) {
@@ -1881,7 +1889,7 @@
         if (!showingAddToDictionaryHint) {
             // If we're not showing the "Touch again to save", then show corrections again.
             // In case the cursor position doesn't change, make sure we show the suggestions again.
-            updateBigramPredictions();
+            updateSuggestionsOrPredictions(true /* isPredictions */);
             // Updating the predictions right away may be slow and feel unresponsive on slower
             // terminals. On the other hand if we just postUpdateBigramPredictions() it will
             // take a noticeable delay to update them which may feel uneasy.