Program: 43306
Project: 43306
Buggy source:
private boolean onModifiedTouchEvent(MotionEvent me){
  int touchX=(int)me.getX() - mPaddingLeft;
  int touchY=(int)me.getY() + mVerticalCorrection - mPaddingTop;
  int action=me.getAction();
  long eventTime=me.getEventTime();
  int keyIndex=getKeyIndices(touchX,touchY,null);
  if (mGestureDetector.onTouchEvent(me)) {
    showPreview(NOT_A_KEY);
    mHandler.removeMessages(MSG_REPEAT);
    mHandler.removeMessages(MSG_LONGPRESS);
    return true;
  }
  if (mMiniKeyboardOnScreen) {
    return true;
  }
switch (action) {
case MotionEvent.ACTION_DOWN:
    mAbortKey=false;
  mStartX=touchX;
mStartY=touchY;
mLastCodeX=touchX;
mLastCodeY=touchY;
mLastKeyTime=0;
mCurrentKeyTime=0;
mLastKey=NOT_A_KEY;
mCurrentKey=keyIndex;
mDownTime=me.getEventTime();
mLastMoveTime=mDownTime;
checkMultiTap(eventTime,keyIndex);
mKeyboardActionListener.onPress(keyIndex != NOT_A_KEY ? mKeys[keyIndex].codes[0] : 0);
if (mCurrentKey >= 0 && mKeys[mCurrentKey].repeatable) {
mRepeatKeyIndex=mCurrentKey;
repeatKey();
Message msg=mHandler.obtainMessage(MSG_REPEAT);
mHandler.sendMessageDelayed(msg,REPEAT_START_DELAY);
}
if (mCurrentKey != NOT_A_KEY) {
Message msg=mHandler.obtainMessage(MSG_LONGPRESS,me);
mHandler.sendMessageDelayed(msg,LONGPRESS_TIMEOUT);
}
showPreview(keyIndex);
break;
case MotionEvent.ACTION_MOVE:
boolean continueLongPress=false;
if (keyIndex != NOT_A_KEY) {
if (mCurrentKey == NOT_A_KEY) {
mCurrentKey=keyIndex;
mCurrentKeyTime=eventTime - mDownTime;
}
 else {
if (keyIndex == mCurrentKey) {
mCurrentKeyTime+=eventTime - mLastMoveTime;
continueLongPress=true;
}
 else {
resetMultiTap();
mLastKey=mCurrentKey;
mLastCodeX=mLastX;
mLastCodeY=mLastY;
mLastKeyTime=mCurrentKeyTime + eventTime - mLastMoveTime;
mCurrentKey=keyIndex;
mCurrentKeyTime=0;
}
}
if (keyIndex != mRepeatKeyIndex) {
mHandler.removeMessages(MSG_REPEAT);
mRepeatKeyIndex=NOT_A_KEY;
}
}
if (!continueLongPress) {
mHandler.removeMessages(MSG_LONGPRESS);
if (keyIndex != NOT_A_KEY) {
Message msg=mHandler.obtainMessage(MSG_LONGPRESS,me);
mHandler.sendMessageDelayed(msg,LONGPRESS_TIMEOUT);
}
}
showPreview(keyIndex);
break;
case MotionEvent.ACTION_UP:
mHandler.removeMessages(MSG_SHOW_PREVIEW);
mHandler.removeMessages(MSG_REPEAT);
mHandler.removeMessages(MSG_LONGPRESS);
if (keyIndex == mCurrentKey) {
mCurrentKeyTime+=eventTime - mLastMoveTime;
}
 else {
resetMultiTap();
mLastKey=mCurrentKey;
mLastKeyTime=mCurrentKeyTime + eventTime - mLastMoveTime;
mCurrentKey=keyIndex;
mCurrentKeyTime=0;
}
if (mCurrentKeyTime < mLastKeyTime && mLastKey != NOT_A_KEY) {
mCurrentKey=mLastKey;
touchX=mLastCodeX;
touchY=mLastCodeY;
}
showPreview(NOT_A_KEY);
Arrays.fill(mKeyIndices,NOT_A_KEY);
if (mRepeatKeyIndex == NOT_A_KEY && !mMiniKeyboardOnScreen && !mAbortKey) {
detectAndSendKey(touchX,touchY,eventTime);
}
invalidateKey(keyIndex);
mRepeatKeyIndex=NOT_A_KEY;
break;
}
mLastX=touchX;
mLastY=touchY;
return true;
}

Fixed version (ground truth):
private boolean onModifiedTouchEvent(MotionEvent me){
  int touchX=(int)me.getX() - mPaddingLeft;
  int touchY=(int)me.getY() + mVerticalCorrection - mPaddingTop;
  int action=me.getAction();
  long eventTime=me.getEventTime();
  int keyIndex=getKeyIndices(touchX,touchY,null);
  if (mGestureDetector.onTouchEvent(me)) {
    showPreview(NOT_A_KEY);
    mHandler.removeMessages(MSG_REPEAT);
    mHandler.removeMessages(MSG_LONGPRESS);
    return true;
  }
  if (mMiniKeyboardOnScreen) {
    return true;
  }
switch (action) {
case MotionEvent.ACTION_DOWN:
    mAbortKey=false;
  mStartX=touchX;
mStartY=touchY;
mLastCodeX=touchX;
mLastCodeY=touchY;
mLastKeyTime=0;
mCurrentKeyTime=0;
mLastKey=NOT_A_KEY;
mCurrentKey=keyIndex;
mDownTime=me.getEventTime();
mLastMoveTime=mDownTime;
checkMultiTap(eventTime,keyIndex);
mKeyboardActionListener.onPress(keyIndex != NOT_A_KEY ? mKeys[keyIndex].codes[0] : 0);
if (mCurrentKey >= 0 && mKeys[mCurrentKey].repeatable) {
mRepeatKeyIndex=mCurrentKey;
repeatKey();
Message msg=mHandler.obtainMessage(MSG_REPEAT);
mHandler.sendMessageDelayed(msg,REPEAT_START_DELAY);
}
if (mCurrentKey != NOT_A_KEY) {
Message msg=mHandler.obtainMessage(MSG_LONGPRESS,me);
mHandler.sendMessageDelayed(msg,LONGPRESS_TIMEOUT);
}
showPreview(keyIndex);
break;
case MotionEvent.ACTION_MOVE:
boolean continueLongPress=false;
if (keyIndex != NOT_A_KEY) {
if (mCurrentKey == NOT_A_KEY) {
mCurrentKey=keyIndex;
mCurrentKeyTime=eventTime - mDownTime;
}
 else {
if (keyIndex == mCurrentKey) {
mCurrentKeyTime+=eventTime - mLastMoveTime;
continueLongPress=true;
}
 else if (mRepeatKeyIndex == NOT_A_KEY) {
resetMultiTap();
mLastKey=mCurrentKey;
mLastCodeX=mLastX;
mLastCodeY=mLastY;
mLastKeyTime=mCurrentKeyTime + eventTime - mLastMoveTime;
mCurrentKey=keyIndex;
mCurrentKeyTime=0;
}
}
}
if (!continueLongPress) {
mHandler.removeMessages(MSG_LONGPRESS);
if (keyIndex != NOT_A_KEY) {
Message msg=mHandler.obtainMessage(MSG_LONGPRESS,me);
mHandler.sendMessageDelayed(msg,LONGPRESS_TIMEOUT);
}
}
showPreview(mCurrentKey);
break;
case MotionEvent.ACTION_UP:
mHandler.removeMessages(MSG_SHOW_PREVIEW);
mHandler.removeMessages(MSG_REPEAT);
mHandler.removeMessages(MSG_LONGPRESS);
if (keyIndex == mCurrentKey) {
mCurrentKeyTime+=eventTime - mLastMoveTime;
}
 else {
resetMultiTap();
mLastKey=mCurrentKey;
mLastKeyTime=mCurrentKeyTime + eventTime - mLastMoveTime;
mCurrentKey=keyIndex;
mCurrentKeyTime=0;
}
if (mCurrentKeyTime < mLastKeyTime && mLastKey != NOT_A_KEY) {
mCurrentKey=mLastKey;
touchX=mLastCodeX;
touchY=mLastCodeY;
}
showPreview(NOT_A_KEY);
Arrays.fill(mKeyIndices,NOT_A_KEY);
if (mRepeatKeyIndex == NOT_A_KEY && !mMiniKeyboardOnScreen && !mAbortKey) {
detectAndSendKey(touchX,touchY,eventTime);
}
invalidateKey(keyIndex);
mRepeatKeyIndex=NOT_A_KEY;
break;
}
mLastX=touchX;
mLastY=touchY;
return true;
}