Revert "Remove symbols shifted layout related code"

This reverts commit 1cd027850bb07cd3fe2c1ec43b8a594d2f8ad313.

Bug: 9059539

Change-Id: I1880b799e2d0f148ae913f13cffa1b8cac48be60
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 631c35d..2a5334f 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -388,6 +388,7 @@
             <enum name="alphabetShiftLocked" value="3" />
             <enum name="alphabetShiftLockShifted" value="4" />
             <enum name="symbols" value="5" />
+            <enum name="symbolsShifted" value="6"  />
             <enum name="phone" value="7"  />
             <enum name="phoneSymbols" value="8"  />
             <enum name="number" value="9"  />
@@ -449,6 +450,7 @@
             <enum name="alphabetShiftLocked" value="3" />
             <enum name="alphabetShiftLockShifted" value="4" />
             <enum name="symbols" value="5" />
+            <enum name="symbolsShifted" value="6"  />
             <enum name="phone" value="7"  />
             <enum name="phoneSymbols" value="8"  />
             <enum name="number" value="9"  />
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index b3bb767..73896df 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -357,6 +357,7 @@
             break;
         case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
         case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
+        case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
             text = context.getText(R.string.spoken_description_shiftmode_on);
             break;
         default:
@@ -388,6 +389,7 @@
             resId = R.string.spoken_description_mode_alpha;
             break;
         case KeyboardId.ELEMENT_SYMBOLS:
+        case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
             resId = R.string.spoken_description_mode_symbol;
             break;
         case KeyboardId.ELEMENT_PHONE:
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index 085ca93..58624a2 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -156,6 +156,7 @@
             resId = R.string.spoken_description_to_symbol;
             break;
         case KeyboardId.ELEMENT_SYMBOLS:
+        case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
             resId = R.string.spoken_description_to_alpha;
             break;
         case KeyboardId.ELEMENT_PHONE:
@@ -190,6 +191,7 @@
             break;
         case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
         case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
+        case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
             resId = R.string.spoken_description_shift_shifted;
             break;
         default:
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index 53748bb..736f13e 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -50,6 +50,7 @@
     public static final int ELEMENT_ALPHABET_SHIFT_LOCKED = 3;
     public static final int ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED = 4;
     public static final int ELEMENT_SYMBOLS = 5;
+    public static final int ELEMENT_SYMBOLS_SHIFTED = 6;
     public static final int ELEMENT_PHONE = 7;
     public static final int ELEMENT_PHONE_SYMBOLS = 8;
     public static final int ELEMENT_NUMBER = 9;
@@ -219,6 +220,7 @@
         case ELEMENT_ALPHABET_SHIFT_LOCKED: return "alphabetShiftLocked";
         case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: return "alphabetShiftLockShifted";
         case ELEMENT_SYMBOLS: return "symbols";
+        case ELEMENT_SYMBOLS_SHIFTED: return "symbolsShifted";
         case ELEMENT_PHONE: return "phone";
         case ELEMENT_PHONE_SYMBOLS: return "phoneSymbols";
         case ELEMENT_NUMBER: return "number";
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index c319c57..4569d31 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -271,6 +271,12 @@
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
+    public void setSymbolsShiftedKeyboard() {
+        setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS_SHIFTED));
+    }
+
+    // Implements {@link KeyboardState.SwitchActions}.
+    @Override
     public void requestUpdatingShiftState() {
         mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState(),
                 mLatinIME.getCurrentRecapitalizeState());
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 089db12..710eed9 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -47,6 +47,7 @@
         public void setAlphabetShiftLockShiftedKeyboard();
         public void setSymbolsKeyboard();
         public void setEmojiKeyboard();
+        public void setSymbolsShiftedKeyboard();
 
         /**
          * Request to call back {@link KeyboardState#onUpdateShiftState(int, int)}.
@@ -64,11 +65,13 @@
     private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
 
     // TODO: Merge {@link #mSwitchState}, {@link #mIsAlphabetMode}, {@link #mAlphabetShiftState},
-    // {@link #mPrevMainKeyboardWasShiftLocked} into single state variable.
+    // {@link #mIsSymbolShifted}, {@link #mPrevMainKeyboardWasShiftLocked}, and
+    // {@link #mPrevSymbolsKeyboardWasShifted} into single state variable.
     private static final int SWITCH_STATE_ALPHA = 0;
     private static final int SWITCH_STATE_SYMBOL_BEGIN = 1;
     private static final int SWITCH_STATE_SYMBOL = 2;
     private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3;
+    private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4;
     private static final int SWITCH_STATE_MOMENTARY_ALPHA_SHIFT = 5;
     private int mSwitchState = SWITCH_STATE_ALPHA;
 
@@ -77,7 +80,9 @@
     private boolean mIsAlphabetMode;
     private boolean mIsEmojiMode;
     private AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState();
+    private boolean mIsSymbolShifted;
     private boolean mPrevMainKeyboardWasShiftLocked;
+    private boolean mPrevSymbolsKeyboardWasShifted;
     private int mRecapitalizeMode;
 
     // For handling double tap.
@@ -102,7 +107,7 @@
             } else if (mIsEmojiMode) {
                 return "EMOJI";
             } else {
-                return "SYMBOLS";
+                return "SYMBOLS_" + shiftModeToString(mShiftMode);
             }
         }
     }
@@ -119,6 +124,7 @@
         // Reset alphabet shift state.
         mAlphabetShiftState.setShiftLocked(false);
         mPrevMainKeyboardWasShiftLocked = false;
+        mPrevSymbolsKeyboardWasShifted = false;
         mShiftKeyState.onRelease();
         mSymbolKeyState.onRelease();
         onRestoreKeyboardState();
@@ -139,6 +145,7 @@
                     : (mAlphabetShiftState.isShiftedOrShiftLocked() ? MANUAL_SHIFT : UNSHIFT);
         } else {
             state.mIsAlphabetShiftLocked = mPrevMainKeyboardWasShiftLocked;
+            state.mShiftMode = mIsSymbolShifted ? MANUAL_SHIFT : UNSHIFT;
         }
         state.mIsValid = true;
         if (DEBUG_EVENT) {
@@ -156,7 +163,11 @@
         } else if (state.mIsEmojiMode) {
             setEmojiKeyboard();
         } else {
-            setSymbolsKeyboard();
+            if (state.mShiftMode == MANUAL_SHIFT) {
+                setSymbolsShiftedKeyboard();
+            } else {
+                setSymbolsKeyboard();
+            }
         }
 
         if (!state.mIsValid) return;
@@ -232,8 +243,14 @@
         }
         if (mIsAlphabetMode) {
             mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked();
-            setSymbolsKeyboard();
+            if (mPrevSymbolsKeyboardWasShifted) {
+                setSymbolsShiftedKeyboard();
+            } else {
+                setSymbolsKeyboard();
+            }
+            mPrevSymbolsKeyboardWasShifted = false;
         } else {
+            mPrevSymbolsKeyboardWasShifted = mIsSymbolShifted;
             setAlphabetKeyboard();
             if (mPrevMainKeyboardWasShiftLocked) {
                 setShiftLocked(true);
@@ -250,6 +267,7 @@
         }
         if (mIsAlphabetMode) return;
 
+        mPrevSymbolsKeyboardWasShifted = mIsSymbolShifted;
         setAlphabetKeyboard();
         if (mPrevMainKeyboardWasShiftLocked) {
             setShiftLocked(true);
@@ -257,6 +275,14 @@
         mPrevMainKeyboardWasShiftLocked = false;
     }
 
+    private void toggleShiftInSymbols() {
+        if (mIsSymbolShifted) {
+            setSymbolsKeyboard();
+        } else {
+            setSymbolsShiftedKeyboard();
+        }
+    }
+
     private void setAlphabetKeyboard() {
         if (DEBUG_ACTION) {
             Log.d(TAG, "setAlphabetKeyboard");
@@ -265,6 +291,7 @@
         mSwitchActions.setAlphabetKeyboard();
         mIsAlphabetMode = true;
         mIsEmojiMode = false;
+        mIsSymbolShifted = false;
         mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE;
         mSwitchState = SWITCH_STATE_ALPHA;
         mSwitchActions.requestUpdatingShiftState();
@@ -276,6 +303,19 @@
         }
         mSwitchActions.setSymbolsKeyboard();
         mIsAlphabetMode = false;
+        mIsSymbolShifted = false;
+        // Reset alphabet shift state.
+        mAlphabetShiftState.setShiftLocked(false);
+        mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
+    }
+
+    private void setSymbolsShiftedKeyboard() {
+        if (DEBUG_ACTION) {
+            Log.d(TAG, "setSymbolsShiftedKeyboard");
+        }
+        mSwitchActions.setSymbolsShiftedKeyboard();
+        mIsAlphabetMode = false;
+        mIsSymbolShifted = true;
         // Reset alphabet shift state.
         mAlphabetShiftState.setShiftLocked(false);
         mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
@@ -337,7 +377,7 @@
         } else if (code == Constants.CODE_CAPSLOCK) {
             setShiftLocked(!mAlphabetShiftState.isShiftLocked());
         } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) {
-            onReleaseSymbol();
+            onReleaseSymbol(withSliding);
         }
     }
 
@@ -347,11 +387,16 @@
         mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL;
     }
 
-    private void onReleaseSymbol() {
+    private void onReleaseSymbol(final boolean withSliding) {
         if (mSymbolKeyState.isChording()) {
             // Switch back to the previous keyboard mode if the user chords the mode change key and
             // another key, then releases the mode change key.
             toggleAlphabetAndSymbols();
+        } else if (!withSliding) {
+            // If the mode change key is being released without sliding, we should forget the
+            // previous symbols keyboard shift state and simply switch back to symbols layout
+            // (never symbols shifted) next time the mode gets changed to symbols layout.
+            mPrevSymbolsKeyboardWasShifted = false;
         }
         mSymbolKeyState.onRelease();
     }
@@ -417,43 +462,48 @@
         if (RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE != mRecapitalizeMode) {
             return;
         }
-        if (!mIsAlphabetMode) {
-            // There is no shift key on symbols keyboard.
-            return;
-        }
-        mIsInDoubleTapShiftKey = mSwitchActions.isInDoubleTapShiftKeyTimeout();
-        if (!mIsInDoubleTapShiftKey) {
-            // This is first tap.
-            mSwitchActions.startDoubleTapShiftKeyTimer();
-        }
-        if (mIsInDoubleTapShiftKey) {
-            if (mAlphabetShiftState.isManualShifted() || mIsInAlphabetUnshiftedFromShifted) {
-                // Shift key has been double tapped while in manual shifted or automatic
-                // shifted state.
-                setShiftLocked(true);
+        if (mIsAlphabetMode) {
+            mIsInDoubleTapShiftKey = mSwitchActions.isInDoubleTapShiftKeyTimeout();
+            if (!mIsInDoubleTapShiftKey) {
+                // This is first tap.
+                mSwitchActions.startDoubleTapShiftKeyTimer();
+            }
+            if (mIsInDoubleTapShiftKey) {
+                if (mAlphabetShiftState.isManualShifted() || mIsInAlphabetUnshiftedFromShifted) {
+                    // Shift key has been double tapped while in manual shifted or automatic
+                    // shifted state.
+                    setShiftLocked(true);
+                } else {
+                    // Shift key has been double tapped while in normal state. This is the second
+                    // tap to disable shift locked state, so just ignore this.
+                }
             } else {
-                // Shift key has been double tapped while in normal state. This is the second
-                // tap to disable shift locked state, so just ignore this.
+                if (mAlphabetShiftState.isShiftLocked()) {
+                    // Shift key is pressed while shift locked state, we will treat this state as
+                    // shift lock shifted state and mark as if shift key pressed while normal
+                    // state.
+                    setShifted(SHIFT_LOCK_SHIFTED);
+                    mShiftKeyState.onPress();
+                } else if (mAlphabetShiftState.isAutomaticShifted()) {
+                    // Shift key is pressed while automatic shifted, we have to move to manual
+                    // shifted.
+                    setShifted(MANUAL_SHIFT);
+                    mShiftKeyState.onPress();
+                } else if (mAlphabetShiftState.isShiftedOrShiftLocked()) {
+                    // In manual shifted state, we just record shift key has been pressing while
+                    // shifted state.
+                    mShiftKeyState.onPressOnShifted();
+                } else {
+                    // In base layout, chording or manual shifted mode is started.
+                    setShifted(MANUAL_SHIFT);
+                    mShiftKeyState.onPress();
+                }
             }
         } else {
-            if (mAlphabetShiftState.isShiftLocked()) {
-                // Shift key is pressed while shift locked state, we will treat this state as
-                // shift lock shifted state and mark as if shift key pressed while normal state.
-                setShifted(SHIFT_LOCK_SHIFTED);
-                mShiftKeyState.onPress();
-            } else if (mAlphabetShiftState.isAutomaticShifted()) {
-                // Shift key is pressed while automatic shifted, we have to move to manual shifted.
-                setShifted(MANUAL_SHIFT);
-                mShiftKeyState.onPress();
-            } else if (mAlphabetShiftState.isShiftedOrShiftLocked()) {
-                // In manual shifted state, we just record shift key has been pressing while
-                // shifted state.
-                mShiftKeyState.onPressOnShifted();
-            } else {
-                // In base layout, chording or manual shifted mode is started.
-                setShifted(MANUAL_SHIFT);
-                mShiftKeyState.onPress();
-            }
+            // In symbol mode, just toggle symbol and symbol more keyboard.
+            toggleShiftInSymbols();
+            mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
+            mShiftKeyState.onPress();
         }
     }
 
@@ -508,7 +558,11 @@
                 mIsInAlphabetUnshiftedFromShifted = true;
             }
         } else {
-            // There is no shift key on symbols keyboard.
+            // In symbol mode, switch back to the previous keyboard mode if the user chords the
+            // shift key and another key, then releases the shift key.
+            if (mShiftKeyState.isChording()) {
+                toggleShiftInSymbols();
+            }
         }
         mShiftKeyState.onRelease();
     }
@@ -522,6 +576,9 @@
         case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL:
             toggleAlphabetAndSymbols();
             break;
+        case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE:
+            toggleShiftInSymbols();
+            break;
         case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT:
             setAlphabetKeyboard();
             break;
@@ -549,6 +606,13 @@
                 }
             }
             break;
+        case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE:
+            if (code == Constants.CODE_SHIFT) {
+                // Detected only the shift key has been pressed on symbol layout, and then
+                // released.
+                mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
+            }
+            break;
         case SWITCH_STATE_SYMBOL_BEGIN:
             if (!isSpaceCharacter(code) && (Constants.isLetterCode(code)
                     || code == Constants.CODE_OUTPUT_TEXT)) {
@@ -560,6 +624,7 @@
             // characters followed by a space/enter.
             if (isSpaceCharacter(code)) {
                 toggleAlphabetAndSymbols();
+                mPrevSymbolsKeyboardWasShifted = false;
             }
             break;
         }
@@ -587,6 +652,7 @@
         case SWITCH_STATE_SYMBOL_BEGIN: return "SYMBOL-BEGIN";
         case SWITCH_STATE_SYMBOL: return "SYMBOL";
         case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: return "MOMENTARY-ALPHA-SYMBOL";
+        case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: return "MOMENTARY-SYMBOL-MORE";
         case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT: return "MOMENTARY-ALPHA_SHIFT";
         default: return null;
         }
@@ -594,7 +660,8 @@
 
     @Override
     public String toString() {
-        return "[keyboard=" + (mIsAlphabetMode ? mAlphabetShiftState.toString() : "SYMBOLS")
+        return "[keyboard=" + (mIsAlphabetMode ? mAlphabetShiftState.toString()
+                : (mIsSymbolShifted ? "SYMBOLS_SHIFTED" : "SYMBOLS"))
                 + " shift=" + mShiftKeyState
                 + " symbol=" + mSymbolKeyState
                 + " switch=" + switchStateToString(mSwitchState) + "]";