Auto generate various shift states alphabet keyboard automatically

If any shift state variants of alphabet keyboard layout is not
specified in KeyboardSet.Element, it will be automatically generated
from base alphabet keyboard definition.

This change also
  * Eliminates KeyboardShiftState object from Keyboard.
  * Removes various set shift state methods from Keyboard.
  * Removes KeyboardSet.Element.elementAutoGenerate attribute.
  * Separates "sticky" Key.backgroundType to "stickyOff" and "stickyOn"
  * Add preserveCase flag to smiley, .com, and labeled special keys.
  * Rename KeyboardShiftState class to AlphabetShiftState.
  * Rename some attributes from *UppercaseLetter* to *ShiftedLetterHint*.
  * Introduce shiftedLetterActivated to Key.keyLabelFlags

Change-Id: I01a0a8efeeaa76820ae728a5bdfa8d02b6ce74b7
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 8d00f7a..a5bf6f6 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -60,16 +60,16 @@
         <attr name="keyHintLetterRatio" format="float" />
         <!-- Size of the text for hint label, in the proportion of key height. -->
         <attr name="keyHintLabelRatio" format="float" />
-        <!-- Size of the text for upper case letter, in the proportion of key height. -->
-        <attr name="keyUppercaseLetterRatio" format="float" />
+        <!-- Size of the text for shifted letter hint, in the proportion of key height. -->
+        <attr name="keyShiftedLetterHintRatio" format="float" />
         <!-- Horizontal padding of left/right aligned key label to the edge of the key. -->
         <attr name="keyLabelHorizontalPadding" format="dimension" />
         <!-- Top and right padding of hint letter to the edge of the key.-->
         <attr name="keyHintLetterPadding" format="dimension" />
         <!-- Bottom padding of popup hint letter "..." to the edge of the key.-->
         <attr name="keyPopupHintLetterPadding" format="dimension" />
-        <!-- Top and right padding of upper case letter to the edge of the key.-->
-        <attr name="keyUppercaseLetterPadding" format="dimension" />
+        <!-- Top and right padding of shifted letter hint to the edge of the key.-->
+        <attr name="keyShiftedLetterHintPadding" format="dimension" />
 
         <!-- Color to use for the label in a key. -->
         <attr name="keyTextColor" format="color" />
@@ -79,9 +79,9 @@
         <attr name="keyHintLetterColor" format="color" />
         <!-- Key hint label color -->
         <attr name="keyHintLabelColor" format="color" />
-        <!-- Upper case letter colors -->
-        <attr name="keyUppercaseLetterInactivatedColor" format="color" />
-        <attr name="keyUppercaseLetterActivatedColor" format="color" />
+        <!-- Shifted letter hint colors -->
+        <attr name="keyShiftedLetterHintInactivatedColor" format="color" />
+        <attr name="keyShiftedLetterHintActivatedColor" format="color" />
 
         <!-- Layout resource for key press feedback.-->
         <attr name="keyPreviewLayout" format="reference" />
@@ -240,7 +240,8 @@
             <enum name="normal" value="0" />
             <enum name="functional" value="1" />
             <enum name="action" value="2" />
-            <enum name="sticky" value="3" />
+            <enum name="stickyOff" value="3" />
+            <enum name="stickyOn" value="4" />
         </attr>
         <!-- The key action flags. -->
         <attr name="keyActionFlags" format="integer">
@@ -267,7 +268,7 @@
             <flag name="followKeyLetterRatio" value="0x80" />
             <flag name="followKeyHintLabelRatio" value="0x100" />
             <flag name="hasPopupHint" value="0x200" />
-            <flag name="hasUppercaseLetter" value="0x400" />
+            <flag name="hasShiftedLetterHint" value="0x400" />
             <flag name="hasHintLabel" value="0x800" />
             <flag name="withIconLeft" value="0x1000" />
             <flag name="withIconRight" value="0x2000" />
@@ -275,10 +276,9 @@
             <!-- If true, character case of code, altCode, moreKeys, keyOutputText, keyLabel,
                  or keyHintLabel will never be subject to change. -->
             <flag name="preserveCase" value="0x8000" />
-            <!-- If true, use keyTextInactivatedColor for the label -->
-            <flag name="inactivatedLabel" value="0x10000" />
-            <!-- If true, use keyUppercaseLetterInactivatedColor for the uppercase letter -->
-            <flag name="inactivatedUppercaseLetter" value="0x20000" />
+            <!-- If true, use keyShiftedLetterHintActivatedColor for the shifted letter hint and
+                 keyTextInactivatedColor for the primary key top label. -->
+            <flag name="shiftedLetterActivated" value="0x10000" />
         </attr>
         <!-- The icon to display on the key instead of the label. -->
         <attr name="keyIcon" format="enum">
@@ -407,7 +407,5 @@
             <enum name="number" value="9"  />
         </attr>
         <attr name="elementKeyboard" format="reference"/>
-        <attr name="elementAutoGenerate" format="boolean" />
-        <!-- TODO: Add setShifted and setShiftLocked attribute. -->
     </declare-styleable>
 </resources>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index 69637d7..f690782 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -39,18 +39,18 @@
         <item name="keyLabelRatio">@fraction/key_label_ratio</item>
         <item name="keyHintLetterRatio">@fraction/key_hint_letter_ratio</item>
         <item name="keyHintLabelRatio">@fraction/key_hint_label_ratio</item>
-        <item name="keyUppercaseLetterRatio">@fraction/key_uppercase_letter_ratio</item>
+        <item name="keyShiftedLetterHintRatio">@fraction/key_uppercase_letter_ratio</item>
         <item name="keyTextStyle">normal</item>
         <item name="keyTextColor">#FFFFFFFF</item>
         <item name="keyTextInactivatedColor">#FFFFFFFF</item>
         <item name="keyHintLetterColor">#80000000</item>
         <item name="keyHintLabelColor">#E0E0E4E5</item>
-        <item name="keyUppercaseLetterInactivatedColor">#66E0E4E5</item>
-        <item name="keyUppercaseLetterActivatedColor">#CCE0E4E5</item>
+        <item name="keyShiftedLetterHintInactivatedColor">#66E0E4E5</item>
+        <item name="keyShiftedLetterHintActivatedColor">#CCE0E4E5</item>
         <item name="keyLabelHorizontalPadding">@dimen/key_label_horizontal_padding</item>
         <item name="keyHintLetterPadding">@dimen/key_hint_letter_padding</item>
         <item name="keyPopupHintLetterPadding">@dimen/key_popup_hint_letter_padding</item>
-        <item name="keyUppercaseLetterPadding">@dimen/key_uppercase_letter_padding</item>
+        <item name="keyShiftedLetterHintPadding">@dimen/key_uppercase_letter_padding</item>
         <item name="keyPreviewLayout">@layout/key_preview</item>
         <item name="keyPreviewBackground">@drawable/keyboard_key_feedback</item>
         <item name="keyPreviewLeftBackground">@null</item>
@@ -181,8 +181,8 @@
         <item name="keyTextInactivatedColor">#FF808080</item>
         <item name="keyHintLetterColor">#80000000</item>
         <item name="keyHintLabelColor">#E0000000</item>
-        <item name="keyUppercaseLetterInactivatedColor">#66000000</item>
-        <item name="keyUppercaseLetterActivatedColor">#CC000000</item>
+        <item name="keyShiftedLetterHintInactivatedColor">#66000000</item>
+        <item name="keyShiftedLetterHintActivatedColor">#CC000000</item>
         <item name="shadowColor">#FFFFFFFF</item>
     </style>
     <style
@@ -298,8 +298,8 @@
         <item name="keyTextInactivatedColor">#66E0E4E5</item>
         <item name="keyHintLetterColor">#80000000</item>
         <item name="keyHintLabelColor">#A0FFFFFF</item>
-        <item name="keyUppercaseLetterInactivatedColor">#66E0E4E5</item>
-        <item name="keyUppercaseLetterActivatedColor">#FFFFFFFF</item>
+        <item name="keyShiftedLetterHintInactivatedColor">#66E0E4E5</item>
+        <item name="keyShiftedLetterHintActivatedColor">#FFFFFFFF</item>
         <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_ics</item>
         <item name="keyPreviewLeftBackground">@drawable/keyboard_key_feedback_left_ics</item>
         <item name="keyPreviewRightBackground">@drawable/keyboard_key_feedback_right_ics</item>
diff --git a/java/res/xml-sw600dp/key_smiley.xml b/java/res/xml-sw600dp/key_smiley.xml
index ee23a81..3430d78 100644
--- a/java/res/xml-sw600dp/key_smiley.xml
+++ b/java/res/xml-sw600dp/key_smiley.xml
@@ -33,18 +33,18 @@
         >
             <Key
                 latin:keyLabel="-"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="_"
-                latin:moreKeys="_" />
+                latin:moreKeys="_"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </case>
         <case
             latin:imeAction="actionSearch"
         >
             <Key
                 latin:keyLabel=":"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="+"
-                latin:moreKeys="+" />
+                latin:moreKeys="+"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </case>
         <default>
             <Key
diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml
index abba592..b554147 100644
--- a/java/res/xml-sw600dp/key_styles_common.xml
+++ b/java/res/xml-sw600dp/key_styles_common.xml
@@ -38,13 +38,51 @@
                 latin:backgroundType="functional" />
         </default>
     </switch>
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="hasShiftedLetterHintStyle"
+                latin:keyLabelFlags="hasShiftedLetterHint|shiftedLetterActivated" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="hasShiftedLetterHintStyle"
+                latin:keyLabelFlags="hasShiftedLetterHint" />
+        </default>
+    </switch>
     <!-- Functional key styles -->
-    <key-style
-        latin:styleName="shiftKeyStyle"
-        latin:code="@integer/key_shift"
-        latin:keyIcon="iconShiftKey"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="sticky" />
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetAutomaticShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </case>
+        <case
+            latin:keyboardSetElement="alphabetShiftLocked|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOn" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKey"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </default>
+    </switch>
     <key-style
         latin:styleName="deleteKeyStyle"
         latin:code="@integer/key_delete"
@@ -69,7 +107,7 @@
         latin:styleName="smileyKeyStyle"
         latin:keyLabel=":-)"
         latin:keyOutputText=":-) "
-        latin:keyLabelFlags="hasPopupHint"
+        latin:keyLabelFlags="hasPopupHint|preserveCase"
         latin:moreKeys="@string/more_keys_for_smiley"
         latin:maxMoreKeysColumn="5" />
     <key-style
@@ -95,30 +133,34 @@
         latin:styleName="toSymbolKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_symbol_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toAlphaKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_alpha_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_more_symbol_for_tablet_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="backFromMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_symbol_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="comKeyStyle"
         latin:keyLabel="@string/keylabel_for_popular_domain"
-        latin:keyLabelFlags="fontNormal|hasPopupHint"
+        latin:keyLabelFlags="fontNormal|hasPopupHint|preserveCase"
         latin:keyOutputText="@string/keylabel_for_popular_domain"
         latin:moreKeys="@string/more_keys_for_popular_domain" />
 </merge>
diff --git a/java/res/xml-sw600dp/keys_apostrophe_dash.xml b/java/res/xml-sw600dp/keys_apostrophe_dash.xml
index 4eb82d2..a53c1e4 100644
--- a/java/res/xml-sw600dp/keys_apostrophe_dash.xml
+++ b/java/res/xml-sw600dp/keys_apostrophe_dash.xml
@@ -33,16 +33,16 @@
         >
             <Key
                 latin:keyLabel="/"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel=":"
-                latin:moreKeys=":" />
+                latin:moreKeys=":"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </case>
         <default>
             <Key
                 latin:keyLabel="@string/keylabel_for_apostrophe"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="@string/keyhintlabel_for_apostrophe"
-                latin:moreKeys="@string/more_keys_for_apostrophe" />
+                latin:moreKeys="@string/more_keys_for_apostrophe"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </default>
     </switch>
     <switch>
@@ -55,9 +55,9 @@
         <default>
             <Key
                 latin:keyLabel="@string/keylabel_for_dash"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="@string/keyhintlabel_for_dash"
-                latin:moreKeys="@string/more_keys_for_dash" />
+                latin:moreKeys="@string/more_keys_for_dash"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </default>
     </switch>
 </merge>
diff --git a/java/res/xml-sw600dp/row_qwerty4.xml b/java/res/xml-sw600dp/row_qwerty4.xml
index bf6bcb1..b06508e 100644
--- a/java/res/xml-sw600dp/row_qwerty4.xml
+++ b/java/res/xml-sw600dp/row_qwerty4.xml
@@ -45,9 +45,9 @@
             <default>
                 <Key
                     latin:keyLabel="/"
-                    latin:keyLabelFlags="hasUppercaseLetter"
                     latin:keyHintLabel="\@"
-                    latin:moreKeys="\@" />
+                    latin:moreKeys="\@"
+                    latin:keyStyle="hasShiftedLetterHintStyle" />
             </default>
         </switch>
         <Key
diff --git a/java/res/xml-sw768dp/key_styles_common.xml b/java/res/xml-sw768dp/key_styles_common.xml
index 72a1a4c..0d2ac5d 100644
--- a/java/res/xml-sw768dp/key_styles_common.xml
+++ b/java/res/xml-sw768dp/key_styles_common.xml
@@ -21,12 +21,50 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <key-style
-        latin:styleName="shiftKeyStyle"
-        latin:code="@integer/key_shift"
-        latin:keyIcon="iconShiftKey"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="sticky" />
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="hasShiftedLetterHintStyle"
+                latin:keyLabelFlags="hasShiftedLetterHint|shiftedLetterActivated" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="hasShiftedLetterHintStyle"
+                latin:keyLabelFlags="hasShiftedLetterHint" />
+        </default>
+    </switch>
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetAutomaticShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </case>
+        <case
+            latin:keyboardSetElement="alphabetShiftLocked|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOn" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKey"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </default>
+    </switch>
     <key-style
         latin:styleName="deleteKeyStyle"
         latin:code="@integer/key_delete"
@@ -51,7 +89,7 @@
         latin:styleName="smileyKeyStyle"
         latin:keyLabel=":-)"
         latin:keyOutputText=":-) "
-        latin:keyLabelFlags="hasPopupHint"
+        latin:keyLabelFlags="hasPopupHint|preserveCase"
         latin:moreKeys="@string/more_keys_for_smiley"
         latin:maxMoreKeysColumn="5" />
     <key-style
@@ -71,40 +109,40 @@
         latin:styleName="tabKeyStyle"
         latin:code="@integer/key_tab"
         latin:keyLabel="@string/label_tab_key"
-        latin:keyLabelFlags="fontNormal"
+        latin:keyLabelFlags="fontNormal|preserveCase"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toSymbolKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_symbol_key"
-        latin:keyLabelFlags="fontNormal"
+        latin:keyLabelFlags="fontNormal|preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toAlphaKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_alpha_key"
-        latin:keyLabelFlags="fontNormal"
+        latin:keyLabelFlags="fontNormal|preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_more_symbol_for_tablet_key"
-        latin:keyLabelFlags="fontNormal"
+        latin:keyLabelFlags="fontNormal|preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="backFromMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_symbol_key"
-        latin:keyLabelFlags="fontNormal"
+        latin:keyLabelFlags="fontNormal|preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="comKeyStyle"
         latin:keyLabel="@string/keylabel_for_popular_domain"
-        latin:keyLabelFlags="fontNormal|hasPopupHint"
+        latin:keyLabelFlags="fontNormal|hasPopupHint|preserveCase"
         latin:keyOutputText="@string/keylabel_for_popular_domain"
         latin:moreKeys="@string/more_keys_for_popular_domain" />
 </merge>
diff --git a/java/res/xml-sw768dp/keys_apostrophe_dash.xml b/java/res/xml-sw768dp/keys_apostrophe_dash.xml
index 4eb82d2..a53c1e4 100644
--- a/java/res/xml-sw768dp/keys_apostrophe_dash.xml
+++ b/java/res/xml-sw768dp/keys_apostrophe_dash.xml
@@ -33,16 +33,16 @@
         >
             <Key
                 latin:keyLabel="/"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel=":"
-                latin:moreKeys=":" />
+                latin:moreKeys=":"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </case>
         <default>
             <Key
                 latin:keyLabel="@string/keylabel_for_apostrophe"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="@string/keyhintlabel_for_apostrophe"
-                latin:moreKeys="@string/more_keys_for_apostrophe" />
+                latin:moreKeys="@string/more_keys_for_apostrophe"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </default>
     </switch>
     <switch>
@@ -55,9 +55,9 @@
         <default>
             <Key
                 latin:keyLabel="@string/keylabel_for_dash"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="@string/keyhintlabel_for_dash"
-                latin:moreKeys="@string/more_keys_for_dash" />
+                latin:moreKeys="@string/more_keys_for_dash"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </default>
     </switch>
 </merge>
diff --git a/java/res/xml-sw768dp/row_qwerty4.xml b/java/res/xml-sw768dp/row_qwerty4.xml
index c3ba911..84c4a37 100644
--- a/java/res/xml-sw768dp/row_qwerty4.xml
+++ b/java/res/xml-sw768dp/row_qwerty4.xml
@@ -57,9 +57,9 @@
                     >
                         <Key
                             latin:keyLabel=":"
-                            latin:keyLabelFlags="hasUppercaseLetter"
                             latin:keyHintLabel="+"
-                            latin:moreKeys="+" />
+                            latin:moreKeys="+"
+                            latin:keyStyle="hasShiftedLetterHintStyle" />
                     </case>
                     <default>
                         <Key
@@ -76,9 +76,9 @@
                     <default>
                         <Key
                             latin:keyLabel="/"
-                            latin:keyLabelFlags="hasUppercaseLetter"
                             latin:keyHintLabel="\@"
-                            latin:moreKeys="\@" />
+                            latin:moreKeys="\@"
+                            latin:keyStyle="hasShiftedLetterHintStyle" />
                     </default>
                 </switch>
             </default>
diff --git a/java/res/xml-sw768dp/rows_azerty.xml b/java/res/xml-sw768dp/rows_azerty.xml
index 066778c..886ebec 100644
--- a/java/res/xml-sw768dp/rows_azerty.xml
+++ b/java/res/xml-sw768dp/rows_azerty.xml
@@ -124,7 +124,7 @@
             latin:moreKeys="@string/more_keys_for_n" />
         <Key
             latin:keyLabel="\'"
-            latin:keyLabelFlags="hasUppercaseLetter"
+            latin:keyLabelFlags="hasShiftedLetterHint"
             latin:keyHintLabel=":"
             latin:moreKeys=":" />
         <include
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
index 7869d21..8d01e0f 100644
--- a/java/res/xml/key_styles_common.xml
+++ b/java/res/xml/key_styles_common.xml
@@ -62,12 +62,36 @@
         </default>
     </switch>
     <!-- Functional key styles -->
-    <key-style
-        latin:styleName="shiftKeyStyle"
-        latin:code="@integer/key_shift"
-        latin:keyIcon="iconShiftKey"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="sticky" />
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetAutomaticShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </case>
+        <case
+            latin:keyboardSetElement="alphabetShiftLocked|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOn" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKey"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </default>
+    </switch>
     <key-style
         latin:styleName="deleteKeyStyle"
         latin:code="@integer/key_delete"
@@ -84,7 +108,7 @@
                 latin:styleName="returnKeyStyle"
                 latin:keyLabel=":-)"
                 latin:keyOutputText=":-) "
-                latin:keyLabelFlags="hasPopupHint"
+                latin:keyLabelFlags="hasPopupHint|preserveCase"
                 latin:moreKeys="@string/more_keys_for_smiley"
                 latin:maxMoreKeysColumn="5"
                 latin:backgroundType="functional" />
@@ -96,7 +120,7 @@
                 latin:styleName="returnKeyStyle"
                 latin:code="@integer/key_return"
                 latin:keyLabel="@string/label_go_key"
-                latin:keyLabelFlags="autoXScale"
+                latin:keyLabelFlags="autoXScale|preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="action" />
         </case>
@@ -107,7 +131,7 @@
                 latin:styleName="returnKeyStyle"
                 latin:code="@integer/key_return"
                 latin:keyLabel="@string/label_next_key"
-                latin:keyLabelFlags="autoXScale"
+                latin:keyLabelFlags="autoXScale|preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="action" />
         </case>
@@ -118,7 +142,7 @@
                 latin:styleName="returnKeyStyle"
                 latin:code="@integer/key_return"
                 latin:keyLabel="@string/label_done_key"
-                latin:keyLabelFlags="autoXScale"
+                latin:keyLabelFlags="autoXScale|preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="action" />
         </case>
@@ -129,7 +153,7 @@
                 latin:styleName="returnKeyStyle"
                 latin:code="@integer/key_return"
                 latin:keyLabel="@string/label_send_key"
-                latin:keyLabelFlags="autoXScale"
+                latin:keyLabelFlags="autoXScale|preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="action" />
         </case>
@@ -199,7 +223,7 @@
                 latin:code="@integer/key_switch_alpha_symbol"
                 latin:keyIcon="iconShortcutForLabel"
                 latin:keyLabel="@string/label_to_symbol_with_microphone_key"
-                latin:keyLabelFlags="withIconRight"
+                latin:keyLabelFlags="withIconRight|preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="functional" />
         </case>
@@ -208,6 +232,7 @@
                 latin:styleName="toSymbolKeyStyle"
                 latin:code="@integer/key_switch_alpha_symbol"
                 latin:keyLabel="@string/label_to_symbol_key"
+                latin:keyLabelFlags="preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="functional" />
         </default>
@@ -216,25 +241,28 @@
         latin:styleName="toAlphaKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_alpha_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_more_symbol_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="backFromMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_symbol_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="punctuationKeyStyle"
         latin:keyLabel="."
         latin:keyHintLabel="@string/keyhintlabel_for_punctuation"
-        latin:keyLabelFlags="hasPopupHint"
+        latin:keyLabelFlags="hasPopupHint|preserveCase"
         latin:moreKeys="@string/more_keys_for_punctuation"
         latin:maxMoreKeysColumn="@integer/mini_keyboard_column_for_punctuation"
         latin:backgroundType="functional" />
diff --git a/java/res/xml/keyboard_set.xml b/java/res/xml/keyboard_set.xml
index 27ef316..ebdd990 100644
--- a/java/res/xml/keyboard_set.xml
+++ b/java/res/xml/keyboard_set.xml
@@ -23,24 +23,7 @@
     latin:keyboardLocale="en_GB,en_US">
     <Element
         latin:elementName="alphabet"
-        latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:elementAutoGenerate="true" />
-    <Element
-        latin:elementName="alphabetManualShifted"
-        latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:elementAutoGenerate="true" />
-    <Element
-        latin:elementName="alphabetAutomaticShifted"
-        latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:elementAutoGenerate="true" />
-    <Element
-        latin:elementName="alphabetShiftLocked"
-        latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:elementAutoGenerate="true" />
-    <Element
-        latin:elementName="alphabetShiftLockShifted"
-        latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:elementAutoGenerate="true" />
+        latin:elementKeyboard="@xml/kbd_qwerty" />
     <Element
         latin:elementName="symbols"
         latin:elementKeyboard="@xml/kbd_symbols" />
diff --git a/java/res/xml/keys_comma_period.xml b/java/res/xml/keys_comma_period.xml
index 97d9738..6db02b6 100644
--- a/java/res/xml/keys_comma_period.xml
+++ b/java/res/xml/keys_comma_period.xml
@@ -33,14 +33,14 @@
         <default>
             <Key
                 latin:keyLabel=","
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="!"
-                latin:moreKeys="!" />
+                latin:moreKeys="!"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
             <Key
                 latin:keyLabel="."
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="\?"
-                latin:moreKeys="\?" />
+                latin:moreKeys="\?"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </default>
     </switch>
 </merge>
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index efaf58f..3b4149d 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -176,25 +176,6 @@
     }
 
     /**
-     * Returns the keycode for the specified key given the current keyboard
-     * state.
-     *
-     * @param keyboard The keyboard on which the key resides.
-     * @param key The key from which to obtain a key code.
-     * @return the key code for the specified key
-     */
-    private int getCorrectKeyCode(Keyboard keyboard, Key key) {
-        // If keyboard is in manual temporary upper case state and key has
-        // manual temporary uppercase letter as key hint letter, alternate
-        // character code should be sent.
-        if (keyboard.isManualTemporaryUpperCase() && key.hasUppercaseLetter()
-                && !TextUtils.isEmpty(key.mHintLabel)) {
-            return key.mHintLabel.charAt(0);
-        }
-        return key.mCode;
-    }
-
-    /**
      * Returns a localized character sequence describing what will happen when
      * the specified key is pressed based on its key code.
      * <p>
@@ -217,7 +198,7 @@
      */
     private CharSequence getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key,
             boolean shouldObscure) {
-        final int code = getCorrectKeyCode(keyboard, key);
+        final int code = key.mCode;
 
         if (keyboard.isShiftLocked() && mShiftLockedKeyCodeMap.containsKey(code)) {
             return context.getString(mShiftLockedKeyCodeMap.get(code));
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index a2d3796..d4419ae 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -66,14 +66,13 @@
     private static final int LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO = 0x80;
     private static final int LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO = 0x100;
     private static final int LABEL_FLAGS_HAS_POPUP_HINT = 0x200;
-    private static final int LABEL_FLAGS_HAS_UPPERCASE_LETTER = 0x400;
+    private static final int LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT = 0x400;
     private static final int LABEL_FLAGS_HAS_HINT_LABEL = 0x800;
     private static final int LABEL_FLAGS_WITH_ICON_LEFT = 0x1000;
     private static final int LABEL_FLAGS_WITH_ICON_RIGHT = 0x2000;
     private static final int LABEL_FLAGS_AUTO_X_SCALE = 0x4000;
     private static final int LABEL_FLAGS_PRESERVE_CASE = 0x8000;
-    private static final int LABEL_FLAGS_INACTIVATED_LABEL = 0x10000;
-    private static final int LABEL_FLAGS_INACTIVATED_UPPERCASE_LETTER = 0x20000;
+    private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x10000;
 
     /** Icon to display instead of a label. Icon takes precedence over a label */
     private final int mIconAttrId;
@@ -114,7 +113,8 @@
     public static final int BACKGROUND_TYPE_NORMAL = 0;
     public static final int BACKGROUND_TYPE_FUNCTIONAL = 1;
     public static final int BACKGROUND_TYPE_ACTION = 2;
-    public static final int BACKGROUND_TYPE_STICKY = 3;
+    public static final int BACKGROUND_TYPE_STICKY_OFF = 3;
+    public static final int BACKGROUND_TYPE_STICKY_ON = 4;
 
     private final int mActionFlags;
     private static final int ACTION_FLAGS_IS_REPEATABLE = 0x01;
@@ -125,8 +125,6 @@
 
     /** The current pressed state of this key */
     private boolean mPressed;
-    /** If this is a sticky key, is its highlight on? */
-    private boolean mHighlightOn;
     /** Key is enabled and responds on press */
     private boolean mEnabled = true;
 
@@ -303,31 +301,46 @@
                 keyAttr, R.styleable.Keyboard_Key_keyLabel), preserveCase, params.mId);
         mHintLabel = adjustCaseOfStringForKeyboardId(style.getString(
                 keyAttr, R.styleable.Keyboard_Key_keyHintLabel), preserveCase, params.mId);
-        mOutputText = adjustCaseOfStringForKeyboardId(style.getString(
+        String outputText = adjustCaseOfStringForKeyboardId(style.getString(
                 keyAttr, R.styleable.Keyboard_Key_keyOutputText), preserveCase, params.mId);
-        // Choose the first letter of the label as primary code if not
-        // specified.
-        final int code = adjustCaseOfCodeForKeyboardId(style.getInt(
-                keyAttr, R.styleable.Keyboard_Key_code, Keyboard.CODE_UNSPECIFIED), preserveCase,
-                params.mId);
-        if (code == Keyboard.CODE_UNSPECIFIED && mOutputText == null
+        final int code = style.getInt(
+                keyAttr, R.styleable.Keyboard_Key_code, Keyboard.CODE_UNSPECIFIED);
+        // Choose the first letter of the label as primary code if not specified.
+        if (code == Keyboard.CODE_UNSPECIFIED && TextUtils.isEmpty(outputText)
                 && !TextUtils.isEmpty(mLabel)) {
-            if (mLabel.length() != 1) {
-                Log.w(TAG, "Label is not a single letter: label=" + mLabel);
+            if (mLabel.codePointCount(0, mLabel.length()) == 1) {
+                final int activatedCode;
+                // Use the first letter of the hint label if shiftedLetterActivated flag is
+                // specified.
+                if (hasShiftedLetterHint() && isShiftedLetterActivated()
+                        && !TextUtils.isEmpty(mHintLabel)) {
+                    activatedCode = mHintLabel.codePointAt(0);
+                } else {
+                    activatedCode = mLabel.codePointAt(0);
+                }
+                mCode = getRtlParenthesisCode(activatedCode, params.mIsRtlKeyboard);
+            } else {
+                // In some locale and case, the character might be represented by multiple code
+                // points, such as upper case Eszett of German alphabet.
+                outputText = mLabel;
+                mCode = Keyboard.CODE_OUTPUT_TEXT;
             }
-            final int firstChar = mLabel.charAt(0);
-            mCode = getRtlParenthesisCode(firstChar, params.mIsRtlKeyboard);
-        } else if (code == Keyboard.CODE_UNSPECIFIED && mOutputText != null) {
+        } else if (code == Keyboard.CODE_UNSPECIFIED && outputText != null) {
             mCode = Keyboard.CODE_OUTPUT_TEXT;
         } else {
-            mCode = code;
+            mCode = adjustCaseOfCodeForKeyboardId(code, preserveCase, params.mId);
         }
+        mOutputText = outputText;
         mAltCode = adjustCaseOfCodeForKeyboardId(style.getInt(keyAttr,
                 R.styleable.Keyboard_Key_altCode, Keyboard.CODE_UNSPECIFIED), preserveCase,
                 params.mId);
         mHashCode = hashCode(this);
 
         keyAttr.recycle();
+
+        if (hasShiftedLetterHint() && TextUtils.isEmpty(mHintLabel)) {
+            Log.w(TAG, "hasShiftedLetterHint specified without keyHintLabel: " + this);
+        }
     }
 
     private static int adjustCaseOfCodeForKeyboardId(int code, boolean preserveCase,
@@ -335,7 +348,8 @@
         if (!Keyboard.isLetterCode(code) || preserveCase) return code;
         final String text = new String(new int[] { code } , 0, 1);
         final String casedText = adjustCaseOfStringForKeyboardId(text, preserveCase, id);
-        return casedText.codePointAt(0);
+        return casedText.codePointCount(0, casedText.length()) == 1
+                ? casedText.codePointAt(0) : Keyboard.CODE_UNSPECIFIED;
     }
 
     private static String adjustCaseOfStringForKeyboardId(String text, boolean preserveCase,
@@ -362,6 +376,7 @@
                 key.mLabel,
                 key.mHintLabel,
                 key.mIconAttrId,
+                key.mBackgroundType,
                 // Key can be distinguishable without the following members.
                 // key.mAltCode,
                 // key.mOutputText,
@@ -370,7 +385,6 @@
                 // key.mIcon,
                 // key.mDisabledIconAttrId,
                 // key.mPreviewIconAttrId,
-                // key.mBackgroundType,
                 // key.mHorizontalGap,
                 // key.mVerticalGap,
                 // key.mVisualInsetLeft,
@@ -388,7 +402,9 @@
                 && o.mHeight == mHeight
                 && o.mCode == mCode
                 && TextUtils.equals(o.mLabel, mLabel)
-                && TextUtils.equals(o.mHintLabel, mHintLabel);
+                && TextUtils.equals(o.mHintLabel, mHintLabel)
+                && o.mIconAttrId != mIconAttrId
+                && o.mBackgroundType != mBackgroundType;
     }
 
     @Override
@@ -401,6 +417,15 @@
         return o instanceof Key && equals((Key)o);
     }
 
+    @Override
+    public String toString() {
+        String top = Keyboard.printableCode(mCode);
+        if (mLabel != null && mLabel.length() != 1) {
+            top += "/\"" + mLabel + '"';
+        }
+        return String.format("%s %d,%d", top, mX, mY);
+    }
+
     public void markAsLeftEdge(Keyboard.Params params) {
         mHitBox.left = params.mHorizontalEdgesPadding;
     }
@@ -417,10 +442,6 @@
         mHitBox.bottom = params.mOccupiedHeight + params.mBottomPadding;
     }
 
-    public boolean isSticky() {
-        return mBackgroundType == BACKGROUND_TYPE_STICKY;
-    }
-
     public boolean isSpacer() {
         return false;
     }
@@ -486,8 +507,8 @@
         return (mLabelFlags & LABEL_FLAGS_HAS_POPUP_HINT) != 0;
     }
 
-    public boolean hasUppercaseLetter() {
-        return (mLabelFlags & LABEL_FLAGS_HAS_UPPERCASE_LETTER) != 0;
+    public boolean hasShiftedLetterHint() {
+        return (mLabelFlags & LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT) != 0;
     }
 
     public boolean hasHintLabel() {
@@ -506,12 +527,8 @@
         return (mLabelFlags & LABEL_FLAGS_AUTO_X_SCALE) != 0;
     }
 
-    public boolean isInactivatedLabel() {
-        return (mLabelFlags & LABEL_FLAGS_INACTIVATED_LABEL) != 0;
-    }
-
-    public boolean isInactivatedUppercaseLetter() {
-        return (mLabelFlags & LABEL_FLAGS_INACTIVATED_UPPERCASE_LETTER) != 0;
+    public boolean isShiftedLetterActivated() {
+        return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0;
     }
 
     // TODO: Get rid of this method.
@@ -542,10 +559,6 @@
         mPressed = false;
     }
 
-    public void setHighlightOn(boolean highlightOn) {
-        mHighlightOn = highlightOn;
-    }
-
     public boolean isEnabled() {
         return mEnabled;
     }
@@ -639,21 +652,17 @@
      * @see android.graphics.drawable.StateListDrawable#setState(int[])
      */
     public int[] getCurrentDrawableState() {
-        final boolean pressed = mPressed;
-
         switch (mBackgroundType) {
         case BACKGROUND_TYPE_FUNCTIONAL:
-            return pressed ? KEY_STATE_FUNCTIONAL_PRESSED : KEY_STATE_FUNCTIONAL_NORMAL;
+            return mPressed ? KEY_STATE_FUNCTIONAL_PRESSED : KEY_STATE_FUNCTIONAL_NORMAL;
         case BACKGROUND_TYPE_ACTION:
-            return pressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL;
-        case BACKGROUND_TYPE_STICKY:
-            if (mHighlightOn) {
-                return pressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON;
-            } else {
-                return pressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF;
-            }
+            return mPressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL;
+        case BACKGROUND_TYPE_STICKY_OFF:
+            return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF;
+        case BACKGROUND_TYPE_STICKY_ON:
+            return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON;
         default: /* BACKGROUND_TYPE_NORMAL */
-            return pressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
+            return mPressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
         }
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index dd88209..8832d8f 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -20,7 +20,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
-import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -31,7 +30,6 @@
 import com.android.inputmethod.compat.EditorInfoCompatUtils;
 import com.android.inputmethod.keyboard.internal.KeyStyles;
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.keyboard.internal.KeyboardShiftState;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.XmlParseUtils;
@@ -130,16 +128,12 @@
     /** List of keys and icons in this keyboard */
     public final Set<Key> mKeys;
     public final Set<Key> mShiftKeys;
-    public final Set<Key> mShiftLockKeys;
     public final KeyboardIconsSet mIconsSet;
 
     private final Map<Integer, Key> mKeyCache = new HashMap<Integer, Key>();
 
     private final ProximityInfo mProximityInfo;
 
-    // TODO: Remove this variable.
-    private final KeyboardShiftState mShiftState = new KeyboardShiftState();
-
     public Keyboard(Params params) {
         mId = params.mId;
         mThemeId = params.mThemeId;
@@ -156,7 +150,6 @@
 
         mKeys = Collections.unmodifiableSet(params.mKeys);
         mShiftKeys = Collections.unmodifiableSet(params.mShiftKeys);
-        mShiftLockKeys = Collections.unmodifiableSet(params.mShiftLockKeys);
         mIconsSet = params.mIconsSet;
 
         mProximityInfo = new ProximityInfo(
@@ -188,70 +181,18 @@
     }
 
     // TODO: Remove this method.
-    boolean hasShiftLockKey() {
-        return !mShiftLockKeys.isEmpty();
-    }
-
-    // TODO: Remove this method.
-    void setShiftLocked(boolean newShiftLockState) {
-        for (final Key key : mShiftLockKeys) {
-            // To represent "shift locked" state. The highlight is handled by background image that
-            // might be a StateListDrawable.
-            key.setHighlightOn(newShiftLockState);
-            final int attrId = newShiftLockState
-                    ? R.styleable.Keyboard_iconShiftKeyShifted
-                    : R.styleable.Keyboard_iconShiftKey;
-            key.setIcon(mIconsSet.getIconByAttrId(attrId));
-        }
-        mShiftState.setShiftLocked(newShiftLockState);
-    }
-
-    // TODO: Move this method to KeyboardId.
     public boolean isShiftLocked() {
-        return mShiftState.isShiftLocked();
-    }
-
-    private void setShiftKeyGraphics(boolean newShiftState) {
-        if (mShiftState.isShiftLocked()) {
-            return;
-        }
-        for (final Key key : mShiftKeys) {
-            final int attrId = newShiftState
-                    ? R.styleable.Keyboard_iconShiftKeyShifted
-                    : R.styleable.Keyboard_iconShiftKey;
-            key.setIcon(mIconsSet.getIconByAttrId(attrId));
-        }
+        return mId.isAlphabetShiftLockedKeyboard();
     }
 
     // TODO: Remove this method.
-    void setShifted(boolean newShiftState) {
-        setShiftKeyGraphics(newShiftState);
-        mShiftState.setShifted(newShiftState);
-    }
-
-    // TODO: Move this method to KeyboardId.
     public boolean isShiftedOrShiftLocked() {
-        return mShiftState.isShiftedOrShiftLocked();
-    }
-
-    // TODO: Remove this method
-    void setAutomaticTemporaryUpperCase() {
-        setShiftKeyGraphics(true);
-        mShiftState.setAutomaticTemporaryUpperCase();
-    }
-
-    // TODO: Move this method to KeyboardId.
-    public boolean isManualTemporaryUpperCase() {
-        return mShiftState.isManualTemporaryUpperCase();
+        return mId.isAlphabetShiftedOrShiftLockedKeyboard();
     }
 
     // TODO: Remove this method.
-    public String adjustLabelCase(String label) {
-        if (mId.isAlphabetKeyboard() && isShiftedOrShiftLocked() && !TextUtils.isEmpty(label)
-                && label.length() < 3 && Character.isLowerCase(label.charAt(0))) {
-            return label.toUpperCase(mId.mLocale);
-        }
-        return label;
+    public boolean isManualShifted() {
+        return mId.isAlphabetManualShiftedKeyboard();
     }
 
     public static boolean isLetterCode(int code) {
@@ -291,7 +232,6 @@
 
         public final Set<Key> mKeys = new HashSet<Key>();
         public final Set<Key> mShiftKeys = new HashSet<Key>();
-        public final Set<Key> mShiftLockKeys = new HashSet<Key>();
         public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
 
         public KeyboardSet.KeysCache mKeysCache;
@@ -360,7 +300,6 @@
         protected void clearKeys() {
             mKeys.clear();
             mShiftKeys.clear();
-            mShiftLockKeys.clear();
             clearHistogram();
         }
 
@@ -370,9 +309,6 @@
             updateHistogram(key);
             if (key.mCode == Keyboard.CODE_SHIFT) {
                 mShiftKeys.add(key);
-                if (key.isSticky()) {
-                    mShiftLockKeys.add(key);
-                }
             }
         }
 
@@ -437,6 +373,8 @@
         case CODE_DELETE: return "delete";
         case CODE_SHORTCUT: return "shortcut";
         case CODE_UNSPECIFIED: return "unspec";
+        case CODE_TAB: return "tab";
+        case CODE_ENTER: return "enter";
         default:
             if (code <= 0) Log.w(TAG, "Unknown non-positive key code=" + code);
             if (code < CODE_SPACE) return String.format("'\\u%02x'", code);
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index 8db8c94..997b952 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -124,6 +124,22 @@
         return mElementId < ELEMENT_SYMBOLS;
     }
 
+    // This should be aligned with {@link KeyboardShiftState#isShiftLocked}.
+    public boolean isAlphabetShiftLockedKeyboard() {
+        return mElementId == ELEMENT_ALPHABET_SHIFT_LOCKED
+                || mElementId == ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED;
+    }
+
+    // This should be aligned with {@link KeyboardShiftState#isShiftedOrShiftLocked}.
+    public boolean isAlphabetShiftedOrShiftLockedKeyboard() {
+        return isAlphabetKeyboard() && mElementId != ELEMENT_ALPHABET;
+    }
+
+    // This should be aligned with {@link KeyboardShiftState#isManualShifted}.
+    public boolean isAlphabetManualShiftedKeyboard() {
+        return mElementId != ELEMENT_ALPHABET_MANUAL_SHIFTED;
+    }
+
     public boolean isSymbolsKeyboard() {
         return mElementId == ELEMENT_SYMBOLS || mElementId == ELEMENT_SYMBOLS_SHIFTED;
     }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
index ae5e4e8..0aed506 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
@@ -77,17 +77,6 @@
         }
     }
 
-    static class KeyboardElement {
-        final int mElementId;
-        final int mLayoutId;
-        final boolean mAutoGenerate;
-        KeyboardElement(int elementId, int layoutId, boolean autoGenerate) {
-            mElementId = elementId;
-            mLayoutId = layoutId;
-            mAutoGenerate = autoGenerate;
-        }
-    }
-
     static class Params {
         int mMode;
         int mInputType;
@@ -100,8 +89,9 @@
         Locale mLocale;
         int mOrientation;
         int mWidth;
-        final Map<Integer, KeyboardElement> mElementKeyboards =
-                new HashMap<Integer, KeyboardElement>();
+        // KeyboardSet element id to keyboard layout XML id map.
+        final Map<Integer, Integer> mKeyboardSetElementIdToXmlIdMap =
+                new HashMap<Integer, Integer>();
         Params() {}
     }
 
@@ -117,41 +107,38 @@
         mParams = params;
     }
 
+    // TODO: Remove this method, use {@link #getKeyboard} directly.
     public Keyboard getMainKeyboard() {
-        return getKeyboard(false, false, false);
+        return getKeyboard(KeyboardId.ELEMENT_ALPHABET);
     }
 
-    public Keyboard getSymbolsKeyboard() {
-        return getKeyboard(true, false, false);
-    }
+    public Keyboard getKeyboard(int baseKeyboardSetElementId) {
+        final int keyboardSetElementId;
+        switch (mParams.mMode) {
+        case KeyboardId.MODE_PHONE:
+            keyboardSetElementId =
+                    (baseKeyboardSetElementId == KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED)
+                    ? KeyboardId.ELEMENT_PHONE_SHIFTED : KeyboardId.ELEMENT_PHONE;
+            break;
+        case KeyboardId.MODE_NUMBER:
+            keyboardSetElementId = KeyboardId.ELEMENT_NUMBER;
+            break;
+        default:
+            keyboardSetElementId = baseKeyboardSetElementId;
+            break;
+        }
 
-    public Keyboard getSymbolsShiftedKeyboard() {
-        final Keyboard keyboard = getKeyboard(true, false, true);
-        // TODO: Remove this logic once we introduce initial keyboard shift state attribute.
-        // Symbol shift keyboard may have a shift key that has a caps lock style indicator (a.k.a.
-        // sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked()
-        // that takes care of the current keyboard having such shift key or not.
-        keyboard.setShiftLocked(keyboard.hasShiftLockKey());
+        Integer keyboardXmlId = mParams.mKeyboardSetElementIdToXmlIdMap.get(keyboardSetElementId);
+        if (keyboardXmlId == null) {
+            keyboardXmlId = mParams.mKeyboardSetElementIdToXmlIdMap.get(
+                    KeyboardId.ELEMENT_ALPHABET);
+        }
+        final KeyboardId id = getKeyboardId(keyboardSetElementId);
+        final Keyboard keyboard = getKeyboard(mContext, keyboardXmlId, id);
         return keyboard;
     }
 
-    private Keyboard getKeyboard(boolean isSymbols, boolean isShiftLock, boolean isShift) {
-        final int elementId = KeyboardSet.getElementId(
-                mParams.mMode, isSymbols, isShiftLock, isShift);
-        final KeyboardElement keyboardElement = mParams.mElementKeyboards.get(elementId);
-        // TODO: If keyboardElement.mAutoGenerate is true, the keyboard will be auto generated
-        // based on keyboardElement.mKayoutId Keyboard XML definition.
-        final KeyboardId id = KeyboardSet.getKeyboardId(elementId, isSymbols, mParams);
-        final Keyboard keyboard = getKeyboard(mContext, keyboardElement, id);
-        return keyboard;
-    }
-
-    public KeyboardId getMainKeyboardId() {
-        final int elementId = KeyboardSet.getElementId(mParams.mMode, false, false, false);
-        return KeyboardSet.getKeyboardId(elementId, false, mParams);
-    }
-
-    private Keyboard getKeyboard(Context context, KeyboardElement element, KeyboardId id) {
+    private Keyboard getKeyboard(Context context, int keyboardXmlId, KeyboardId id) {
         final Resources res = context.getResources();
         final SoftReference<Keyboard> ref = sKeyboardCache.get(id);
         Keyboard keyboard = (ref == null) ? null : ref.get();
@@ -160,10 +147,10 @@
             try {
                 final Keyboard.Builder<Keyboard.Params> builder =
                         new Keyboard.Builder<Keyboard.Params>(context, new Keyboard.Params());
-                if (element.mAutoGenerate) {
+                if (id.isAlphabetKeyboard()) {
                     builder.setAutoGenerate(mKeysCache);
                 }
-                builder.load(element.mLayoutId, id);
+                builder.load(keyboardXmlId, id);
                 builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled);
                 keyboard = builder.build();
             } finally {
@@ -179,36 +166,23 @@
             Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": HIT  id=" + id);
         }
 
-        // TODO: Remove setShiftLocked and setShift calls.
-        keyboard.setShiftLocked(false);
-        keyboard.setShifted(false);
         return keyboard;
     }
 
-    private static int getElementId(int mode, boolean isSymbols, boolean isShiftLock,
-            boolean isShift) {
-        switch (mode) {
-        case KeyboardId.MODE_PHONE:
-            return (isSymbols && isShift)
-                    ? KeyboardId.ELEMENT_PHONE_SHIFTED : KeyboardId.ELEMENT_PHONE;
-        case KeyboardId.MODE_NUMBER:
-            return KeyboardId.ELEMENT_NUMBER;
-        default:
-            if (isSymbols) {
-                return isShift
-                        ? KeyboardId.ELEMENT_SYMBOLS_SHIFTED : KeyboardId.ELEMENT_SYMBOLS;
-            }
-            // TODO: Consult isShiftLock and isShift to determine the element.
-            return KeyboardId.ELEMENT_ALPHABET;
-        }
-    }
-
-    private static KeyboardId getKeyboardId(int elementId, boolean isSymbols, Params params) {
+    // TODO: Make this method private.
+    // Note: The keyboard for each locale, shift state, and mode are represented as KeyboardSet
+    // element id that is a key in keyboard_set.xml.  Also that file specifies which XML layout
+    // should be used for each keyboard.  The KeyboardId is an internal key for Keyboard object.
+    public KeyboardId getKeyboardId(int keyboardSetElementId) {
+        final Params params = mParams;
+        final boolean isSymbols = (keyboardSetElementId == KeyboardId.ELEMENT_SYMBOLS
+                || keyboardSetElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED);
         final boolean hasShortcutKey = params.mVoiceKeyEnabled
                 && (isSymbols != params.mVoiceKeyOnMain);
-        return new KeyboardId(elementId, params.mLocale, params.mOrientation, params.mWidth,
-                params.mMode, params.mInputType, params.mImeOptions, params.mSettingsKeyEnabled,
-                params.mNoSettingsKey, params.mVoiceKeyEnabled, hasShortcutKey);
+        return new KeyboardId(keyboardSetElementId, params.mLocale, params.mOrientation,
+                params.mWidth, params.mMode, params.mInputType, params.mImeOptions,
+                params.mSettingsKeyEnabled, params.mNoSettingsKey, params.mVoiceKeyEnabled,
+                hasShortcutKey);
     }
 
     public static class Builder {
@@ -345,10 +319,7 @@
                         R.styleable.KeyboardSet_Element_elementName, 0);
                 final int elementKeyboard = a.getResourceId(
                         R.styleable.KeyboardSet_Element_elementKeyboard, 0);
-                final boolean elementAutoGenerate = a.getBoolean(
-                        R.styleable.KeyboardSet_Element_elementAutoGenerate, false);
-                mParams.mElementKeyboards.put(elementName, new KeyboardElement(
-                        elementName, elementKeyboard, elementAutoGenerate));
+                mParams.mKeyboardSetElementIdToXmlIdMap.put(elementName, elementKeyboard);
             } finally {
                 a.recycle();
             }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 5a59cc1..17ad45d 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -135,24 +135,19 @@
                 settingsValues.isVoiceKeyEnabled(editorInfo),
                 settingsValues.isVoiceKeyOnMain());
         mKeyboardSet = builder.build();
-        final KeyboardId mainKeyboardId = mKeyboardSet.getMainKeyboardId();
         try {
             mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols));
         } catch (RuntimeException e) {
-            Log.w(TAG, "loading keyboard failed: " + mainKeyboardId, e);
-            LatinImeLogger.logOnException(mainKeyboardId.toString(), e);
+            Log.w(TAG, "loading keyboard failed: " + mKeyboardSet.getKeyboardId(
+                    KeyboardId.ELEMENT_ALPHABET), e);
+            LatinImeLogger.logOnException(mKeyboardSet.getKeyboardId(
+                    KeyboardId.ELEMENT_ALPHABET).toString(), e);
             return;
         }
-        // TODO: Should get rid of this special case handling for Phone Number layouts once we
-        // have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted
-        // respectively.
-        if (mainKeyboardId.isPhoneKeyboard()) {
-            mState.setSymbolsKeyboard();
-        }
     }
 
     public void saveKeyboardState() {
-        if (isKeyboardAvailable()) {
+        if (getKeyboard() != null) {
             mState.onSaveKeyboardState();
         }
     }
@@ -184,31 +179,23 @@
         mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
     }
 
+    // TODO: Remove this method.
     public boolean isAlphabetMode() {
         final Keyboard keyboard = getKeyboard();
         return keyboard != null && keyboard.mId.isAlphabetKeyboard();
     }
 
+    // TODO: Remove this method.
     public boolean isInputViewShown() {
         return mCurrentInputView != null && mCurrentInputView.isShown();
     }
 
+    // TODO: Remove this method.
     public boolean isShiftedOrShiftLocked() {
         final Keyboard keyboard = getKeyboard();
         return keyboard != null && keyboard.isShiftedOrShiftLocked();
     }
 
-    public boolean isManualTemporaryUpperCase() {
-        final Keyboard keyboard = getKeyboard();
-        return keyboard != null && keyboard.isManualTemporaryUpperCase();
-    }
-
-    public boolean isKeyboardAvailable() {
-        if (mKeyboardView != null)
-            return mKeyboardView.getKeyboard() != null;
-        return false;
-    }
-
     public Keyboard getKeyboard() {
         if (mKeyboardView != null) {
             return mKeyboardView.getKeyboard();
@@ -235,91 +222,46 @@
         mState.onCancelInput(isSinglePointer());
     }
 
-    // TODO: Remove these constants.
-    private static final int ALPHABET_UNSHIFTED = 0;
-    private static final int ALPHABET_MANUAL_SHIFTED = 1;
-    private static final int ALPHABET_AUTOMATIC_SHIFTED = 2;
-    private static final int ALPHABET_SHIFT_LOCKED = 3;
-    private static final int ALPHABET_SHIFT_LOCK_SHIFTED = 4;
-
-    // TODO: Remove this method.
-    private void updateAlphabetKeyboardShiftState(int shiftMode) {
-        mInputMethodService.mHandler.cancelUpdateShiftState();
-        Keyboard keyboard = getKeyboard();
-        if (keyboard == null)
-            return;
-        switch (shiftMode) {
-        case ALPHABET_UNSHIFTED:
-            keyboard.setShifted(false);
-            break;
-        case ALPHABET_MANUAL_SHIFTED:
-            keyboard.setShifted(true);
-            break;
-        case ALPHABET_AUTOMATIC_SHIFTED:
-            keyboard.setAutomaticTemporaryUpperCase();
-            break;
-        case ALPHABET_SHIFT_LOCKED:
-            keyboard.setShiftLocked(true);
-            break;
-        case ALPHABET_SHIFT_LOCK_SHIFTED:
-            keyboard.setShiftLocked(true);
-            keyboard.setShifted(true);
-            break;
-        }
-        mKeyboardView.invalidateAllKeys();
-        if (shiftMode != ALPHABET_SHIFT_LOCKED) {
-            // To be able to turn off caps lock by "double tap" on shift key, we should ignore
-            // the second tap of the "double tap" from now for a while because we just have
-            // already turned off caps lock above.
-            mKeyboardView.startIgnoringDoubleTap();
-        }
-    }
-
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetKeyboard() {
-        setKeyboard(mKeyboardSet.getMainKeyboard());
-        updateAlphabetKeyboardShiftState(ALPHABET_UNSHIFTED);
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetManualShiftedKeyboard() {
-        setKeyboard(mKeyboardSet.getMainKeyboard());
-        updateAlphabetKeyboardShiftState(ALPHABET_MANUAL_SHIFTED);
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetAutomaticShiftedKeyboard() {
-        setKeyboard(mKeyboardSet.getMainKeyboard());
-        updateAlphabetKeyboardShiftState(ALPHABET_AUTOMATIC_SHIFTED);
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetShiftLockedKeyboard() {
-        setKeyboard(mKeyboardSet.getMainKeyboard());
-        updateAlphabetKeyboardShiftState(ALPHABET_SHIFT_LOCKED);
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetShiftLockShiftedKeyboard() {
-        setKeyboard(mKeyboardSet.getMainKeyboard());
-        updateAlphabetKeyboardShiftState(ALPHABET_SHIFT_LOCK_SHIFTED);
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setSymbolsKeyboard() {
-        setKeyboard(mKeyboardSet.getSymbolsKeyboard());
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setSymbolsShiftedKeyboard() {
-        setKeyboard(mKeyboardSet.getSymbolsShiftedKeyboard());
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index d977327..2cbd132 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -53,12 +53,12 @@
  * @attr ref R.styleable#KeyboardView_keyLargeLetterRatio
  * @attr ref R.styleable#KeyboardView_keyLabelRatio
  * @attr ref R.styleable#KeyboardView_keyHintLetterRatio
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterRatio
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintRatio
  * @attr ref R.styleable#KeyboardView_keyHintLabelRatio
  * @attr ref R.styleable#KeyboardView_keyLabelHorizontalPadding
  * @attr ref R.styleable#KeyboardView_keyHintLetterPadding
  * @attr ref R.styleable#KeyboardView_keyPopupHintLetterPadding
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterPadding
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintPadding
  * @attr ref R.styleable#KeyboardView_keyTextStyle
  * @attr ref R.styleable#KeyboardView_keyPreviewLayout
  * @attr ref R.styleable#KeyboardView_keyPreviewTextRatio
@@ -68,8 +68,8 @@
  * @attr ref R.styleable#KeyboardView_keyTextColorDisabled
  * @attr ref R.styleable#KeyboardView_keyHintLetterColor
  * @attr ref R.styleable#KeyboardView_keyHintLabelColor
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterInactivatedColor
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterActivatedColor
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintInactivatedColor
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintActivatedColor
  * @attr ref R.styleable#KeyboardView_shadowColor
  * @attr ref R.styleable#KeyboardView_shadowRadius
  */
@@ -175,20 +175,20 @@
         public final float mKeyLabelHorizontalPadding;
         public final float mKeyHintLetterPadding;
         public final float mKeyPopupHintLetterPadding;
-        public final float mKeyUppercaseLetterPadding;
+        public final float mKeyShiftedLetterHintPadding;
         public final int mShadowColor;
         public final float mShadowRadius;
         public final Drawable mKeyBackground;
         public final int mKeyHintLetterColor;
         public final int mKeyHintLabelColor;
-        public final int mKeyUppercaseLetterInactivatedColor;
-        public final int mKeyUppercaseLetterActivatedColor;
+        public final int mKeyShiftedLetterHintInactivatedColor;
+        public final int mKeyShiftedLetterHintActivatedColor;
 
         private final float mKeyLetterRatio;
         private final float mKeyLargeLetterRatio;
         private final float mKeyLabelRatio;
         private final float mKeyHintLetterRatio;
-        private final float mKeyUppercaseLetterRatio;
+        private final float mKeyShiftedLetterHintRatio;
         private final float mKeyHintLabelRatio;
         private static final float UNDEFINED_RATIO = -1.0f;
 
@@ -197,7 +197,7 @@
         public int mKeyLargeLetterSize;
         public int mKeyLabelSize;
         public int mKeyHintLetterSize;
-        public int mKeyUppercaseLetterSize;
+        public int mKeyShiftedLetterHintSize;
         public int mKeyHintLabelSize;
 
         public KeyDrawParams(TypedArray a) {
@@ -216,8 +216,8 @@
             }
             mKeyLargeLetterRatio = getRatio(a, R.styleable.KeyboardView_keyLargeLetterRatio);
             mKeyHintLetterRatio = getRatio(a, R.styleable.KeyboardView_keyHintLetterRatio);
-            mKeyUppercaseLetterRatio = getRatio(a,
-                    R.styleable.KeyboardView_keyUppercaseLetterRatio);
+            mKeyShiftedLetterHintRatio = getRatio(a,
+                    R.styleable.KeyboardView_keyShiftedLetterHintRatio);
             mKeyHintLabelRatio = getRatio(a, R.styleable.KeyboardView_keyHintLabelRatio);
             mKeyLabelHorizontalPadding = a.getDimension(
                     R.styleable.KeyboardView_keyLabelHorizontalPadding, 0);
@@ -225,17 +225,17 @@
                     R.styleable.KeyboardView_keyHintLetterPadding, 0);
             mKeyPopupHintLetterPadding = a.getDimension(
                     R.styleable.KeyboardView_keyPopupHintLetterPadding, 0);
-            mKeyUppercaseLetterPadding = a.getDimension(
-                    R.styleable.KeyboardView_keyUppercaseLetterPadding, 0);
+            mKeyShiftedLetterHintPadding = a.getDimension(
+                    R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0);
             mKeyTextColor = a.getColor(R.styleable.KeyboardView_keyTextColor, 0xFF000000);
             mKeyTextInactivatedColor = a.getColor(
                     R.styleable.KeyboardView_keyTextInactivatedColor, 0xFF000000);
             mKeyHintLetterColor = a.getColor(R.styleable.KeyboardView_keyHintLetterColor, 0);
             mKeyHintLabelColor = a.getColor(R.styleable.KeyboardView_keyHintLabelColor, 0);
-            mKeyUppercaseLetterInactivatedColor = a.getColor(
-                    R.styleable.KeyboardView_keyUppercaseLetterInactivatedColor, 0);
-            mKeyUppercaseLetterActivatedColor = a.getColor(
-                    R.styleable.KeyboardView_keyUppercaseLetterActivatedColor, 0);
+            mKeyShiftedLetterHintInactivatedColor = a.getColor(
+                    R.styleable.KeyboardView_keyShiftedLetterHintInactivatedColor, 0);
+            mKeyShiftedLetterHintActivatedColor = a.getColor(
+                    R.styleable.KeyboardView_keyShiftedLetterHintActivatedColor, 0);
             mKeyTextStyle = Typeface.defaultFromStyle(
                     a.getInt(R.styleable.KeyboardView_keyTextStyle, Typeface.NORMAL));
             mShadowColor = a.getColor(R.styleable.KeyboardView_shadowColor, 0);
@@ -251,7 +251,7 @@
                 mKeyLabelSize = (int)(keyHeight * mKeyLabelRatio);
             mKeyLargeLetterSize = (int)(keyHeight * mKeyLargeLetterRatio);
             mKeyHintLetterSize = (int)(keyHeight * mKeyHintLetterRatio);
-            mKeyUppercaseLetterSize = (int)(keyHeight * mKeyUppercaseLetterRatio);
+            mKeyShiftedLetterHintSize = (int)(keyHeight * mKeyShiftedLetterHintRatio);
             mKeyHintLabelSize = (int)(keyHeight * mKeyHintLabelRatio);
         }
     }
@@ -527,8 +527,7 @@
         final Drawable icon = key.getIcon(mKeyboard.mIconsSet);
         float positionX = centerX;
         if (key.mLabel != null) {
-            // Switch the character to uppercase if shift is pressed
-            final String label = mKeyboard.adjustLabelCase(key.mLabel);
+            final String label = key.mLabel;
             // For characters, use large font. For labels like "Done", use smaller font.
             paint.setTypeface(key.selectTypeface(params.mKeyTextStyle));
             final int labelSize = key.selectTextSize(params.mKeyLetterSize,
@@ -571,14 +570,8 @@
                         Math.min(1.0f, (keyWidth * MAX_LABEL_RATIO) / getLabelWidth(label, paint)));
             }
 
-            // TODO: Remove this first if-clause.
-            if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) {
-                paint.setColor(params.mKeyTextInactivatedColor);
-            } else if (key.isInactivatedLabel()) {
-                paint.setColor(params.mKeyTextInactivatedColor);
-            } else {
-                paint.setColor(params.mKeyTextColor);
-            }
+            paint.setColor(key.isShiftedLetterActivated()
+                    ? params.mKeyTextInactivatedColor : params.mKeyTextColor);
             if (key.isEnabled()) {
                 // Set a drop shadow for the text
                 paint.setShadowLayer(params.mShadowRadius, 0, 0, params.mShadowColor);
@@ -620,16 +613,11 @@
                 hintColor = params.mKeyHintLabelColor;
                 hintSize = params.mKeyHintLabelSize;
                 paint.setTypeface(Typeface.DEFAULT);
-            } else if (key.hasUppercaseLetter()) {
-                // TODO: Remove this first if-clause.
-                if (mKeyboard.isManualTemporaryUpperCase()) {
-                    hintColor = params.mKeyUppercaseLetterActivatedColor;
-                } else if (!key.isInactivatedUppercaseLetter()) {
-                    hintColor = params.mKeyUppercaseLetterActivatedColor;
-                } else {
-                    hintColor = params.mKeyUppercaseLetterInactivatedColor;
-                }
-                hintSize = params.mKeyUppercaseLetterSize;
+            } else if (key.hasShiftedLetterHint()) {
+                hintColor = key.isShiftedLetterActivated()
+                        ? params.mKeyShiftedLetterHintActivatedColor
+                        : params.mKeyShiftedLetterHintInactivatedColor;
+                hintSize = params.mKeyShiftedLetterHintSize;
             } else { // key.hasHintLetter()
                 hintColor = params.mKeyHintLetterColor;
                 hintSize = params.mKeyHintLetterSize;
@@ -644,9 +632,9 @@
                 hintX = positionX + getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2;
                 hintY = centerY + getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
                 paint.setTextAlign(Align.LEFT);
-            } else if (key.hasUppercaseLetter()) {
+            } else if (key.hasShiftedLetterHint()) {
                 // The hint label is placed at top-right corner of the key. Used mainly on tablet.
-                hintX = keyWidth - params.mKeyUppercaseLetterPadding
+                hintX = keyWidth - params.mKeyShiftedLetterHintPadding
                         - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
                 hintY = -paint.ascent();
                 paint.setTextAlign(Align.CENTER);
@@ -870,7 +858,7 @@
                 previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mPreviewTextSize);
                 previewText.setTypeface(params.mKeyTextStyle);
             }
-            previewText.setText(mKeyboard.adjustLabelCase(key.mLabel));
+            previewText.setText(key.mLabel);
         } else {
             final Drawable previewIcon = mKeyboard.mIconsSet.getIconByAttrId(
                     key.mPreviewIconAttrId);
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 7e8a718..056aa25 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -548,7 +548,6 @@
         mMoreKeysPanelPointerTrackerId = tracker.mPointerId;
 
         final Keyboard keyboard = getKeyboard();
-        moreKeysPanel.setShifted(keyboard.isShiftedOrShiftLocked());
         final int pointX = (mConfigShowMiniKeyboardAtTouchedPoint) ? tracker.getLastX()
                 : parentKey.mX + parentKey.mWidth / 2;
         final int pointY = parentKey.mY - keyboard.mVerticalGap;
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java
index 1f9ed5e..72d5b68 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java
@@ -131,13 +131,6 @@
     }
 
     @Override
-    public void setShifted(boolean shifted) {
-        final Keyboard keyboard = getKeyboard();
-        keyboard.setShifted(shifted);
-        invalidateAllKeys();
-    }
-
-    @Override
     public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY,
             PopupWindow window, KeyboardActionListener listener) {
         mController = controller;
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java b/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
index a3ff372..f9a196d 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
@@ -24,9 +24,6 @@
         public boolean dismissMoreKeysPanel();
     }
 
-    // TODO: Remove this method.
-    public void setShifted(boolean shifted);
-
     /**
      * Show more keys panel.
      *
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index a75b8f9..4dac347 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -705,7 +705,7 @@
             if (sParams.mLongPressSpaceKeyTimeout > 0) {
                 mTimerProxy.startLongPressTimer(sParams.mLongPressSpaceKeyTimeout, this);
             }
-        } else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) {
+        } else if (key.hasShiftedLetterHint() && mKeyboard.isManualShifted()) {
             // We need not start long press timer on the key which has manual temporary upper case
             // code defined and the keyboard is in manual temporary upper case mode.
             return;
@@ -727,13 +727,6 @@
         final int[] codes = mKeyDetector.newCodeArray();
         mKeyDetector.getKeyAndNearbyCodes(x, y, codes);
 
-        // If keyboard is in manual temporary upper case state and key has manual temporary
-        // uppercase letter as key hint letter, alternate character code should be sent.
-        if (mKeyboard.isManualTemporaryUpperCase() && key.hasUppercaseLetter()) {
-            code = key.mHintLabel.charAt(0);
-            codes[0] = code;
-        }
-
         // Swap the first and second values in the codes array if the primary code is not the
         // first value but the second value in the array. This happens when key debouncing is
         // in effect.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
similarity index 76%
rename from java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
rename to java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
index 4608e22..5712df1 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
@@ -18,27 +18,27 @@
 
 import android.util.Log;
 
-public class KeyboardShiftState {
-    private static final String TAG = KeyboardShiftState.class.getSimpleName();
+public class AlphabetShiftState {
+    private static final String TAG = AlphabetShiftState.class.getSimpleName();
     private static final boolean DEBUG = false;
 
-    private static final int NORMAL = 0;
+    private static final int UNSHIFTED = 0;
     private static final int MANUAL_SHIFTED = 1;
     private static final int MANUAL_SHIFTED_FROM_AUTO = 2;
-    private static final int AUTO_SHIFTED = 3;
+    private static final int AUTOMATIC_SHIFTED = 3;
     private static final int SHIFT_LOCKED = 4;
     private static final int SHIFT_LOCK_SHIFTED = 5;
 
-    private int mState = NORMAL;
+    private int mState = UNSHIFTED;
 
     public void setShifted(boolean newShiftState) {
         final int oldState = mState;
         if (newShiftState) {
             switch (oldState) {
-            case NORMAL:
+            case UNSHIFTED:
                 mState = MANUAL_SHIFTED;
                 break;
-            case AUTO_SHIFTED:
+            case AUTOMATIC_SHIFTED:
                 mState = MANUAL_SHIFTED_FROM_AUTO;
                 break;
             case SHIFT_LOCKED:
@@ -49,8 +49,8 @@
             switch (oldState) {
             case MANUAL_SHIFTED:
             case MANUAL_SHIFTED_FROM_AUTO:
-            case AUTO_SHIFTED:
-                mState = NORMAL;
+            case AUTOMATIC_SHIFTED:
+                mState = UNSHIFTED;
                 break;
             case SHIFT_LOCK_SHIFTED:
                 mState = SHIFT_LOCKED;
@@ -65,30 +65,30 @@
         final int oldState = mState;
         if (newShiftLockState) {
             switch (oldState) {
-            case NORMAL:
+            case UNSHIFTED:
             case MANUAL_SHIFTED:
             case MANUAL_SHIFTED_FROM_AUTO:
-            case AUTO_SHIFTED:
+            case AUTOMATIC_SHIFTED:
                 mState = SHIFT_LOCKED;
                 break;
             }
         } else {
-            mState = NORMAL;
+            mState = UNSHIFTED;
         }
         if (DEBUG)
             Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState)
                     + " > " + this);
     }
 
-    public void setAutomaticTemporaryUpperCase() {
+    public void setAutomaticShifted() {
         final int oldState = mState;
-        mState = AUTO_SHIFTED;
+        mState = AUTOMATIC_SHIFTED;
         if (DEBUG)
-            Log.d(TAG, "setAutomaticTemporaryUpperCase: " + toString(oldState) + " > " + this);
+            Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this);
     }
 
     public boolean isShiftedOrShiftLocked() {
-        return mState != NORMAL;
+        return mState != UNSHIFTED;
     }
 
     public boolean isShiftLocked() {
@@ -99,16 +99,16 @@
         return mState == SHIFT_LOCK_SHIFTED;
     }
 
-    public boolean isAutomaticTemporaryUpperCase() {
-        return mState == AUTO_SHIFTED;
+    public boolean isAutomaticShifted() {
+        return mState == AUTOMATIC_SHIFTED;
     }
 
-    public boolean isManualTemporaryUpperCase() {
+    public boolean isManualShifted() {
         return mState == MANUAL_SHIFTED || mState == MANUAL_SHIFTED_FROM_AUTO
                 || mState == SHIFT_LOCK_SHIFTED;
     }
 
-    public boolean isManualTemporaryUpperCaseFromAuto() {
+    public boolean isManualShiftedFromAutomaticShifted() {
         return mState == MANUAL_SHIFTED_FROM_AUTO;
     }
 
@@ -119,13 +119,13 @@
 
     private static String toString(int state) {
         switch (state) {
-        case NORMAL: return "NORMAL";
+        case UNSHIFTED: return "UNSHIFTED";
         case MANUAL_SHIFTED: return "MANUAL_SHIFTED";
         case MANUAL_SHIFTED_FROM_AUTO: return "MANUAL_SHIFTED_FROM_AUTO";
-        case AUTO_SHIFTED: return "AUTO_SHIFTED";
+        case AUTOMATIC_SHIFTED: return "AUTOMATIC_SHIFTED";
         case SHIFT_LOCKED: return "SHIFT_LOCKED";
         case SHIFT_LOCK_SHIFTED: return "SHIFT_LOCK_SHIFTED";
-        default: return "UKNOWN";
+        default: return "UNKNOWN";
         }
     }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 5542bd3..4af4e3c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -70,7 +70,7 @@
     private String mLayoutSwitchBackSymbols;
 
     private boolean mIsAlphabetMode;
-    private KeyboardShiftState mAlphabetShiftState = new KeyboardShiftState();
+    private AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState();
     private boolean mIsSymbolShifted;
     private boolean mPrevMainKeyboardWasShiftLocked;
     private boolean mPrevSymbolsKeyboardWasShifted;
@@ -167,16 +167,16 @@
         }
         if (!mIsAlphabetMode) return;
         final int prevShiftMode;
-        if (mAlphabetShiftState.isAutomaticTemporaryUpperCase()) {
+        if (mAlphabetShiftState.isAutomaticShifted()) {
             prevShiftMode = AUTOMATIC_SHIFT;
-        } else if (mAlphabetShiftState.isManualTemporaryUpperCase()) {
+        } else if (mAlphabetShiftState.isManualShifted()) {
             prevShiftMode = MANUAL_SHIFT;
         } else {
             prevShiftMode = UNSHIFT;
         }
         switch (shiftMode) {
         case AUTOMATIC_SHIFT:
-            mAlphabetShiftState.setAutomaticTemporaryUpperCase();
+            mAlphabetShiftState.setAutomaticShifted();
             if (shiftMode != prevShiftMode) {
                 mSwitchActions.setAlphabetAutomaticShiftedKeyboard();
             }
@@ -353,7 +353,7 @@
                 // caps lock state and mark as if shift key pressed while normal state.
                 setShifted(SHIFT_LOCK_SHIFTED);
                 mShiftKeyState.onPress();
-            } else if (mAlphabetShiftState.isAutomaticTemporaryUpperCase()) {
+            } else if (mAlphabetShiftState.isAutomaticShifted()) {
                 // Shift key is pressed while automatic temporary upper case, we have to move to
                 // manual temporary upper case.
                 setShifted(MANUAL_SHIFT);
@@ -400,7 +400,7 @@
                     && mShiftKeyState.isPressingOnShifted() && !withSliding) {
                 // Shift has been pressed without chording while shifted state.
                 setShifted(UNSHIFT);
-            } else if (mAlphabetShiftState.isManualTemporaryUpperCaseFromAuto()
+            } else if (mAlphabetShiftState.isManualShiftedFromAutomaticShifted()
                     && mShiftKeyState.isPressing() && !withSliding) {
                 // Shift has been pressed without chording while manual temporary upper case
                 // transited from automatic temporary upper case.
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 2e7e826..0d6395d 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1470,13 +1470,12 @@
         if (ic == null)
             return;
 
-        // True if keyboard is in either chording shift or manual temporary upper case mode.
-        final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase();
-        if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions)
-                && !isManualTemporaryUpperCase) {
+        final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
+        // True if keyboard is in either shift chording or manual shifted state.
+        final boolean isManualShifted = (keyboard != null  && keyboard.isManualShifted());
+        if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) && !isManualShifted) {
             EditorInfoCompatUtils.performEditorActionNext(ic);
-        } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)
-                && isManualTemporaryUpperCase) {
+        } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) && isManualShifted) {
             EditorInfoCompatUtils.performEditorActionPrevious(ic);
         }
     }
@@ -1518,27 +1517,6 @@
                 mComposingStateManager.onFinishComposingText();
             }
         }
-        final KeyboardSwitcher switcher = mKeyboardSwitcher;
-        if (switcher.isShiftedOrShiftLocked()) {
-            if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT
-                    || keyCodes[0] > Character.MAX_CODE_POINT) {
-                return;
-            }
-            code = keyCodes[0];
-            if (switcher.isAlphabetMode() && Character.isLowerCase(code)) {
-                // In some locales, such as Turkish, Character.toUpperCase() may return a wrong
-                // character because it doesn't take care of locale.
-                final String upperCaseString = new String(new int[] {code}, 0, 1)
-                        .toUpperCase(mSubtypeSwitcher.getInputLocale());
-                if (upperCaseString.codePointCount(0, upperCaseString.length()) == 1) {
-                    code = upperCaseString.codePointAt(0);
-                } else {
-                    // Some keys, such as [eszett], have upper case as multi-characters.
-                    onTextInput(upperCaseString);
-                    return;
-                }
-            }
-        }
         if (isComposingWord) {
             mWordComposer.add(code, keyCodes, x, y);
             if (ic != null) {
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
index 600f14e..cd83c3e 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
@@ -141,11 +141,6 @@
     }
 
     @Override
-    public void setShifted(boolean shifted) {
-        // Nothing to do with.
-    }
-
-    @Override
     public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY,
             PopupWindow window, KeyboardActionListener listener) {
         mController = controller;