Cancel long press shift key while chording input

Bug: 12123508
Change-Id: I693caad1f8ee47ebeb14419603d1fc29f6263a75
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index f9e78bf..a2528e0 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -70,6 +70,7 @@
         public void startKeyRepeatTimerOf(PointerTracker tracker, int repeatCount, int delay);
         public void startLongPressTimerOf(PointerTracker tracker, int delay);
         public void cancelLongPressTimerOf(PointerTracker tracker);
+        public void cancelLongPressShiftKeyTimers();
         public void cancelKeyTimersOf(PointerTracker tracker);
         public void startDoubleTapShiftKeyTimer();
         public void cancelDoubleTapShiftKeyTimer();
@@ -90,6 +91,8 @@
             @Override
             public void cancelLongPressTimerOf(PointerTracker tracker) {}
             @Override
+            public void cancelLongPressShiftKeyTimers() {}
+            @Override
             public void cancelKeyTimersOf(PointerTracker tracker) {}
             @Override
             public void startDoubleTapShiftKeyTimer() {}
@@ -1338,6 +1341,9 @@
     }
 
     private void startLongPressTimer(final Key key) {
+        // Note that we need to cancel all active long press shift key timers if any whenever we
+        // start a new long press timer for both non-shift and shift keys.
+        sTimerProxy.cancelLongPressShiftKeyTimers();
         if (sInGesture) return;
         if (key == null) return;
         if (!key.isLongPressEnabled()) return;
@@ -1349,6 +1355,7 @@
         if (mIsInDraggingFinger && key.getMoreKeys() == null) return;
 
         final int delay = getLongPressTimeout(key.getCode());
+        if (delay <= 0) return;
         sTimerProxy.startLongPressTimerOf(this, delay);
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
index 88d0878..3298a3f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
@@ -38,8 +38,9 @@
     private static final int MSG_TYPING_STATE_EXPIRED = 0;
     private static final int MSG_REPEAT_KEY = 1;
     private static final int MSG_LONGPRESS_KEY = 2;
-    private static final int MSG_DOUBLE_TAP_SHIFT_KEY = 3;
-    private static final int MSG_UPDATE_BATCH_INPUT = 4;
+    private static final int MSG_LONGPRESS_SHIFT_KEY = 3;
+    private static final int MSG_DOUBLE_TAP_SHIFT_KEY = 4;
+    private static final int MSG_UPDATE_BATCH_INPUT = 5;
 
     private final int mIgnoreAltCodeKeyTimeout;
     private final int mGestureRecognitionUpdateTime;
@@ -66,6 +67,7 @@
             tracker.onKeyRepeat(msg.arg1 /* code */, msg.arg2 /* repeatCount */);
             break;
         case MSG_LONGPRESS_KEY:
+        case MSG_LONGPRESS_SHIFT_KEY:
             cancelLongPressTimers();
             callbacks.onLongPress(tracker);
             break;
@@ -102,19 +104,31 @@
 
     @Override
     public void startLongPressTimerOf(final PointerTracker tracker, final int delay) {
-        if (delay <= 0) {
+        final Key key = tracker.getKey();
+        if (key == null) {
             return;
         }
-        sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, tracker), delay);
+        // Use a separate message id for long pressing shift key, because long press shift key
+        // timers should be canceled when other key is pressed.
+        final int messageId = (key.getCode() == Constants.CODE_SHIFT)
+                ? MSG_LONGPRESS_SHIFT_KEY : MSG_LONGPRESS_KEY;
+        sendMessageDelayed(obtainMessage(messageId, tracker), delay);
     }
 
     @Override
     public void cancelLongPressTimerOf(final PointerTracker tracker) {
         removeMessages(MSG_LONGPRESS_KEY, tracker);
+        removeMessages(MSG_LONGPRESS_SHIFT_KEY, tracker);
+    }
+
+    @Override
+    public void cancelLongPressShiftKeyTimers() {
+        removeMessages(MSG_LONGPRESS_SHIFT_KEY);
     }
 
     private void cancelLongPressTimers() {
         removeMessages(MSG_LONGPRESS_KEY);
+        removeMessages(MSG_LONGPRESS_SHIFT_KEY);
     }
 
     @Override