Program: 175952
Project: 175952
Buggy source:
@Override public boolean onTouchEvent(MotionEvent ev){
  if (getChildCount() == 0)   return false;
  if (mVelocityTracker == null) {
    mVelocityTracker=VelocityTracker.obtain();
  }
  mVelocityTracker.addMovement(ev);
  final int action=ev.getAction();
  final float x=ev.getX();
switch (action) {
case MotionEvent.ACTION_DOWN:
    if (!mScroller.isFinished()) {
      mScroller.abortAnimation();
    }
  mLastMotionX=x;
mTouchState=mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_MOVE:
final int xDiff=(int)Math.abs(x - mLastMotionX);
boolean xMoved=xDiff > mTouchSlop;
if (xMoved) {
mTouchState=TOUCH_STATE_SCROLLING;
}
if (mTouchState == TOUCH_STATE_SCROLLING) {
final int deltaX=(int)(mLastMotionX - x);
mLastMotionX=x;
final int scrollX=getScrollX();
if (deltaX < 0) {
if (scrollX > 0) {
scrollBy(Math.max(-scrollX,deltaX),0);
}
}
 else if (deltaX > 0) {
final int availableToScroll=getChildAt(getChildCount() - 1).getRight() - scrollX - getWidth();
if (availableToScroll > 0) {
scrollBy(Math.min(availableToScroll,deltaX),0);
}
}
return true;
}
break;
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker=mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000,mMaximumVelocity);
int velocityX=(int)velocityTracker.getXVelocity();
if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
snapToScreen(mCurrentScreen - 1);
}
 else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
snapToScreen(mCurrentScreen + 1);
}
 else {
snapToDestination();
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker=null;
}
}
mTouchState=TOUCH_STATE_REST;
break;
case MotionEvent.ACTION_CANCEL:
mTouchState=TOUCH_STATE_REST;
}
return false;
}

Fixed version (ground truth):
@Override public boolean onTouchEvent(MotionEvent ev){
  if (getChildCount() == 0)   return false;
  if (mVelocityTracker == null) {
    mVelocityTracker=VelocityTracker.obtain();
  }
  mVelocityTracker.addMovement(ev);
  final int action=ev.getAction();
  final float x=ev.getX();
switch (action) {
case MotionEvent.ACTION_DOWN:
    if (!mScroller.isFinished()) {
      mScroller.abortAnimation();
    }
  mLastMotionX=x;
mTouchState=mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_MOVE:
final int xDiff=(int)Math.abs(x - mLastMotionX);
boolean xMoved=xDiff > mTouchSlop;
if (xMoved) {
mTouchState=TOUCH_STATE_SCROLLING;
}
if (mTouchState == TOUCH_STATE_SCROLLING) {
final int deltaX=(int)(mLastMotionX - x);
mLastMotionX=x;
final int scrollX=getScrollX();
if (deltaX < 0) {
if (scrollX > 0) {
scrollBy(Math.max(-scrollX,deltaX),0);
}
}
 else if (deltaX > 0) {
final int availableToScroll=getChildAt(getChildCount() - 1).getRight() - scrollX - getWidth();
if (availableToScroll > 0) {
scrollBy(Math.min(availableToScroll,deltaX),0);
}
}
return true;
}
break;
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker=mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000,mMaximumVelocity);
int velocityX=(int)velocityTracker.getXVelocity();
if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
snapToScreen(mCurrentScreen - 1);
}
 else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
snapToScreen(mCurrentScreen + 1);
}
 else {
snapToDestination();
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker=null;
}
}
mTouchState=TOUCH_STATE_REST;
break;
case MotionEvent.ACTION_CANCEL:
mTouchState=TOUCH_STATE_REST;
}
return true;
}