Program: 21971
Project: 21971
Buggy source:
@Override public boolean onTouchEvent(MotionEvent ev){
  if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
    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:
{
      final float y=ev.getY();
      if (!(mIsBeingDragged=inChild((int)ev.getX(),(int)y))) {
        return false;
      }
      if (!mScroller.isFinished()) {
        mScroller.abortAnimation();
      }
      mLastMotionY=y;
      mActivePointerId=ev.getPointerId(0);
      break;
    }
case MotionEvent.ACTION_MOVE:
  if (mIsBeingDragged) {
    final int activePointerIndex=ev.findPointerIndex(mActivePointerId);
    final float y=ev.getY(activePointerIndex);
    final int deltaY=(int)(mLastMotionY - y);
    mLastMotionY=y;
    final int oldX=mScrollX;
    final int oldY=mScrollY;
    final int range=getScrollRange();
    if (overscrollBy(0,deltaY,0,mScrollY,0,range,0,mOverscrollDistance,true)) {
      mVelocityTracker.clear();
    }
    onScrollChanged(mScrollX,mScrollY,oldX,oldY);
    final int pulledToY=oldY + deltaY;
    if (pulledToY < 0) {
      mEdgeGlowTop.onPull((float)deltaY / getHeight());
    }
 else     if (pulledToY > range) {
      mEdgeGlowBottom.onPull((float)deltaY / getHeight());
    }
  }
break;
case MotionEvent.ACTION_UP:
if (mIsBeingDragged) {
final VelocityTracker velocityTracker=mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000,mMaximumVelocity);
int initialVelocity=(int)velocityTracker.getYVelocity(mActivePointerId);
if (getChildCount() > 0) {
  if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
    fling(-initialVelocity);
  }
 else {
    final int bottom=getScrollRange();
    if (mScroller.springback(mScrollX,mScrollY,0,0,0,bottom)) {
      invalidate();
    }
  }
}
mActivePointerId=INVALID_POINTER;
mIsBeingDragged=false;
if (mVelocityTracker != null) {
  mVelocityTracker.recycle();
  mVelocityTracker=null;
}
if (mEdgeGlowTop != null) {
  mEdgeGlowTop.onRelease();
  mEdgeGlowBottom.onRelease();
}
}
break;
case MotionEvent.ACTION_CANCEL:
if (mIsBeingDragged && getChildCount() > 0) {
if (mScroller.springback(mScrollX,mScrollY,0,0,0,getScrollRange())) {
invalidate();
}
mActivePointerId=INVALID_POINTER;
mIsBeingDragged=false;
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker=null;
}
if (mEdgeGlowTop != null) {
mEdgeGlowTop.onRelease();
mEdgeGlowBottom.onRelease();
}
}
break;
case MotionEvent.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
break;
}
return true;
}

Fixed version (ground truth):
@Override public boolean onTouchEvent(MotionEvent ev){
  if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
    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:
{
      final float y=ev.getY();
      if (!(mIsBeingDragged=inChild((int)ev.getX(),(int)y))) {
        return false;
      }
      if (!mScroller.isFinished()) {
        mScroller.abortAnimation();
      }
      mLastMotionY=y;
      mActivePointerId=ev.getPointerId(0);
      break;
    }
case MotionEvent.ACTION_MOVE:
  if (mIsBeingDragged) {
    final int activePointerIndex=ev.findPointerIndex(mActivePointerId);
    final float y=ev.getY(activePointerIndex);
    final int deltaY=(int)(mLastMotionY - y);
    mLastMotionY=y;
    final int oldX=mScrollX;
    final int oldY=mScrollY;
    final int range=getScrollRange();
    if (overscrollBy(0,deltaY,0,mScrollY,0,range,0,mOverscrollDistance,true)) {
      mVelocityTracker.clear();
    }
    onScrollChanged(mScrollX,mScrollY,oldX,oldY);
    final int overscrollMode=getOverscrollMode();
    if (overscrollMode == OVERSCROLL_ALWAYS || (overscrollMode == OVERSCROLL_IF_CONTENT_SCROLLS && range > 0)) {
      final int pulledToY=oldY + deltaY;
      if (pulledToY < 0) {
        mEdgeGlowTop.onPull((float)deltaY / getHeight());
      }
 else       if (pulledToY > range) {
        mEdgeGlowBottom.onPull((float)deltaY / getHeight());
      }
    }
  }
break;
case MotionEvent.ACTION_UP:
if (mIsBeingDragged) {
final VelocityTracker velocityTracker=mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000,mMaximumVelocity);
int initialVelocity=(int)velocityTracker.getYVelocity(mActivePointerId);
if (getChildCount() > 0) {
  if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
    fling(-initialVelocity);
  }
 else {
    final int bottom=getScrollRange();
    if (mScroller.springback(mScrollX,mScrollY,0,0,0,bottom)) {
      invalidate();
    }
  }
}
mActivePointerId=INVALID_POINTER;
mIsBeingDragged=false;
if (mVelocityTracker != null) {
  mVelocityTracker.recycle();
  mVelocityTracker=null;
}
if (mEdgeGlowTop != null) {
  mEdgeGlowTop.onRelease();
  mEdgeGlowBottom.onRelease();
}
}
break;
case MotionEvent.ACTION_CANCEL:
if (mIsBeingDragged && getChildCount() > 0) {
if (mScroller.springback(mScrollX,mScrollY,0,0,0,getScrollRange())) {
invalidate();
}
mActivePointerId=INVALID_POINTER;
mIsBeingDragged=false;
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker=null;
}
if (mEdgeGlowTop != null) {
mEdgeGlowTop.onRelease();
mEdgeGlowBottom.onRelease();
}
}
break;
case MotionEvent.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
break;
}
return true;
}