Program: 25505
Project: 25505
Buggy source:
/** 
 * Process a touch event received by the parent view. This method will dispatch callback events as needed before returning. The parent view's onTouchEvent implementation should call this.
 * @param ev The touch event received by the parent view
 */
public void processTouchEvent(MotionEvent ev){
  final int action=MotionEventCompat.getActionMasked(ev);
  final int actionIndex=MotionEventCompat.getActionIndex(ev);
  if (action == MotionEvent.ACTION_DOWN) {
    cancel();
  }
  if (mVelocityTracker == null) {
    mVelocityTracker=VelocityTracker.obtain();
  }
  mVelocityTracker.addMovement(ev);
switch (action) {
case MotionEvent.ACTION_DOWN:
{
      final float x=ev.getX();
      final float y=ev.getY();
      final int pointerId=MotionEventCompat.getPointerId(ev,0);
      final View toCapture=findTopChildUnder((int)x,(int)y);
      saveInitialMotion(x,y,pointerId);
      tryCaptureViewForDrag(toCapture,pointerId);
      final int edgesTouched=mInitialEdgesTouched[pointerId];
      if ((edgesTouched & mTrackingEdges) != 0) {
        mCallback.onEdgeTouched(edgesTouched & mTrackingEdges,pointerId);
      }
      break;
    }
case MotionEventCompat.ACTION_POINTER_DOWN:
{
    final int pointerId=MotionEventCompat.getPointerId(ev,actionIndex);
    final float x=MotionEventCompat.getX(ev,actionIndex);
    final float y=MotionEventCompat.getY(ev,actionIndex);
    saveInitialMotion(x,y,pointerId);
    if (mDragState == STATE_IDLE) {
      final View toCapture=findTopChildUnder((int)x,(int)y);
      tryCaptureViewForDrag(toCapture,pointerId);
      final int edgesTouched=mInitialEdgesTouched[pointerId];
      if ((edgesTouched & mTrackingEdges) != 0) {
        mCallback.onEdgeTouched(edgesTouched & mTrackingEdges,pointerId);
      }
    }
 else     if (isCapturedViewUnder((int)x,(int)y)) {
      tryCaptureViewForDrag(mCapturedView,pointerId);
    }
    break;
  }
case MotionEvent.ACTION_MOVE:
{
  if (mDragState == STATE_DRAGGING) {
    final int index=MotionEventCompat.findPointerIndex(ev,mActivePointerId);
    final float x=MotionEventCompat.getX(ev,index);
    final float y=MotionEventCompat.getY(ev,index);
    final int idx=(int)(x - mLastMotionX[mActivePointerId]);
    final int idy=(int)(y - mLastMotionY[mActivePointerId]);
    dragTo(mCapturedView.getLeft() + idx,mCapturedView.getTop() + idy,idx,idy);
    saveLastMotion(ev);
  }
 else {
    final int pointerCount=MotionEventCompat.getPointerCount(ev);
    for (int i=0; i < pointerCount; i++) {
      final int pointerId=MotionEventCompat.getPointerId(ev,i);
      final float x=MotionEventCompat.getX(ev,i);
      final float y=MotionEventCompat.getY(ev,i);
      final float dx=x - mInitialMotionX[pointerId];
      final float dy=y - mInitialMotionY[pointerId];
      reportNewEdgeDrags(dx,dy,pointerId);
      if (mDragState == STATE_DRAGGING) {
        break;
      }
      final View toCapture=findTopChildUnder((int)x,(int)y);
      if (checkTouchSlop(toCapture,dx,dy) && tryCaptureViewForDrag(toCapture,pointerId)) {
        break;
      }
    }
    saveLastMotion(ev);
  }
  break;
}
case MotionEventCompat.ACTION_POINTER_UP:
{
final int pointerId=MotionEventCompat.getPointerId(ev,actionIndex);
if (mDragState == STATE_DRAGGING && pointerId == mActivePointerId) {
  int newActivePointer=INVALID_POINTER;
  final int pointerCount=MotionEventCompat.getPointerCount(ev);
  for (int i=0; i < pointerCount; i++) {
    final int id=MotionEventCompat.getPointerId(ev,i);
    if (id == mActivePointerId) {
      continue;
    }
    final float x=MotionEventCompat.getX(ev,i);
    final float y=MotionEventCompat.getY(ev,i);
    if (findTopChildUnder((int)x,(int)y) == mCapturedView && tryCaptureViewForDrag(mCapturedView,id)) {
      newActivePointer=mActivePointerId;
      break;
    }
  }
  if (newActivePointer == INVALID_POINTER) {
    releaseViewForPointerUp();
  }
}
clearMotionHistory(pointerId);
break;
}
case MotionEvent.ACTION_UP:
{
if (mDragState == STATE_DRAGGING) {
releaseViewForPointerUp();
}
cancel();
break;
}
case MotionEvent.ACTION_CANCEL:
{
if (mDragState == STATE_DRAGGING) {
dispatchViewReleased(0,0);
}
cancel();
break;
}
}
}

Fixed version (ground truth):
/** 
 * Process a touch event received by the parent view. This method will dispatch callback events as needed before returning. The parent view's onTouchEvent implementation should call this.
 * @param ev The touch event received by the parent view
 */
public void processTouchEvent(MotionEvent ev){
  final int action=MotionEventCompat.getActionMasked(ev);
  final int actionIndex=MotionEventCompat.getActionIndex(ev);
  if (action == MotionEvent.ACTION_DOWN) {
    cancel();
  }
  if (mVelocityTracker == null) {
    mVelocityTracker=VelocityTracker.obtain();
  }
  mVelocityTracker.addMovement(ev);
switch (action) {
case MotionEvent.ACTION_DOWN:
{
      final float x=ev.getX();
      final float y=ev.getY();
      final int pointerId=MotionEventCompat.getPointerId(ev,0);
      final View toCapture=findTopChildUnder((int)x,(int)y);
      saveInitialMotion(x,y,pointerId);
      tryCaptureViewForDrag(toCapture,pointerId);
      final int edgesTouched=mInitialEdgesTouched[pointerId];
      if ((edgesTouched & mTrackingEdges) != 0) {
        mCallback.onEdgeTouched(edgesTouched & mTrackingEdges,pointerId);
      }
      break;
    }
case MotionEventCompat.ACTION_POINTER_DOWN:
{
    final int pointerId=MotionEventCompat.getPointerId(ev,actionIndex);
    final float x=MotionEventCompat.getX(ev,actionIndex);
    final float y=MotionEventCompat.getY(ev,actionIndex);
    saveInitialMotion(x,y,pointerId);
    if (mDragState == STATE_IDLE) {
      final View toCapture=findTopChildUnder((int)x,(int)y);
      tryCaptureViewForDrag(toCapture,pointerId);
      final int edgesTouched=mInitialEdgesTouched[pointerId];
      if ((edgesTouched & mTrackingEdges) != 0) {
        mCallback.onEdgeTouched(edgesTouched & mTrackingEdges,pointerId);
      }
    }
 else     if (isCapturedViewUnder((int)x,(int)y)) {
      tryCaptureViewForDrag(mCapturedView,pointerId);
    }
    break;
  }
case MotionEvent.ACTION_MOVE:
{
  if (mDragState == STATE_DRAGGING) {
    final int index=MotionEventCompat.findPointerIndex(ev,mActivePointerId);
    final float x=MotionEventCompat.getX(ev,index);
    final float y=MotionEventCompat.getY(ev,index);
    final int idx=(int)(x - mLastMotionX[mActivePointerId]);
    final int idy=(int)(y - mLastMotionY[mActivePointerId]);
    dragTo(mCapturedView.getLeft() + idx,mCapturedView.getTop() + idy,idx,idy);
    saveLastMotion(ev);
  }
 else {
    final int pointerCount=MotionEventCompat.getPointerCount(ev);
    for (int i=0; i < pointerCount; i++) {
      final int pointerId=MotionEventCompat.getPointerId(ev,i);
      final float x=MotionEventCompat.getX(ev,i);
      final float y=MotionEventCompat.getY(ev,i);
      final float dx=x - mInitialMotionX[pointerId];
      final float dy=y - mInitialMotionY[pointerId];
      reportNewEdgeDrags(dx,dy,pointerId);
      if (mDragState == STATE_DRAGGING) {
        break;
      }
      final View toCapture=findTopChildUnder((int)mInitialMotionX[pointerId],(int)mInitialMotionY[pointerId]);
      if (checkTouchSlop(toCapture,dx,dy) && tryCaptureViewForDrag(toCapture,pointerId)) {
        break;
      }
    }
    saveLastMotion(ev);
  }
  break;
}
case MotionEventCompat.ACTION_POINTER_UP:
{
final int pointerId=MotionEventCompat.getPointerId(ev,actionIndex);
if (mDragState == STATE_DRAGGING && pointerId == mActivePointerId) {
  int newActivePointer=INVALID_POINTER;
  final int pointerCount=MotionEventCompat.getPointerCount(ev);
  for (int i=0; i < pointerCount; i++) {
    final int id=MotionEventCompat.getPointerId(ev,i);
    if (id == mActivePointerId) {
      continue;
    }
    final float x=MotionEventCompat.getX(ev,i);
    final float y=MotionEventCompat.getY(ev,i);
    if (findTopChildUnder((int)x,(int)y) == mCapturedView && tryCaptureViewForDrag(mCapturedView,id)) {
      newActivePointer=mActivePointerId;
      break;
    }
  }
  if (newActivePointer == INVALID_POINTER) {
    releaseViewForPointerUp();
  }
}
clearMotionHistory(pointerId);
break;
}
case MotionEvent.ACTION_UP:
{
if (mDragState == STATE_DRAGGING) {
releaseViewForPointerUp();
}
cancel();
break;
}
case MotionEvent.ACTION_CANCEL:
{
if (mDragState == STATE_DRAGGING) {
dispatchViewReleased(0,0);
}
cancel();
break;
}
}
}