Merge "Remove FeedbackLog instance variables."
diff --git a/java/res/layout-land/setup_steps_screen.xml b/java/res/layout-land/setup_steps_screen.xml
index 0b4a096..cf8c424 100644
--- a/java/res/layout-land/setup_steps_screen.xml
+++ b/java/res/layout-land/setup_steps_screen.xml
@@ -27,7 +27,9 @@
         android:layout_width="0dp"
         android:layout_height="match_parent"
         android:layout_weight="@integer/setup_title_weight_in_screen"
-        android:orientation="vertical">
+        android:orientation="vertical"
+        android:layout_marginEnd="@dimen/setup_title_end_margin"
+        android:layout_marginRight="@dimen/setup_title_end_margin">
         <include layout="@layout/setup_steps_title" />
     </LinearLayout>
     <LinearLayout
diff --git a/java/res/layout-land/setup_welcome_screen.xml b/java/res/layout-land/setup_welcome_screen.xml
index 8b162e2..38aea2c 100644
--- a/java/res/layout-land/setup_welcome_screen.xml
+++ b/java/res/layout-land/setup_welcome_screen.xml
@@ -27,7 +27,9 @@
         android:layout_width="0dp"
         android:layout_height="match_parent"
         android:layout_weight="@integer/setup_title_weight_in_screen"
-        android:orientation="vertical">
+        android:orientation="vertical"
+        android:layout_marginEnd="@dimen/setup_title_end_margin"
+        android:layout_marginRight="@dimen/setup_title_end_margin">
         <include layout="@layout/setup_welcome_title" />
     </LinearLayout>
     <LinearLayout
diff --git a/java/res/layout/setup_welcome_video.xml b/java/res/layout/setup_welcome_video.xml
index 8c04e63..c39411e 100644
--- a/java/res/layout/setup_welcome_video.xml
+++ b/java/res/layout/setup_welcome_video.xml
@@ -25,24 +25,27 @@
         android:orientation="horizontal"
         android:paddingTop="@dimen/setup_welcome_video_vertical_margin"
         android:paddingBottom="@dimen/setup_welcome_video_vertical_margin">
-        <View
-            android:layout_weight="@integer/setup_welcome_video_left_padding_weight_in_screen"
-            android:layout_width="0dp"
-            android:layout_height="0dp" />
-        <VideoView
-            android:id="@+id/setup_welcome_video"
-            android:background="@color/setup_background"
+        <LinearLayout
+            android:id="@+id/setup_welcome_video_frame"
             android:layout_weight="@integer/setup_welcome_video_weight_in_screen"
             android:layout_width="0dp"
-            android:layout_height="wrap_content" />
-        <ImageView
-            android:id="@+id/setup_welcome_image"
-            android:visibility="gone"
-            android:layout_weight="@integer/setup_welcome_video_weight_in_screen"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content" />
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:padding="1dp"
+            android:background="@color/setup_welcome_video_margin_color" >
+            <VideoView
+                android:id="@+id/setup_welcome_video"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:background="@color/setup_background" />
+            <ImageView
+                android:id="@+id/setup_welcome_image"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone" />
+        </LinearLayout>
         <View
-            android:layout_weight="@integer/setup_welcome_video_right_padding_weight_in_screen"
+            android:layout_weight="@integer/setup_welcome_video_end_padding_weight_in_screen"
             android:layout_width="0dp"
             android:layout_height="0dp" />
     </LinearLayout>
diff --git a/java/res/raw/setup_welcome_image.png b/java/res/raw/setup_welcome_image.png
index 17e3111..db5dc34 100644
--- a/java/res/raw/setup_welcome_image.png
+++ b/java/res/raw/setup_welcome_image.png
Binary files differ
diff --git a/java/res/raw/setup_welcome_video.mp4 b/java/res/raw/setup_welcome_video.mp4
index 09357d8..8208525 100644
--- a/java/res/raw/setup_welcome_video.mp4
+++ b/java/res/raw/setup_welcome_video.mp4
Binary files differ
diff --git a/java/res/values-h1200dp-port/setup-dimens-large-tablet-port.xml b/java/res/values-h1200dp-port/setup-dimens-large-tablet-port.xml
index ad61c1a..d1df81e 100644
--- a/java/res/values-h1200dp-port/setup-dimens-large-tablet-port.xml
+++ b/java/res/values-h1200dp-port/setup-dimens-large-tablet-port.xml
@@ -33,8 +33,8 @@
     <dimen name="setup_step_horizontal_line_height">2dp</dimen>
     <integer name="setup_title_weight_in_screen">40</integer>
     <integer name="setup_body_weight_in_screen">60</integer>
+    <dimen name="setup_title_end_margin">24dp</dimen>
     <dimen name="setup_welcome_video_vertical_margin">24dp</dimen>
-    <integer name="setup_welcome_video_weight_in_screen">50</integer>
-    <integer name="setup_welcome_video_left_padding_weight_in_screen">25</integer>
-    <integer name="setup_welcome_video_right_padding_weight_in_screen">25</integer>
+    <integer name="setup_welcome_video_weight_in_screen">70</integer>
+    <integer name="setup_welcome_video_end_padding_weight_in_screen">30</integer>
 </resources>
diff --git a/java/res/values-h330dp-land/setup-dimens-large-phone-land.xml b/java/res/values-h330dp-land/setup-dimens-large-phone-land.xml
index 69a8a7a..babc05b 100644
--- a/java/res/values-h330dp-land/setup-dimens-large-phone-land.xml
+++ b/java/res/values-h330dp-land/setup-dimens-large-phone-land.xml
@@ -33,8 +33,8 @@
     <dimen name="setup_step_horizontal_line_height">2dp</dimen>
     <integer name="setup_title_weight_in_screen">40</integer>
     <integer name="setup_body_weight_in_screen">60</integer>
+    <dimen name="setup_title_end_margin">24dp</dimen>
     <dimen name="setup_welcome_video_vertical_margin">24dp</dimen>
-    <integer name="setup_welcome_video_weight_in_screen">80</integer>
-    <integer name="setup_welcome_video_left_padding_weight_in_screen">10</integer>
-    <integer name="setup_welcome_video_right_padding_weight_in_screen">10</integer>
+    <integer name="setup_welcome_video_weight_in_screen">70</integer>
+    <integer name="setup_welcome_video_end_padding_weight_in_screen">30</integer>
 </resources>
diff --git a/java/res/values-h520dp-land/setup-dimens-small-tablet-land.xml b/java/res/values-h520dp-land/setup-dimens-small-tablet-land.xml
index 6a14d59..7725874 100644
--- a/java/res/values-h520dp-land/setup-dimens-small-tablet-land.xml
+++ b/java/res/values-h520dp-land/setup-dimens-small-tablet-land.xml
@@ -33,8 +33,8 @@
     <dimen name="setup_step_horizontal_line_height">2dp</dimen>
     <integer name="setup_title_weight_in_screen">40</integer>
     <integer name="setup_body_weight_in_screen">60</integer>
+    <dimen name="setup_title_end_margin">24dp</dimen>
     <dimen name="setup_welcome_video_vertical_margin">24dp</dimen>
     <integer name="setup_welcome_video_weight_in_screen">60</integer>
-    <integer name="setup_welcome_video_left_padding_weight_in_screen">20</integer>
-    <integer name="setup_welcome_video_right_padding_weight_in_screen">20</integer>
+    <integer name="setup_welcome_video_end_padding_weight_in_screen">40</integer>
 </resources>
diff --git a/java/res/values-h540dp-port/setup-dimens-large-phone-port.xml b/java/res/values-h540dp-port/setup-dimens-large-phone-port.xml
index b8dd33d..42d2284 100644
--- a/java/res/values-h540dp-port/setup-dimens-large-phone-port.xml
+++ b/java/res/values-h540dp-port/setup-dimens-large-phone-port.xml
@@ -33,8 +33,8 @@
     <dimen name="setup_step_horizontal_line_height">2dp</dimen>
     <integer name="setup_title_weight_in_screen">40</integer>
     <integer name="setup_body_weight_in_screen">60</integer>
+    <dimen name="setup_title_end_margin">24dp</dimen>
     <dimen name="setup_welcome_video_vertical_margin">24dp</dimen>
-    <integer name="setup_welcome_video_weight_in_screen">80</integer>
-    <integer name="setup_welcome_video_left_padding_weight_in_screen">10</integer>
-    <integer name="setup_welcome_video_right_padding_weight_in_screen">10</integer>
+    <integer name="setup_welcome_video_weight_in_screen">70</integer>
+    <integer name="setup_welcome_video_end_padding_weight_in_screen">30</integer>
 </resources>
diff --git a/java/res/values-h720dp-land/setup-dimens-large-tablet-land.xml b/java/res/values-h720dp-land/setup-dimens-large-tablet-land.xml
index 0004a3c..b5f0e5c 100644
--- a/java/res/values-h720dp-land/setup-dimens-large-tablet-land.xml
+++ b/java/res/values-h720dp-land/setup-dimens-large-tablet-land.xml
@@ -33,8 +33,8 @@
     <dimen name="setup_step_horizontal_line_height">2dp</dimen>
     <integer name="setup_title_weight_in_screen">40</integer>
     <integer name="setup_body_weight_in_screen">60</integer>
+    <dimen name="setup_title_end_margin">24dp</dimen>
     <dimen name="setup_welcome_video_vertical_margin">24dp</dimen>
-    <integer name="setup_welcome_video_weight_in_screen">50</integer>
-    <integer name="setup_welcome_video_left_padding_weight_in_screen">25</integer>
-    <integer name="setup_welcome_video_right_padding_weight_in_screen">25</integer>
+    <integer name="setup_welcome_video_weight_in_screen">70</integer>
+    <integer name="setup_welcome_video_end_padding_weight_in_screen">30</integer>
 </resources>
diff --git a/java/res/values-h800dp-port/setup-dimens-small-tablet-port.xml b/java/res/values-h800dp-port/setup-dimens-small-tablet-port.xml
index 87c991c..770b4e8 100644
--- a/java/res/values-h800dp-port/setup-dimens-small-tablet-port.xml
+++ b/java/res/values-h800dp-port/setup-dimens-small-tablet-port.xml
@@ -33,8 +33,8 @@
     <dimen name="setup_step_horizontal_line_height">2dp</dimen>
     <integer name="setup_title_weight_in_screen">40</integer>
     <integer name="setup_body_weight_in_screen">60</integer>
+    <dimen name="setup_title_end_margin">24dp</dimen>
     <dimen name="setup_welcome_video_vertical_margin">24dp</dimen>
     <integer name="setup_welcome_video_weight_in_screen">60</integer>
-    <integer name="setup_welcome_video_left_padding_weight_in_screen">20</integer>
-    <integer name="setup_welcome_video_right_padding_weight_in_screen">20</integer>
+    <integer name="setup_welcome_video_end_padding_weight_in_screen">40</integer>
 </resources>
diff --git a/java/res/values-land/setup-dimens-small-phone-land.xml b/java/res/values-land/setup-dimens-small-phone-land.xml
index 63f4661..e6dbaa7 100644
--- a/java/res/values-land/setup-dimens-small-phone-land.xml
+++ b/java/res/values-land/setup-dimens-small-phone-land.xml
@@ -33,8 +33,8 @@
     <dimen name="setup_step_horizontal_line_height">2dp</dimen>
     <integer name="setup_title_weight_in_screen">40</integer>
     <integer name="setup_body_weight_in_screen">60</integer>
-    <dimen name="setup_welcome_video_vertical_margin">24dp</dimen>
-    <integer name="setup_welcome_video_weight_in_screen">80</integer>
-    <integer name="setup_welcome_video_left_padding_weight_in_screen">10</integer>
-    <integer name="setup_welcome_video_right_padding_weight_in_screen">10</integer>
+    <dimen name="setup_title_end_margin">12dp</dimen>
+    <dimen name="setup_welcome_video_vertical_margin">12dp</dimen>
+    <integer name="setup_welcome_video_weight_in_screen">60</integer>
+    <integer name="setup_welcome_video_end_padding_weight_in_screen">40</integer>
 </resources>
diff --git a/java/res/values-ms/strings-appname.xml b/java/res/values-ms/strings-appname.xml
index 1f9501a..76d1d29 100644
--- a/java/res/values-ms/strings-appname.xml
+++ b/java/res/values-ms/strings-appname.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_name" msgid="5940510615957428904">"Papan kekunci Android (AOSP)"</string>
+    <string name="english_ime_name" msgid="5940510615957428904">"Papan Kekunci Android (AOSP)"</string>
     <string name="spell_checker_service_name" msgid="1254221805440242662">"Penyemak Ejaan Android (AOSP)"</string>
     <string name="english_ime_settings" msgid="5760361067176802794">"Tetapan Papan Kekunci Android (AOSP)"</string>
     <string name="android_spell_checker_settings" msgid="6123949487832861885">"Tetapan Penyemak Ejaan Android (AOSP)"</string>
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index fe1a3cd..bb001ef 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -177,7 +177,7 @@
     <string name="setup_steps_title" msgid="6400373034871816182">"Menyediakan <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_step1_title" msgid="3147967630253462315">"Dayakan <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_step1_instruction" msgid="2578631936624637241">"Sila semak \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" dlm ttpn Bhs &amp; input. Ini mbnarkn apl djlnkn pd pranti anda."</string>
-    <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> sudah didayakan dlm ttpn Bahasa &amp; input anda, jd langkah ini tlh selesai. Beralih ke langkah seterusnya!"</string>
+    <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> sudah didayakan dalam tetapan Bahasa &amp; input anda, jadi langkah ini telah selesai. Beralih ke langkah seterusnya!"</string>
     <string name="setup_step1_action" msgid="4366513534999901728">"Dayakan dalam Tetapan"</string>
     <string name="setup_step2_title" msgid="6860725447906690594">"Beralih ke <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_step2_instruction" msgid="9141481964870023336">"Seterusnya, pilih \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" sebagai kaedah input teks aktif anda."</string>
@@ -233,7 +233,7 @@
     <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Edit perkataan"</string>
     <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Edit"</string>
     <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Padam"</string>
-    <string name="user_dict_settings_empty_text" msgid="558499587532668203">"Anda tidak mempunyai sebarang perkataan dalam kamus pengguna. Tambah perkataan dengan menyentuh butang Tambah (+)."</string>
+    <string name="user_dict_settings_empty_text" msgid="558499587532668203">"Anda tidak mempunyai sebarang perkataan dalam kamus pengguna. Tambahkan perkataan dengan menyentuh butang Tambah (+)."</string>
     <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"Untuk semua bahasa"</string>
     <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"Lebih banyak bahasa..."</string>
     <string name="user_dict_settings_delete" msgid="110413335187193859">"Padam"</string>
diff --git a/java/res/values-port/setup-dimens-small-phone-port.xml b/java/res/values-port/setup-dimens-small-phone-port.xml
index 34f4d92..a3b18af 100644
--- a/java/res/values-port/setup-dimens-small-phone-port.xml
+++ b/java/res/values-port/setup-dimens-small-phone-port.xml
@@ -33,8 +33,8 @@
     <dimen name="setup_step_horizontal_line_height">2dp</dimen>
     <integer name="setup_title_weight_in_screen">40</integer>
     <integer name="setup_body_weight_in_screen">60</integer>
+    <dimen name="setup_title_end_margin">16dp</dimen>
     <dimen name="setup_welcome_video_vertical_margin">16dp</dimen>
-    <integer name="setup_welcome_video_weight_in_screen">80</integer>
-    <integer name="setup_welcome_video_left_padding_weight_in_screen">10</integer>
-    <integer name="setup_welcome_video_right_padding_weight_in_screen">10</integer>
+    <integer name="setup_welcome_video_weight_in_screen">70</integer>
+    <integer name="setup_welcome_video_end_padding_weight_in_screen">30</integer>
 </resources>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 25592b1..907eee8 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -177,7 +177,7 @@
     <string name="setup_steps_title" msgid="6400373034871816182">"Configurando o <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_step1_title" msgid="3147967630253462315">"Ative o <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_step1_instruction" msgid="2578631936624637241">"Marque \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" em \"Configurações de idioma e entrada\" para autorizar a execução."</string>
-    <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> já está ativado em suas configurações de idioma e entrada. Esta estapa está concluída. Vamos avançar para a próxima!"</string>
+    <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> já está ativado em suas configurações de idioma e entrada. Esta etapa está concluída. Vamos avançar para a próxima!"</string>
     <string name="setup_step1_action" msgid="4366513534999901728">"Ativar em \"Configurações\""</string>
     <string name="setup_step2_title" msgid="6860725447906690594">"Abra o <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_step2_instruction" msgid="9141481964870023336">"Em seguida, selecione \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" como o método de entrada de texto ativo."</string>
diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml
index 8a8049f..daa167c 100644
--- a/java/res/values/colors.xml
+++ b/java/res/values/colors.xml
@@ -58,4 +58,5 @@
     <color name="setup_text_dark">#FF707070</color>
     <color name="setup_text_action">@android:color/holo_blue_light</color>
     <color name="setup_step_background">@android:color/background_light</color>
+    <color name="setup_welcome_video_margin_color">#FFCCCCCC</color>
 </resources>
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 742860b..d3a21f2 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -31,7 +31,7 @@
     <bool name="config_default_next_word_prediction">true</bool>
     <bool name="config_default_sound_enabled">false</bool>
     <bool name="config_default_vibration_enabled">true</bool>
-    <integer name="config_max_vibration_duration">250</integer> <!-- milliseconds -->
+    <integer name="config_max_vibration_duration">100</integer> <!-- milliseconds -->
     <integer name="config_delay_update_suggestions">100</integer>
     <integer name="config_delay_update_old_suggestions">300</integer>
     <integer name="config_delay_update_shift_state">100</integer>
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index b6413b3..98ae76c 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -102,7 +102,7 @@
 
     <!-- Gesture trail parameters -->
     <!-- Minimum distance between gesture trail sampling points. -->
-    <dimen name="gesture_trail_min_sampling_distance">6.4dp</dimen>
+    <dimen name="gesture_trail_min_sampling_distance">9.6dp</dimen>
     <!-- Maximum angular threshold between gesture trails interpolation segments in degree. -->
     <integer name="gesture_trail_max_interpolation_angular_threshold">15</integer>
     <!-- Maximum distance threshold between gesture trails interpolation segments. -->
diff --git a/java/res/values/keypress-vibration-durations.xml b/java/res/values/keypress-vibration-durations.xml
index ac502f5..9ce5051 100644
--- a/java/res/values/keypress-vibration-durations.xml
+++ b/java/res/values/keypress-vibration-durations.xml
@@ -42,7 +42,7 @@
         <!-- LG Optimus G -->
         <item>MODEL=LG-E97[013]|LS970|L-01E:MANUFACTURER=LGE,15</item>
         <!-- HTC One X -->
-        <item>MODEL=HTC One X:MANUFACTURER=HTC,15</item>
+        <item>MODEL=HTC One X:MANUFACTURER=HTC,20</item>
         <!-- Motorola Razor M -->
         <item>MODEL=XT907:MANUFACTURER=motorola,30</item>
         <!-- Sony Xperia Z -->
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
index 60d09d6..9eeee5b 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
@@ -27,8 +27,9 @@
      *
      * @param primaryCode the unicode of the key being pressed. If the touch is not on a valid key,
      *            the value will be zero.
+     * @param isSinglePointer true if pressing has occurred while no other key is being pressed.
      */
-    public void onPressKey(int primaryCode);
+    public void onPressKey(int primaryCode, boolean isSinglePointer);
 
     /**
      * Called when the user releases a key. This is sent after the {@link #onCodeInput} is called.
@@ -88,6 +89,11 @@
     public void onCancelInput();
 
     /**
+     * Called when user finished sliding key input.
+     */
+    public void onFinishSlidingInput();
+
+    /**
      * Send a non-"code input" custom request to the listener.
      * @return true if the request has been consumed, false otherwise.
      */
@@ -97,7 +103,7 @@
         public static final Adapter EMPTY_LISTENER = new Adapter();
 
         @Override
-        public void onPressKey(int primaryCode) {}
+        public void onPressKey(int primaryCode, boolean isSinglePointer) {}
         @Override
         public void onReleaseKey(int primaryCode, boolean withSliding) {}
         @Override
@@ -115,6 +121,8 @@
         @Override
         public void onCancelInput() {}
         @Override
+        public void onFinishSlidingInput() {}
+        @Override
         public boolean onCustomRequest(int requestCode) {
             return false;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 39afe90..ad08d64 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -216,19 +216,19 @@
         mState.onResetKeyboardStateToAlphabet();
     }
 
-    public void onPressKey(final int code) {
+    public void onPressKey(final int code, final boolean isSinglePointer) {
         if (isVibrateAndSoundFeedbackRequired()) {
             mFeedbackManager.hapticAndAudioFeedback(code, mKeyboardView);
         }
-        mState.onPressKey(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState());
+        mState.onPressKey(code, isSinglePointer, mLatinIME.getCurrentAutoCapsState());
     }
 
     public void onReleaseKey(final int code, final boolean withSliding) {
         mState.onReleaseKey(code, withSliding);
     }
 
-    public void onCancelInput() {
-        mState.onCancelInput(isSinglePointer());
+    public void onFinishSlidingInput() {
+        mState.onFinishSlidingInput();
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
@@ -346,15 +346,11 @@
         return mKeyboardView != null && !mKeyboardView.isInSlidingKeyInput();
     }
 
-    private boolean isSinglePointer() {
-        return mKeyboardView != null && mKeyboardView.getPointerCount() == 1;
-    }
-
     /**
      * Updates state machine to figure out when to automatically switch back to the previous mode.
      */
     public void onCodeInput(final int code) {
-        mState.onCodeInput(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState());
+        mState.onCodeInput(code, mLatinIME.getCurrentAutoCapsState());
     }
 
     public MainKeyboardView getMainKeyboardView() {
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 3201d2e..6c6fc61 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -1100,10 +1100,6 @@
         return false;
     }
 
-    public int getPointerCount() {
-        return mOldPointerCount;
-    }
-
     @Override
     public boolean dispatchTouchEvent(MotionEvent event) {
         if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 5a2af80..1742393 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -459,7 +459,7 @@
             return false;
         }
         if (key.isEnabled()) {
-            mListener.onPressKey(key.mCode);
+            mListener.onPressKey(key.mCode, getActivePointerTrackerCount() == 1);
             final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged;
             mKeyboardLayoutHasBeenChanged = false;
             mTimerProxy.startTypingStateTimer(key);
@@ -527,6 +527,13 @@
         }
     }
 
+    private void callListenerOnFinishSlidingInput() {
+        if (DEBUG_LISTENER) {
+            Log.d(TAG, String.format("[%d] onFinishSlidingInput", mPointerId));
+        }
+        mListener.onFinishSlidingInput();
+    }
+
     private void callListenerOnCancelInput() {
         if (DEBUG_LISTENER) {
             Log.d(TAG, String.format("[%d] onCancelInput", mPointerId));
@@ -1036,7 +1043,7 @@
 
     private void processSildeOutFromOldKey(final Key oldKey) {
         setReleasedKeyGraphics(oldKey);
-        callListenerOnRelease(oldKey, oldKey.mCode, true);
+        callListenerOnRelease(oldKey, oldKey.mCode, true /* withSliding */);
         startSlidingKeyInput(oldKey);
         mTimerProxy.cancelKeyTimers();
     }
@@ -1168,6 +1175,8 @@
 
     private void onUpEventInternal(final int x, final int y, final long eventTime) {
         mTimerProxy.cancelKeyTimers();
+        final boolean isInSlidingKeyInput = mIsInSlidingKeyInput;
+        final boolean isInSlidingKeyInputFromModifier = mIsInSlidingKeyInputFromModifier;
         resetSlidingKeyInput();
         mIsDetectingGesture = false;
         final Key currentKey = mCurrentKey;
@@ -1188,7 +1197,7 @@
 
         if (sInGesture) {
             if (currentKey != null) {
-                callListenerOnRelease(currentKey, currentKey.mCode, true);
+                callListenerOnRelease(currentKey, currentKey.mCode, true /* withSliding */);
             }
             mayEndBatchInput(eventTime);
             return;
@@ -1197,8 +1206,13 @@
         if (mIsTrackingForActionDisabled) {
             return;
         }
-        if (currentKey != null && !currentKey.isRepeatable()) {
-            detectAndSendKey(currentKey, mKeyX, mKeyY, eventTime);
+        if (currentKey != null && currentKey.isRepeatable() && !isInSlidingKeyInput) {
+            // Repeatable key has been registered in {@link #onDownEventInternal(int,int,long)}.
+            return;
+        }
+        detectAndSendKey(currentKey, mKeyX, mKeyY, eventTime);
+        if (isInSlidingKeyInputFromModifier) {
+            callListenerOnFinishSlidingInput();
         }
     }
 
@@ -1251,7 +1265,7 @@
         if (key == null) return;
         if (!key.isRepeatable()) return;
         // Don't start key repeat when we are in sliding input mode.
-        if (mIsInSlidingKeyInputFromModifier) return;
+        if (mIsInSlidingKeyInput) return;
         onRegisterKey(key);
         mTimerProxy.startKeyRepeatTimer(this);
     }
@@ -1313,7 +1327,7 @@
         // doesn't have its more keys. (e.g. spacebar, globe key)
         // We always need to start the long press timer if the key has its more keys regardless of
         // whether or not we are in the sliding input mode.
-        if (mIsInSlidingKeyInputFromModifier && key.mMoreKeys == null) return;
+        if (mIsInSlidingKeyInput && key.mMoreKeys == null) return;
         mTimerProxy.startLongPressTimer(this);
     }
 
@@ -1325,7 +1339,7 @@
 
         final int code = key.mCode;
         callListenerOnCodeInput(key, code, x, y, eventTime);
-        callListenerOnRelease(key, code, false);
+        callListenerOnRelease(key, code, false /* withSliding */);
     }
 
     private void printTouchEvent(final String title, final int x, final int y,
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 962bde9..6af1bd7 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -28,9 +28,9 @@
  * This class contains all keyboard state transition logic.
  *
  * The input events are {@link #onLoadKeyboard()}, {@link #onSaveKeyboardState()},
- * {@link #onPressKey(int, boolean, int)}, {@link #onReleaseKey(int, boolean)},
- * {@link #onCodeInput(int, boolean, int)}, {@link #onCancelInput(boolean)},
- * {@link #onUpdateShiftState(int, int)}, {@link #onLongPressTimeout(int)}.
+ * {@link #onPressKey(int,boolean,int)}, {@link #onReleaseKey(int,boolean)},
+ * {@link #onCodeInput(int,int)}, {@link #onFinishSlidingInput()}, {@link #onCancelInput()},
+ * {@link #onUpdateShiftState(int,int)}, {@link #onLongPressTimeout(int)}.
  *
  * The actions are {@link SwitchActions}'s methods.
  */
@@ -74,6 +74,7 @@
     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;
 
     private boolean mIsAlphabetMode;
@@ -525,6 +526,9 @@
             } else if (mAlphabetShiftState.isShiftLockShifted() && withSliding) {
                 // In shift locked state, shift has been pressed and slid out to other key.
                 setShiftLocked(true);
+            } else if (mAlphabetShiftState.isManualShifted() && withSliding) {
+                // Shift has been pressed and slid out to other key.
+                mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_SHIFT;
             } else if (isShiftLocked && !mAlphabetShiftState.isShiftLockShifted()
                     && (mShiftKeyState.isPressing() || mShiftKeyState.isPressingOnShifted())
                     && !withSliding) {
@@ -554,17 +558,21 @@
         mShiftKeyState.onRelease();
     }
 
-    public void onCancelInput(final boolean isSinglePointer) {
+    public void onFinishSlidingInput() {
         if (DEBUG_EVENT) {
-            Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this);
+            Log.d(TAG, "onFinishSlidingInput: " + this);
         }
         // Switch back to the previous keyboard mode if the user cancels sliding input.
-        if (isSinglePointer) {
-            if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
-                toggleAlphabetAndSymbols();
-            } else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) {
-                toggleShiftInSymbols();
-            }
+        switch (mSwitchState) {
+        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;
         }
     }
 
@@ -577,10 +585,9 @@
         return c == Constants.CODE_SPACE || c == Constants.CODE_ENTER;
     }
 
-    public void onCodeInput(final int code, final boolean isSinglePointer, final int autoCaps) {
+    public void onCodeInput(final int code, final int autoCaps) {
         if (DEBUG_EVENT) {
             Log.d(TAG, "onCodeInput: code=" + Constants.printableCode(code)
-                    + " single=" + isSinglePointer
                     + " autoCaps=" + autoCaps + " " + this);
         }
 
@@ -593,23 +600,12 @@
                 } else {
                     mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
                 }
-            } else if (isSinglePointer) {
-                // Switch back to the previous keyboard mode if the user pressed the mode change key
-                // and slid to other key, then released the finger.
-                // If the user cancels the sliding input, switching back to the previous keyboard
-                // mode is handled by {@link #onCancelInput}.
-                toggleAlphabetAndSymbols();
             }
             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;
-            } else if (isSinglePointer) {
-                // Switch back to the previous keyboard mode if the user pressed the shift key on
-                // symbol mode and slid to other key, then released the finger.
-                toggleShiftInSymbols();
-                mSwitchState = SWITCH_STATE_SYMBOL;
             }
             break;
         case SWITCH_STATE_SYMBOL_BEGIN:
@@ -650,6 +646,7 @@
         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;
         }
     }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
index 8901f99..31ef3cd 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
@@ -48,6 +48,9 @@
 
     public void add(final Element pointer) {
         synchronized (mExpandableArrayOfActivePointers) {
+            if (DEBUG) {
+                Log.d(TAG, "add: " + pointer + " " + this);
+            }
             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
             final int arraySize = mArraySize;
             if (arraySize < expandableArray.size()) {
@@ -61,24 +64,27 @@
 
     public void remove(final Element pointer) {
         synchronized (mExpandableArrayOfActivePointers) {
+            if (DEBUG) {
+                Log.d(TAG, "remove: " + pointer + " " + this);
+            }
             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
             final int arraySize = mArraySize;
-            int newSize = 0;
+            int newIndex = 0;
             for (int index = 0; index < arraySize; index++) {
                 final Element element = expandableArray.get(index);
                 if (element == pointer) {
-                    if (newSize != index) {
+                    if (newIndex != index) {
                         Log.w(TAG, "Found duplicated element in remove: " + pointer);
                     }
                     continue; // Remove this element from the expandableArray.
                 }
-                if (newSize != index) {
+                if (newIndex != index) {
                     // Shift this element toward the beginning of the expandableArray.
-                    expandableArray.set(newSize, element);
+                    expandableArray.set(newIndex, element);
                 }
-                newSize++;
+                newIndex++;
             }
-            mArraySize = newSize;
+            mArraySize = newIndex;
         }
     }
 
@@ -95,8 +101,8 @@
             }
             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
             final int arraySize = mArraySize;
-            int newSize, index;
-            for (newSize = index = 0; index < arraySize; index++) {
+            int newIndex, index;
+            for (newIndex = index = 0; index < arraySize; index++) {
                 final Element element = expandableArray.get(index);
                 if (element == pointer) {
                     break; // Stop releasing elements.
@@ -105,29 +111,30 @@
                     element.onPhantomUpEvent(eventTime);
                     continue; // Remove this element from the expandableArray.
                 }
-                if (newSize != index) {
+                if (newIndex != index) {
                     // Shift this element toward the beginning of the expandableArray.
-                    expandableArray.set(newSize, element);
+                    expandableArray.set(newIndex, element);
                 }
-                newSize++;
+                newIndex++;
             }
             // Shift rest of the expandableArray.
             int count = 0;
             for (; index < arraySize; index++) {
                 final Element element = expandableArray.get(index);
                 if (element == pointer) {
-                    if (count > 0) {
+                    count++;
+                    if (count > 1) {
                         Log.w(TAG, "Found duplicated element in releaseAllPointersOlderThan: "
                                 + pointer);
                     }
-                    count++;
                 }
-                if (newSize != index) {
-                    expandableArray.set(newSize, expandableArray.get(index));
-                    newSize++;
+                if (newIndex != index) {
+                    // Shift this element toward the beginning of the expandableArray.
+                    expandableArray.set(newIndex, expandableArray.get(index));
                 }
+                newIndex++;
             }
-            mArraySize = newSize;
+            mArraySize = newIndex;
         }
     }
 
@@ -146,26 +153,26 @@
             }
             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
             final int arraySize = mArraySize;
-            int newSize = 0, count = 0;
+            int newIndex = 0, count = 0;
             for (int index = 0; index < arraySize; index++) {
                 final Element element = expandableArray.get(index);
                 if (element == pointer) {
-                    if (count > 0) {
+                    count++;
+                    if (count > 1) {
                         Log.w(TAG, "Found duplicated element in releaseAllPointersExcept: "
                                 + pointer);
                     }
-                    count++;
                 } else {
                     element.onPhantomUpEvent(eventTime);
                     continue; // Remove this element from the expandableArray.
                 }
-                if (newSize != index) {
+                if (newIndex != index) {
                     // Shift this element toward the beginning of the expandableArray.
-                    expandableArray.set(newSize, element);
+                    expandableArray.set(newIndex, element);
                 }
-                newSize++;
+                newIndex++;
             }
-            mArraySize = newSize;
+            mArraySize = newIndex;
         }
     }
 
@@ -202,6 +209,9 @@
 
     public void cancelAllPointerTracker() {
         synchronized (mExpandableArrayOfActivePointers) {
+            if (DEBUG) {
+                Log.d(TAG, "cancelAllPointerTracker: " + this);
+            }
             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
             final int arraySize = mArraySize;
             for (int index = 0; index < arraySize; index++) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index fdd470c..9caec55 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1752,9 +1752,16 @@
 
     // Called from PointerTracker through the KeyboardActionListener interface
     @Override
+    public void onFinishSlidingInput() {
+        // User finished sliding input.
+        mKeyboardSwitcher.onFinishSlidingInput();
+    }
+
+    // Called from PointerTracker through the KeyboardActionListener interface
+    @Override
     public void onCancelInput() {
         // User released a finger outside any key
-        mKeyboardSwitcher.onCancelInput();
+        // Nothing to do so far.
     }
 
     @Override
@@ -2612,8 +2619,8 @@
     // Callback called by PointerTracker through the KeyboardActionListener. This is called when a
     // key is depressed; release matching call is onReleaseKey below.
     @Override
-    public void onPressKey(final int primaryCode) {
-        mKeyboardSwitcher.onPressKey(primaryCode);
+    public void onPressKey(final int primaryCode, final boolean isSinglePointer) {
+        mKeyboardSwitcher.onPressKey(primaryCode, isSinglePointer);
     }
 
     // Callback by PointerTracker through the KeyboardActionListener. This is called when a key
diff --git a/java/src/com/android/inputmethod/latin/SeekBarDialogPreference.java b/java/src/com/android/inputmethod/latin/SeekBarDialogPreference.java
index 9819a02..7c4156c 100644
--- a/java/src/com/android/inputmethod/latin/SeekBarDialogPreference.java
+++ b/java/src/com/android/inputmethod/latin/SeekBarDialogPreference.java
@@ -59,7 +59,7 @@
 
     public void setInterface(final ValueProxy proxy) {
         mValueProxy = proxy;
-        setSummary(getValueText(proxy.readValue(getKey())));
+        setSummary(getValueText(clipValue(proxy.readValue(getKey()))));
     }
 
     private String getValueText(final int value) {
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
index 3406ecf..0d25bc3 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
@@ -27,6 +27,7 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.inputmethod.InputMethodInfo;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -199,6 +200,11 @@
                 welcomeVideoView.setVisibility(View.GONE);
                 welcomeImageView.setImageResource(R.raw.setup_welcome_image);
                 welcomeImageView.setVisibility(View.VISIBLE);
+                // Remove unnecessary light gray background around still image.
+                final ViewGroup videoFrame = (ViewGroup)findViewById(
+                        R.id.setup_welcome_video_frame);
+                videoFrame.setBackgroundColor(getResources().getColor(R.color.setup_background));
+                videoFrame.requestLayout();
                 return true;
             }
         });
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
index a3f9dbd..d5b9d1d 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
@@ -352,30 +352,34 @@
         // Alphabet -> shift key + letter -> alphabet.
         // Press and slide from shift key, enter alphabet shifted.
         pressAndSlideFromKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
-        // Enter/release letter key, switch back to alphabet.
-        pressAndReleaseKey('Z', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED);
+        // Enter/release letter keys, switch back to alphabet.
+        pressAndSlideFromKey('A', ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        stopSlidingOnKey('Z', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED);
 
         // Alphabet -> "?123" key + letter -> alphabet.
         // Press and slide from "123?" key, enter symbols.
         pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
-        // Enter/release into symbol letter key, switch back to alphabet.
-        pressAndReleaseKey('!', SYMBOLS_UNSHIFTED, ALPHABET_UNSHIFTED);
+        // Enter/release into symbol letter keys, switch back to alphabet.
+        pressAndSlideFromKey('@', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        stopSlidingOnKey('!', SYMBOLS_UNSHIFTED, ALPHABET_UNSHIFTED);
 
         // Alphabet shifted -> shift key + letter -> alphabet.
         // Press/release shift key, enter alphabet shifted.
         pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
         // Press and slide from shift key, remain alphabet shifted.
         pressAndSlideFromKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
-        // Enter/release letter key, switch back to alphabet (not alphabet shifted).
-        pressAndReleaseKey('Z', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED);
+        // Enter/release letter keys, switch back to alphabet (not alphabet shifted).
+        pressAndSlideFromKey('A', ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        stopSlidingOnKey('Z', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED);
 
         // Alphabet shifted -> "?123" key + letter -> alphabet.
         // Press/release shift key, enter alphabet shifted.
         pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
         // Press and slide from "123?" key, enter symbols.
         pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
-        // Enter/release into symbol letter key, switch back to alphabet (not alphabet shifted).
-        pressAndReleaseKey('!', SYMBOLS_UNSHIFTED, ALPHABET_UNSHIFTED);
+        // Enter/release into symbol letter keys, switch back to alphabet (not alphabet shifted).
+        pressAndSlideFromKey('@', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        stopSlidingOnKey('!', SYMBOLS_UNSHIFTED, ALPHABET_UNSHIFTED);
 
         // Alphabet shift locked -> shift key + letter -> alphabet shift locked.
         // Long press shift key, enter alphabet shift locked.
@@ -383,14 +387,76 @@
                 ALPHABET_SHIFT_LOCKED);
         // Press and slide from "123?" key, enter symbols.
         pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
-        // Enter/release into symbol letter key, switch back to alphabet shift locked.
-        pressAndReleaseKey('!', SYMBOLS_UNSHIFTED, ALPHABET_SHIFT_LOCKED);
+        // Enter/release into symbol letter keys, switch back to alphabet shift locked.
+        pressAndSlideFromKey('!', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        stopSlidingOnKey('!', SYMBOLS_UNSHIFTED, ALPHABET_SHIFT_LOCKED);
 
         // Alphabet shift locked -> "?123" key + letter -> alphabet shift locked.
         // Press and slide from shift key, enter alphabet shifted.
         pressAndSlideFromKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCKED);
+        // Enter/release letter keys, switch back to shift locked.
+        pressAndSlideFromKey('A', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+        stopSlidingOnKey('Z', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+    }
+
+    // Cancel sliding input in alphabet.
+    public void testSlidingAlphabetCancel() {
+        // Alphabet -> shift key + letter -> cancel -> alphabet.
+        // Press and slide from shift key, enter alphabet shifted.
+        pressAndSlideFromKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        // Press and slide from shift key, enter alphabet shifted.
+        pressAndSlideFromKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        // Enter/release letter key, remains in alphabet shifted.
+        pressAndSlideFromKey('Z', ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        // Cancel sliding, switch back to alphabet.
+        stopSlidingAndCancel(ALPHABET_UNSHIFTED);
+
+        // Alphabet -> "?123" key + letter -> cancel -> alphabet.
+        // Press and slide from "123?" key, enter symbols.
+        pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Enter/release into symbol letter key, remains in symbols.
+        pressAndSlideFromKey('!', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Cancel sliding, switch back to alphabet.
+        stopSlidingAndCancel(ALPHABET_UNSHIFTED);
+
+        // Alphabet shifted -> shift key + letter -> cancel -> alphabet.
+        // Press/release shift key, enter alphabet shifted.
+        pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        // Press and slide from shift key, remain alphabet shifted.
+        pressAndSlideFromKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        // Enter/release letter key, remains in alphabet shifted.
+        pressAndSlideFromKey('Z', ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        // Cancel sliding, switch back to alphabet (not alphabet shifted).
+        stopSlidingAndCancel(ALPHABET_UNSHIFTED);
+
+        // Alphabet shifted -> "?123" key + letter -> cancel -> alphabet.
+        // Press/release shift key, enter alphabet shifted.
+        pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        // Press and slide from "123?" key, enter symbols.
+        pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Enter/release into symbol letter key, remains in symbols.
+        pressAndSlideFromKey('!', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Cancel sliding, switch back to alphabet (not alphabet shifted).
+        stopSlidingAndCancel(ALPHABET_UNSHIFTED);
+
+        // Alphabet shift locked -> shift key + letter -> cancel -> alphabet shift locked.
+        // Long press shift key, enter alphabet shift locked.
+        longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+                ALPHABET_SHIFT_LOCKED);
+        // Press and slide from "123?" key, enter symbols.
+        pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Enter/release into symbol letter key, remains in symbols.
+        pressAndSlideFromKey('!', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Cancel sliding, switch back to alphabet shift locked.
+        stopSlidingAndCancel( ALPHABET_SHIFT_LOCKED);
+
+        // Alphabet shift locked -> "?123" key + letter -> cancel -> alphabet shift locked.
+        // Press and slide from shift key, enter alphabet shifted.
+        pressAndSlideFromKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCKED);
+        // Enter/release letter key, remains in alphabet shift locked.
+        pressAndSlideFromKey('Z', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
         // Enter/release letter key, switch back to shift locked.
-        pressAndReleaseKey('Z', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+        stopSlidingAndCancel(ALPHABET_SHIFT_LOCKED);
     }
 
     // Sliding input in symbols.
@@ -398,16 +464,18 @@
         // Symbols -> "=\<" key + letter -> symbols.
         // Press/release "?123" key, enter into symbols.
         pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
-        // Press and slide from shift key, enter symols shifted.
+        // Press and slide from shift key, enter symbols shifted.
         pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
-        // Enter/release symbol shifted letter key, switch back to symbols.
-        pressAndReleaseKey('~', SYMBOLS_SHIFTED, SYMBOLS_UNSHIFTED);
+        // Enter/release symbol shifted letter keys, switch back to symbols.
+        pressAndSlideFromKey('|', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
+        stopSlidingOnKey('~', SYMBOLS_SHIFTED, SYMBOLS_UNSHIFTED);
 
         // Symbols -> "ABC" key + letter -> Symbols.
         // Press and slide from "ABC" key, enter alphabet.
         pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
-        // Enter/release letter key, switch back to symbols.
-        pressAndReleaseKey('a', ALPHABET_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Enter/release letter keys, switch back to symbols.
+        pressAndSlideFromKey('z', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        stopSlidingOnKey('a', ALPHABET_UNSHIFTED, SYMBOLS_UNSHIFTED);
         // Press/release "ABC" key, switch to alphabet.
         pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
 
@@ -421,8 +489,9 @@
         pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
         // Press and slide from "ABC" key.
         pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
-        // Enter/release letter key, switch back to symbols.
-        pressAndReleaseKey('a', ALPHABET_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Enter/release letter keys, switch back to symbols.
+        pressAndSlideFromKey('z', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        stopSlidingOnKey('a', ALPHABET_UNSHIFTED, SYMBOLS_UNSHIFTED);
         // Press/release "ABC" key, switch to alphabet (not alphabet shifted).
         pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
 
@@ -437,8 +506,9 @@
         pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
         // Press and slide from "ABC" key, enter alphabet shift locked.
         pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
-        // Enter/release letter key, switch back to symbols.
-        pressAndReleaseKey('A', ALPHABET_SHIFT_LOCKED, SYMBOLS_UNSHIFTED);
+        // Enter/release letter keys, switch back to symbols.
+        pressAndSlideFromKey('Z', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+        stopSlidingOnKey('A', ALPHABET_SHIFT_LOCKED, SYMBOLS_UNSHIFTED);
         // Press/release "ABC" key, switch to alphabet shift locked.
         pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
 
@@ -453,8 +523,85 @@
         pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
         // Press and slide from "=\<" key, enter symbols shifted.
         pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
-        // Enter/release symbols shift letter key, switch back to symbols.
-        pressAndReleaseKey('~', SYMBOLS_SHIFTED, SYMBOLS_UNSHIFTED);
+        // Enter/release symbols shift letter keys, switch back to symbols.
+        pressAndSlideFromKey('|', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
+        stopSlidingOnKey('~', SYMBOLS_SHIFTED, SYMBOLS_UNSHIFTED);
+        // Press/release "ABC" key, switch to alphabet shift locked.
+        pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+    }
+
+    // Cancel sliding input in symbols.
+    public void testSlidingSymbolsCancel() {
+        // Symbols -> "=\<" key + letter -> cancel -> symbols.
+        // Press/release "?123" key, enter into symbols.
+        pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Press and slide from shift key, enter symbols shifted.
+        pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
+        // Enter/release symbol shifted letter key, remains in symbols shifted.
+        pressAndSlideFromKey('|', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
+        // Cancel sliding, switch back to symbols.
+        stopSlidingAndCancel(SYMBOLS_UNSHIFTED);
+
+        // Symbols -> "ABC" key + letter -> Symbols.
+        // Press and slide from "ABC" key, enter alphabet.
+        pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        // Enter/release letter keys, remains in alphabet.
+        pressAndSlideFromKey('z', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        // Cancel sliding, switch back to symbols.
+        stopSlidingAndCancel(SYMBOLS_UNSHIFTED);
+        // Press/release "ABC" key, switch to alphabet.
+        pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+
+        // Alphabet shifted -> symbols -> "ABC" key + letter -> symbols ->
+        // alphabet.
+        // Load keyboard
+        loadKeyboard(ALPHABET_UNSHIFTED);
+        // Press/release shift key, enter alphabet shifted.
+        pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        // Press/release "?123" key, enter into symbols.
+        pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Press and slide from "ABC" key.
+        pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        // Enter/release letter key, remains in alphabet.
+        pressAndSlideFromKey('z', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        // Cancel sliding, switch back to symbols.
+        stopSlidingAndCancel(SYMBOLS_UNSHIFTED);
+        // Press/release "ABC" key, switch to alphabet (not alphabet shifted).
+        pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+
+        // Alphabet shift locked -> symbols -> "ABC" key + letter -> symbols ->
+        // alphabet shift locked.
+        // Load keyboard
+        loadKeyboard(ALPHABET_UNSHIFTED);
+        // Long press shift key, enter alphabet shift locked.
+        longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+                ALPHABET_SHIFT_LOCKED);
+        // Press/release "?123" key, enter into symbols.
+        pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Press and slide from "ABC" key, enter alphabet shift locked.
+        pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+        // Enter/release letter key, remains in alphabet shifted.
+        pressAndSlideFromKey('Z', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+        // Cancel sliding, switch back to symbols.
+        stopSlidingAndCancel(SYMBOLS_UNSHIFTED);
+        // Press/release "ABC" key, switch to alphabet shift locked.
+        pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+
+        // Alphabet shift locked -> symbols -> "=\<" key + letter -> symbols ->
+        // alphabet shift locked.
+        // Load keyboard
+        loadKeyboard(ALPHABET_UNSHIFTED);
+        // Long press shift key, enter alphabet shift locked.
+        longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+                ALPHABET_SHIFT_LOCKED);
+        // Press/release "?123" key, enter into symbols.
+        pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Press and slide from "=\<" key, enter symbols shifted.
+        pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
+        // Enter/release symbols shift letter key, remains in symbols shifted.
+        pressAndSlideFromKey('|', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
+        // Cancel sliding, switch back to symbols.
+        stopSlidingAndCancel(SYMBOLS_UNSHIFTED);
         // Press/release "ABC" key, switch to alphabet shift locked.
         pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
     }
@@ -468,14 +615,16 @@
         pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
         // Press and slide from shift key, enter symbols.
         pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
-        // Enter/release symbol letter key, switch back to symbols shifted.
-        pressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_SHIFTED);
+        // Enter/release symbol letter keys, switch back to symbols shifted.
+        pressAndSlideFromKey('2', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        stopSlidingOnKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_SHIFTED);
 
         // Symbols shifted -> "ABC" key + letter -> symbols shifted.
         // Press and slide from "ABC" key, enter alphabet.
         pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
-        // Enter/release letter key, switch back to symbols shifted.
-        pressAndReleaseKey('a', ALPHABET_UNSHIFTED, SYMBOLS_SHIFTED);
+        // Enter/release letter keys, switch back to symbols shifted.
+        pressAndSlideFromKey('z', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        stopSlidingOnKey('a', ALPHABET_UNSHIFTED, SYMBOLS_SHIFTED);
         // Press/release "ABC" key, switch to alphabet.
         pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
 
@@ -491,8 +640,9 @@
         pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
         // Press and slide from "ABC" key.
         pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
-        // Enter/release letter key, switch back to symbols shifted.
-        pressAndReleaseKey('a', ALPHABET_UNSHIFTED, SYMBOLS_SHIFTED);
+        // Enter/release letter keys, switch back to symbols shifted.
+        pressAndSlideFromKey('z', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        stopSlidingOnKey('a', ALPHABET_UNSHIFTED, SYMBOLS_SHIFTED);
         // Press/release "ABC" key, switch to alphabet (not alphabet shifted).
         pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
 
@@ -509,8 +659,9 @@
         pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
         // Press and slide from "ABC" key.
         pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
-        // Enter/release letter key, switch back to symbols shifted.
-        pressAndReleaseKey('A', ALPHABET_SHIFT_LOCKED, SYMBOLS_SHIFTED);
+        // Enter/release letter keys, switch back to symbols shifted.
+        pressAndSlideFromKey('Z', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+        stopSlidingOnKey('A', ALPHABET_SHIFT_LOCKED, SYMBOLS_SHIFTED);
         // Press/release "ABC" key, switch to alphabet shift locked.
         pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
 
@@ -527,8 +678,93 @@
         pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
         // Press and slide from "?123" key.
         pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
-        // Enter/release symbol letter key, switch back to symbols shifted.
-        pressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_SHIFTED);
+        // Enter/release symbol letter keys, switch back to symbols shifted.
+        pressAndSlideFromKey('2', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        stopSlidingOnKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_SHIFTED);
+        // Press/release "ABC" key, switch to alphabet shift locked.
+        pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+    }
+
+    // Cancel sliding input in symbols shifted.
+    public void testSlidingSymbolsShiftedCancel() {
+        // Symbols shifted -> "?123" + letter -> symbols shifted.
+        // Press/release "?123" key, enter into symbols.
+        pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Press/release "=\<" key, enter into symbols shifted.
+        pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
+        // Press and slide from shift key, enter symbols.
+        pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Enter/release symbol letter key, remains in symbols.
+        pressAndSlideFromKey('2', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Cancel sliding, switch back to symbols shifted.
+        stopSlidingAndCancel(SYMBOLS_SHIFTED);
+
+        // Symbols shifted -> "ABC" key + letter -> symbols shifted.
+        // Press and slide from "ABC" key, enter alphabet.
+        pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        // Enter/release letter key, remains in alphabet.
+        pressAndSlideFromKey('z', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        // Cancel sliding, switch back to symbols shifted.
+        stopSlidingAndCancel(SYMBOLS_SHIFTED);
+        // Press/release "ABC" key, switch to alphabet.
+        pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+
+        // Alphabet shifted -> symbols shifted -> "ABC" + letter -> symbols shifted ->
+        // alphabet.
+        // Load keyboard
+        loadKeyboard(ALPHABET_UNSHIFTED);
+        // Press/release shift key, enter alphabet shifted.
+        pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        // Press/release "?123" key, enter into symbols.
+        pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Press/release "=\<" key, enter into symbols shifted.
+        pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
+        // Press and slide from "ABC" key.
+        pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        // Enter/release letter key, remains in alphabet.
+        pressAndSlideFromKey('z', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+        // Cancel sliding, switch back to symbols shifted.
+        stopSlidingAndCancel(SYMBOLS_SHIFTED);
+        // Press/release "ABC" key, switch to alphabet (not alphabet shifted).
+        pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
+
+        // Alphabet shift locked -> symbols shifted -> "ABC" + letter -> symbols shifted ->
+        // alphabet shift locked.
+        // Load keyboard
+        loadKeyboard(ALPHABET_UNSHIFTED);
+        // Long press shift key, enter alphabet shift locked.
+        longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+                ALPHABET_SHIFT_LOCKED);
+        // Press/release "?123" key, enter into symbols.
+        pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Press/release "=\<" key, enter into symbols shifted.
+        pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
+        // Press and slide from "ABC" key.
+        pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+        // Enter/release letter key, remains in alphabet shift locked.
+        pressAndSlideFromKey('Z', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+        // Cancel sliding, switch back to symbols shifted.
+        stopSlidingAndCancel(SYMBOLS_SHIFTED);
+        // Press/release "ABC" key, switch to alphabet shift locked.
+        pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
+
+        // Alphabet shift locked -> symbols shifted -> "?123" + letter -> symbols shifted ->
+        // alphabet shift locked.
+        // Load keyboard
+        loadKeyboard(ALPHABET_UNSHIFTED);
+        // Long press shift key, enter alphabet shift locked.
+        longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+                ALPHABET_SHIFT_LOCKED);
+        // Press/release "?123" key, enter into symbols.
+        pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Press/release "=\<" key, enter into symbols shifted.
+        pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED);
+        // Press and slide from "?123" key.
+        pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Enter/release symbol letter key, remains in symbols.
+        pressAndSlideFromKey('2', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Cancel sliding, switch back to symbols shifted.
+        stopSlidingAndCancel(SYMBOLS_SHIFTED);
         // Press/release "ABC" key, switch to alphabet shift locked.
         pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
     }
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
index 5e94aeb..e06ca06 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
@@ -71,7 +71,7 @@
     }
 
     public void releaseKey(final int code, final int afterRelease) {
-        mSwitcher.onCodeInput(code, SINGLE);
+        mSwitcher.onCodeInput(code);
         mSwitcher.onReleaseKey(code, NOT_SLIDING);
         assertLayout("afterRelease", afterRelease, mSwitcher.getLayoutId());
     }
@@ -87,7 +87,7 @@
     }
 
     public void chordingReleaseKey(final int code, final int afterRelease) {
-        mSwitcher.onCodeInput(code, MULTI);
+        mSwitcher.onCodeInput(code);
         mSwitcher.onReleaseKey(code, NOT_SLIDING);
         assertLayout("afterRelease", afterRelease, mSwitcher.getLayoutId());
     }
@@ -104,6 +104,19 @@
         assertLayout("afterSlide", afterSlide, mSwitcher.getLayoutId());
     }
 
+    public void stopSlidingOnKey(final int code, final int afterPress, final int afterSlide) {
+        pressKey(code, afterPress);
+        mSwitcher.onCodeInput(code);
+        mSwitcher.onReleaseKey(code, NOT_SLIDING);
+        mSwitcher.onFinishSlidingInput();
+        assertLayout("afterSlide", afterSlide, mSwitcher.getLayoutId());
+    }
+
+    public void stopSlidingAndCancel(final int afterCancelSliding) {
+        mSwitcher.onFinishSlidingInput();
+        assertLayout("afterCancelSliding", afterCancelSliding, mSwitcher.getLayoutId());
+    }
+
     public void longPressKey(final int code, final int afterPress, final int afterLongPress) {
         pressKey(code, afterPress);
         mSwitcher.onLongPressTimeout(code);
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
index 74506d2..2544b6c 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
@@ -185,7 +185,7 @@
         }
     }
 
-    public void onCodeInput(final int code, final boolean isSinglePointer) {
+    public void onCodeInput(final int code) {
         if (mAutoCapsMode == MockConstants.CAP_MODE_WORDS) {
             if (Constants.isLetterCode(code)) {
                 mAutoCapsState = (code == MockConstants.CODE_AUTO_CAPS_TRIGGER)
@@ -194,10 +194,10 @@
         } else {
             mAutoCapsState = mAutoCapsMode;
         }
-        mState.onCodeInput(code, isSinglePointer, mAutoCapsState);
+        mState.onCodeInput(code, mAutoCapsState);
     }
 
-    public void onCancelInput(final boolean isSinglePointer) {
-        mState.onCancelInput(isSinglePointer);
+    public void onFinishSlidingInput() {
+        mState.onFinishSlidingInput();
     }
-}
\ No newline at end of file
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueueTests.java b/tests/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueueTests.java
index a572daa..279559c 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueueTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueueTests.java
@@ -66,23 +66,23 @@
     private final PointerTrackerQueue mQueue = new PointerTrackerQueue();
 
     public void testEmpty() {
-        assertEquals("empty queue", 0, mQueue.size());
-        assertEquals("empty queue", "[]", mQueue.toString());
+        assertEquals(0, mQueue.size());
+        assertEquals("[]", mQueue.toString());
     }
 
     public void testAdd() {
         mQueue.add(mElement1);
-        assertEquals("add element1", 1, mQueue.size());
-        assertEquals("after adding element1", "[1]", mQueue.toString());
+        assertEquals(1, mQueue.size());
+        assertEquals("[1]", mQueue.toString());
         mQueue.add(mElement2);
-        assertEquals("add element2", 2, mQueue.size());
-        assertEquals("after adding element2", "[1 2]", mQueue.toString());
+        assertEquals(2, mQueue.size());
+        assertEquals("[1 2]", mQueue.toString());
         mQueue.add(mElement3);
-        assertEquals("add element3", 3, mQueue.size());
-        assertEquals("after adding element3", "[1 2 3]", mQueue.toString());
+        assertEquals(3, mQueue.size());
+        assertEquals("[1 2 3]", mQueue.toString());
         mQueue.add(mElement4);
-        assertEquals("add element4", 4, mQueue.size());
-        assertEquals("after adding element4", "[1 2 3 4]", mQueue.toString());
+        assertEquals(4, mQueue.size());
+        assertEquals("[1 2 3 4]", mQueue.toString());
     }
 
     public void testRemove() {
@@ -94,33 +94,29 @@
         mQueue.add(mElement4);
 
         mQueue.remove(mElement2);
-        assertEquals("remove element2", 3, mQueue.size());
-        assertEquals("after removing element2", "[1 3 4]", mQueue.toString());
+        assertEquals(3, mQueue.size());
+        assertEquals("[1 3 4]", mQueue.toString());
         mQueue.remove(mElement4);
-        assertEquals("remove element4", 2, mQueue.size());
-        assertEquals("after removing element4", "[1 3]", mQueue.toString());
+        assertEquals(2, mQueue.size());
+        assertEquals("[1 3]", mQueue.toString());
         mQueue.remove(mElement4);
-        assertEquals("remove element4 again", 2, mQueue.size());
-        assertEquals("after removing element4 again", "[1 3]", mQueue.toString());
+        assertEquals(2, mQueue.size());
+        assertEquals("[1 3]", mQueue.toString());
         mQueue.remove(mElement1);
-        assertEquals("remove element1", 1, mQueue.size());
-        assertEquals("after removing element4", "[3]", mQueue.toString());
+        assertEquals(1, mQueue.size());
+        assertEquals("[3]", mQueue.toString());
         mQueue.remove(mElement3);
-        assertEquals("remove element3", 0, mQueue.size());
-        assertEquals("after removing element3", "[]", mQueue.toString());
+        assertEquals(0, mQueue.size());
+        assertEquals("[]", mQueue.toString());
         mQueue.remove(mElement1);
-        assertEquals("remove element1 again", 0, mQueue.size());
-        assertEquals("after removing element1 again", "[]", mQueue.toString());
+        assertEquals(0, mQueue.size());
+        assertEquals("[]", mQueue.toString());
 
-        assertEquals("after remove elements", 0, Element.sPhantomUpCount);
-        assertEquals("after remove element1",
-                Element.NOT_HAPPENED, mElement1.mPhantomUpEventTime);
-        assertEquals("after remove element2",
-                Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
-        assertEquals("after remove element3",
-                Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
-        assertEquals("after remove element4",
-                Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
+        assertEquals(0, Element.sPhantomUpCount);
+        assertEquals(Element.NOT_HAPPENED, mElement1.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
     }
 
     public void testAddAndRemove() {
@@ -132,38 +128,34 @@
         mQueue.add(mElement4);
 
         mQueue.remove(mElement2);
-        assertEquals("remove element2", 3, mQueue.size());
-        assertEquals("after removing element2", "[1 3 4]", mQueue.toString());
+        assertEquals(3, mQueue.size());
+        assertEquals("[1 3 4]", mQueue.toString());
         mQueue.remove(mElement4);
-        assertEquals("remove element4", 2, mQueue.size());
-        assertEquals("after removing element4", "[1 3]", mQueue.toString());
+        assertEquals(2, mQueue.size());
+        assertEquals("[1 3]", mQueue.toString());
         mQueue.add(mElement2);
-        assertEquals("add element2", 3, mQueue.size());
-        assertEquals("after adding element2", "[1 3 2]", mQueue.toString());
+        assertEquals(3, mQueue.size());
+        assertEquals("[1 3 2]", mQueue.toString());
         mQueue.remove(mElement4);
-        assertEquals("remove element4 again", 3, mQueue.size());
-        assertEquals("after removing element4 again", "[1 3 2]", mQueue.toString());
+        assertEquals(3, mQueue.size());
+        assertEquals("[1 3 2]", mQueue.toString());
         mQueue.remove(mElement1);
-        assertEquals("remove element1", 2, mQueue.size());
-        assertEquals("after removing element4", "[3 2]", mQueue.toString());
+        assertEquals(2, mQueue.size());
+        assertEquals("[3 2]", mQueue.toString());
         mQueue.add(mElement1);
-        assertEquals("add element1", 3, mQueue.size());
-        assertEquals("after adding element1", "[3 2 1]", mQueue.toString());
+        assertEquals(3, mQueue.size());
+        assertEquals("[3 2 1]", mQueue.toString());
         mQueue.remove(mElement3);
-        assertEquals("remove element3", 2, mQueue.size());
-        assertEquals("after removing element3", "[2 1]", mQueue.toString());
+        assertEquals(2, mQueue.size());
+        assertEquals("[2 1]", mQueue.toString());
         mQueue.remove(mElement1);
-        assertEquals("remove element1 again", 1, mQueue.size());
-        assertEquals("after removing element1 again", "[2]", mQueue.toString());
+        assertEquals(1, mQueue.size());
+        assertEquals("[2]", mQueue.toString());
 
-        assertEquals("after remove element1",
-                Element.NOT_HAPPENED, mElement1.mPhantomUpEventTime);
-        assertEquals("after remove element2",
-                Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
-        assertEquals("after remove element3",
-                Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
-        assertEquals("after remove element4",
-                Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement1.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
     }
 
     public void testReleaseAllPointers() {
@@ -176,20 +168,33 @@
         final long eventTime = 123;
         Element.sPhantomUpCount = 0;
         mQueue.releaseAllPointers(eventTime);
-        assertEquals("after releaseAllPointers", 4, Element.sPhantomUpCount);
-        assertEquals("after releaseAllPointers", 0, mQueue.size());
-        assertEquals("after releaseAllPointers", "[]", mQueue.toString());
-        assertEquals("after releaseAllPointers element1",
-                eventTime + 1, mElement1.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointers element2",
-                eventTime + 2, mElement2.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointers element3",
-                eventTime + 3, mElement3.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointers element4",
-                eventTime + 4, mElement4.mPhantomUpEventTime);
+        assertEquals(4, Element.sPhantomUpCount);
+        assertEquals(0, mQueue.size());
+        assertEquals("[]", mQueue.toString());
+        assertEquals(eventTime + 1, mElement1.mPhantomUpEventTime);
+        assertEquals(eventTime + 2, mElement2.mPhantomUpEventTime);
+        assertEquals(eventTime + 3, mElement3.mPhantomUpEventTime);
+        assertEquals(eventTime + 4, mElement4.mPhantomUpEventTime);
     }
 
-    public void testReleaseAllPointersOlderThan() {
+    public void testReleaseAllPointersOlderThanFirst() {
+        mElement2.mIsModifier = true;
+        mQueue.add(mElement1);
+        mQueue.add(mElement2);
+        mQueue.add(mElement3);
+
+        final long eventTime = 123;
+        Element.sPhantomUpCount = 0;
+        mQueue.releaseAllPointersOlderThan(mElement1, eventTime);
+        assertEquals(0, Element.sPhantomUpCount);
+        assertEquals(3, mQueue.size());
+        assertEquals("[1 2 3]", mQueue.toString());
+        assertEquals(Element.NOT_HAPPENED, mElement1.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
+    }
+
+    public void testReleaseAllPointersOlderThanLast() {
         mElement2.mIsModifier = true;
         mQueue.add(mElement1);
         mQueue.add(mElement2);
@@ -199,20 +204,34 @@
         final long eventTime = 123;
         Element.sPhantomUpCount = 0;
         mQueue.releaseAllPointersOlderThan(mElement4, eventTime);
-        assertEquals("after releaseAllPointersOlderThan", 2, Element.sPhantomUpCount);
-        assertEquals("after releaseAllPointersOlderThan", 2, mQueue.size());
-        assertEquals("after releaseAllPointersOlderThan", "[2 4]", mQueue.toString());
-        assertEquals("after releaseAllPointersOlderThan element1",
-                eventTime + 1, mElement1.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointersOlderThan element2",
-                Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointersOlderThan element3",
-                eventTime + 2, mElement3.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointersOlderThan element4",
-                Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
+        assertEquals(2, Element.sPhantomUpCount);
+        assertEquals(2, mQueue.size());
+        assertEquals("[2 4]", mQueue.toString());
+        assertEquals(eventTime + 1, mElement1.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
+        assertEquals(eventTime + 2, mElement3.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
     }
 
-    public void testReleaseAllPointersOlderThanWithoutModifier() {
+    public void testReleaseAllPointersOlderThanWithoutModifierMiddle() {
+        mQueue.add(mElement1);
+        mQueue.add(mElement2);
+        mQueue.add(mElement3);
+        mQueue.add(mElement4);
+
+        final long eventTime = 123;
+        Element.sPhantomUpCount = 0;
+        mQueue.releaseAllPointersOlderThan(mElement3, eventTime);
+        assertEquals(2, Element.sPhantomUpCount);
+        assertEquals(2, mQueue.size());
+        assertEquals("[3 4]", mQueue.toString());
+        assertEquals(eventTime + 1, mElement1.mPhantomUpEventTime);
+        assertEquals(eventTime + 2, mElement2.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
+    }
+
+    public void testReleaseAllPointersOlderThanWithoutModifierLast() {
         mQueue.add(mElement1);
         mQueue.add(mElement2);
         mQueue.add(mElement3);
@@ -221,19 +240,13 @@
         final long eventTime = 123;
         Element.sPhantomUpCount = 0;
         mQueue.releaseAllPointersOlderThan(mElement4, eventTime);
-        assertEquals("after releaseAllPointersOlderThan without modifier",
-                3, Element.sPhantomUpCount);
-        assertEquals("after releaseAllPointersOlderThan without modifier", 1, mQueue.size());
-        assertEquals("after releaseAllPointersOlderThan without modifier",
-                "[4]", mQueue.toString());
-        assertEquals("after releaseAllPointersOlderThan without modifier element1",
-                eventTime + 1, mElement1.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointersOlderThan without modifier element2",
-                eventTime + 2, mElement2.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointersOlderThan without modifier element3",
-                eventTime + 3, mElement3.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointersOlderThan without modifier element4",
-                Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
+        assertEquals(3, Element.sPhantomUpCount);
+        assertEquals(1, mQueue.size());
+        assertEquals("[4]", mQueue.toString());
+        assertEquals(eventTime + 1, mElement1.mPhantomUpEventTime);
+        assertEquals(eventTime + 2, mElement2.mPhantomUpEventTime);
+        assertEquals(eventTime + 3, mElement3.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
     }
 
     public void testReleaseAllPointersExcept() {
@@ -246,17 +259,13 @@
         final long eventTime = 123;
         Element.sPhantomUpCount = 0;
         mQueue.releaseAllPointersExcept(mElement3, eventTime);
-        assertEquals("after releaseAllPointersExcept", 3, Element.sPhantomUpCount);
-        assertEquals("after releaseAllPointersExcept", 1, mQueue.size());
-        assertEquals("after releaseAllPointersExcept", "[3]", mQueue.toString());
-        assertEquals("after releaseAllPointersExcept element1",
-                eventTime + 1, mElement1.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointersExcept element2",
-                eventTime + 2, mElement2.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointersExcept element3",
-                Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
-        assertEquals("after releaseAllPointersExcept element4",
-                eventTime + 3, mElement4.mPhantomUpEventTime);
+        assertEquals(3, Element.sPhantomUpCount);
+        assertEquals(1, mQueue.size());
+        assertEquals("[3]", mQueue.toString());
+        assertEquals(eventTime + 1, mElement1.mPhantomUpEventTime);
+        assertEquals(eventTime + 2, mElement2.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
+        assertEquals(eventTime + 3, mElement4.mPhantomUpEventTime);
     }
 
     public void testHasModifierKeyOlderThan() {
@@ -268,54 +277,46 @@
         mQueue.add(mElement3);
         mQueue.add(mElement4);
 
-        assertFalse("hasModifierKeyOlderThan element1", mQueue.hasModifierKeyOlderThan(mElement1));
-        assertFalse("hasModifierKeyOlderThan element2", mQueue.hasModifierKeyOlderThan(mElement2));
-        assertFalse("hasModifierKeyOlderThan element3", mQueue.hasModifierKeyOlderThan(mElement3));
-        assertFalse("hasModifierKeyOlderThan element4", mQueue.hasModifierKeyOlderThan(mElement4));
+        assertFalse(mQueue.hasModifierKeyOlderThan(mElement1));
+        assertFalse(mQueue.hasModifierKeyOlderThan(mElement2));
+        assertFalse(mQueue.hasModifierKeyOlderThan(mElement3));
+        assertFalse(mQueue.hasModifierKeyOlderThan(mElement4));
 
         mElement2.mIsModifier = true;
-        assertFalse("hasModifierKeyOlderThan element1", mQueue.hasModifierKeyOlderThan(mElement1));
-        assertFalse("hasModifierKeyOlderThan element2", mQueue.hasModifierKeyOlderThan(mElement2));
-        assertTrue("hasModifierKeyOlderThan element3", mQueue.hasModifierKeyOlderThan(mElement3));
-        assertTrue("hasModifierKeyOlderThan element4", mQueue.hasModifierKeyOlderThan(mElement4));
+        assertFalse(mQueue.hasModifierKeyOlderThan(mElement1));
+        assertFalse(mQueue.hasModifierKeyOlderThan(mElement2));
+        assertTrue(mQueue.hasModifierKeyOlderThan(mElement3));
+        assertTrue(mQueue.hasModifierKeyOlderThan(mElement4));
 
-        assertEquals("after hasModifierKeyOlderThan", 0, Element.sPhantomUpCount);
-        assertEquals("after hasModifierKeyOlderThan", 4, mQueue.size());
-        assertEquals("after hasModifierKeyOlderThan", "[1 2 3 4]", mQueue.toString());
-        assertEquals("after hasModifierKeyOlderThan element1",
-                Element.NOT_HAPPENED, mElement1.mPhantomUpEventTime);
-        assertEquals("after hasModifierKeyOlderThan element2",
-                Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
-        assertEquals("after hasModifierKeyOlderThan element3",
-                Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
-        assertEquals("after hasModifierKeyOlderThan element4",
-                Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
+        assertEquals(0, Element.sPhantomUpCount);
+        assertEquals(4, mQueue.size());
+        assertEquals("[1 2 3 4]", mQueue.toString());
+        assertEquals(Element.NOT_HAPPENED, mElement1.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
     }
 
     public void testIsAnyInSlidingKeyInput() {
         Element.sPhantomUpCount = 0;
-        assertFalse("isAnyInSlidingKeyInput empty", mQueue.isAnyInSlidingKeyInput());
+        assertFalse(mQueue.isAnyInSlidingKeyInput());
 
         mQueue.add(mElement1);
         mQueue.add(mElement2);
         mQueue.add(mElement3);
         mQueue.add(mElement4);
 
-        assertFalse("isAnyInSlidingKeyInput element1", mQueue.isAnyInSlidingKeyInput());
+        assertFalse(mQueue.isAnyInSlidingKeyInput());
 
         mElement3.mIsInSlidingKeyInput = true;
-        assertTrue("isAnyInSlidingKeyInput element1", mQueue.isAnyInSlidingKeyInput());
+        assertTrue(mQueue.isAnyInSlidingKeyInput());
 
-        assertEquals("after isAnyInSlidingKeyInput", 0, Element.sPhantomUpCount);
-        assertEquals("after isAnyInSlidingKeyInput", 4, mQueue.size());
-        assertEquals("after isAnyInSlidingKeyInput", "[1 2 3 4]", mQueue.toString());
-        assertEquals("after isAnyInSlidingKeyInput element1",
-                Element.NOT_HAPPENED, mElement1.mPhantomUpEventTime);
-        assertEquals("after isAnyInSlidingKeyInput element2",
-                Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
-        assertEquals("after isAnyInSlidingKeyInput element3",
-                Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
-        assertEquals("after isAnyInSlidingKeyInput element4",
-                Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
+        assertEquals(0, Element.sPhantomUpCount);
+        assertEquals(4, mQueue.size());
+        assertEquals("[1 2 3 4]", mQueue.toString());
+        assertEquals(Element.NOT_HAPPENED, mElement1.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement2.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement3.mPhantomUpEventTime);
+        assertEquals(Element.NOT_HAPPENED, mElement4.mPhantomUpEventTime);
     }
 }