Program: 45441
Project: 45441
Buggy source:
@Override public boolean onTouchEvent(MotionEvent ev){
  if (mLauncher.isWorkspaceLocked()) {
    return false;
  }
  if (mLauncher.isAllAppsVisible()) {
    if (!mScroller.isFinished()) {
      mScroller.abortAnimation();
    }
    snapToScreen(mCurrentScreen);
    return false;
  }
  if (mVelocityTracker == null) {
    mVelocityTracker=VelocityTracker.obtain();
  }
  mVelocityTracker.addMovement(ev);
  final int action=ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
    if (!mScroller.isFinished()) {
      mScroller.abortAnimation();
    }
  mLastMotionX=ev.getX();
mActivePointerId=ev.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
if (mTouchState == TOUCH_STATE_SCROLLING) {
final int pointerIndex=ev.findPointerIndex(mActivePointerId);
final float x=filterX(ev.getX(pointerIndex));
final float deltaX=mLastMotionX - x;
mLastMotionX=x;
if (deltaX < 0) {
if (mScrollX > 0) {
  scrollBy(Math.round(Math.max(-mScrollX,deltaX)),0);
  updateWallpaperOffset();
}
}
 else if (deltaX > 0) {
final int availableToScroll=getChildAt(getChildCount() - 1).getRight() - mScrollX - getWidth();
if (availableToScroll > 0) {
  scrollBy(Math.round(Math.min(availableToScroll,deltaX)),0);
  updateWallpaperOffset();
}
}
 else {
awakenScrollBars();
}
}
break;
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker=mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000,mMaximumVelocity);
final int velocityX=(int)velocityTracker.getXVelocity(mActivePointerId);
final int screenWidth=getWidth();
final int whichScreen=(mScrollX + (screenWidth / 2)) / screenWidth;
final float scrolledPos=(float)mScrollX / screenWidth;
if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
final int bound=scrolledPos < whichScreen ? mCurrentScreen - 1 : mCurrentScreen;
snapToScreen(Math.min(whichScreen,bound),velocityX,true);
}
 else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
final int bound=scrolledPos > whichScreen ? mCurrentScreen + 1 : mCurrentScreen;
snapToScreen(Math.max(whichScreen,bound),velocityX,true);
}
 else {
snapToScreen(whichScreen,0,true);
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker=null;
}
resetFilter();
}
mTouchState=TOUCH_STATE_REST;
mActivePointerId=INVALID_POINTER;
break;
case MotionEvent.ACTION_CANCEL:
mTouchState=TOUCH_STATE_REST;
mActivePointerId=INVALID_POINTER;
resetFilter();
break;
case MotionEvent.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
break;
}
return true;
}

Fixed version (ground truth):
@Override public boolean onTouchEvent(MotionEvent ev){
  if (mLauncher.isWorkspaceLocked()) {
    return false;
  }
  if (mLauncher.isAllAppsVisible()) {
    if (!mScroller.isFinished()) {
      mScroller.abortAnimation();
    }
    snapToScreen(mCurrentScreen);
    return false;
  }
  if (mVelocityTracker == null) {
    mVelocityTracker=VelocityTracker.obtain();
  }
  mVelocityTracker.addMovement(ev);
  final int action=ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
    if (!mScroller.isFinished()) {
      mScroller.abortAnimation();
    }
  mLastMotionX=ev.getX();
mActivePointerId=ev.getPointerId(0);
if (mTouchState == TOUCH_STATE_SCROLLING) {
enableChildrenCache(mCurrentScreen - 1,mCurrentScreen + 1);
}
break;
case MotionEvent.ACTION_MOVE:
if (mTouchState == TOUCH_STATE_SCROLLING) {
final int pointerIndex=ev.findPointerIndex(mActivePointerId);
final float x=filterX(ev.getX(pointerIndex));
final float deltaX=mLastMotionX - x;
mLastMotionX=x;
if (deltaX < 0) {
if (mScrollX > 0) {
scrollBy(Math.round(Math.max(-mScrollX,deltaX)),0);
updateWallpaperOffset();
}
}
 else if (deltaX > 0) {
final int availableToScroll=getChildAt(getChildCount() - 1).getRight() - mScrollX - getWidth();
if (availableToScroll > 0) {
scrollBy(Math.round(Math.min(availableToScroll,deltaX)),0);
updateWallpaperOffset();
}
}
 else {
awakenScrollBars();
}
}
break;
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker=mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000,mMaximumVelocity);
final int velocityX=(int)velocityTracker.getXVelocity(mActivePointerId);
final int screenWidth=getWidth();
final int whichScreen=(mScrollX + (screenWidth / 2)) / screenWidth;
final float scrolledPos=(float)mScrollX / screenWidth;
if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
final int bound=scrolledPos < whichScreen ? mCurrentScreen - 1 : mCurrentScreen;
snapToScreen(Math.min(whichScreen,bound),velocityX,true);
}
 else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
final int bound=scrolledPos > whichScreen ? mCurrentScreen + 1 : mCurrentScreen;
snapToScreen(Math.max(whichScreen,bound),velocityX,true);
}
 else {
snapToScreen(whichScreen,0,true);
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker=null;
}
resetFilter();
}
mTouchState=TOUCH_STATE_REST;
mActivePointerId=INVALID_POINTER;
break;
case MotionEvent.ACTION_CANCEL:
mTouchState=TOUCH_STATE_REST;
mActivePointerId=INVALID_POINTER;
resetFilter();
break;
case MotionEvent.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
break;
}
return true;
}