Program: 161793
Project: 161793
Buggy source:
@Override public boolean onTouchEvent(MotionEvent event){
  int touchCount=event.getPointerCount();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_1_DOWN:
case MotionEvent.ACTION_POINTER_2_DOWN:
    if (touchCount >= 2) {
      float distance=distance(event.getX(0),event.getX(1),event.getY(0),event.getY(1));
      mPrevDistance=distance;
      isScaling=true;
    }
 else {
      if (System.currentTimeMillis() <= mLastTime + DOUBLE_TAP_SECOND) {
        if (30 > Math.abs(mPrevMoveX - event.getX()) + Math.abs(mPrevMoveY - event.getY())) {
          isDoubleTap=true;
          mDoubleTapX=(int)event.getX();
          mDoubleTapY=(int)event.getY();
        }
      }
      mLastTime=System.currentTimeMillis();
      mPrevMoveX=(int)event.getX();
      mPrevMoveY=(int)event.getY();
    }
  break;
case MotionEvent.ACTION_MOVE:
if (touchCount >= 2 && isScaling) {
  float dist=distance(event.getX(0),event.getX(1),event.getY(0),event.getY(1));
  float scale=(dist - mPrevDistance) / dispDistance();
  mPrevDistance=dist;
  scale+=1;
  scale=scale * scale;
  zoomTo(scale,getWidth() / 2,getHeight() / 2);
  cutting();
}
 else if (!isScaling) {
  int distanceX=mPrevMoveX - (int)event.getX();
  int distanceY=mPrevMoveY - (int)event.getY();
  mPrevMoveX=(int)event.getX();
  mPrevMoveY=(int)event.getY();
  mMatrix.postTranslate(-distanceX,-distanceY);
  cutting();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_2_UP:
if (event.getPointerCount() <= 1) {
isScaling=false;
if (isDoubleTap) {
if (30 > Math.abs(mDoubleTapX - event.getX()) + Math.abs(mDoubleTapY - event.getY())) {
  maxZoomTo(mDoubleTapX,mDoubleTapY);
  cutting();
}
}
}
isDoubleTap=false;
break;
}
return true;
}

Fixed version (ground truth):
@Override public boolean onTouchEvent(MotionEvent event){
  int touchCount=event.getPointerCount();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_1_DOWN:
case MotionEvent.ACTION_POINTER_2_DOWN:
    if (touchCount >= 2) {
      float distance=distance(event.getX(0),event.getX(1),event.getY(0),event.getY(1));
      mPrevDistance=distance;
      isScaling=true;
    }
 else {
      if (System.currentTimeMillis() <= mLastTime + DOUBLE_TAP_SECOND) {
        if (30 > Math.abs(mPrevMoveX - event.getX()) + Math.abs(mPrevMoveY - event.getY())) {
          isDoubleTap=true;
          mDoubleTapX=(int)event.getX();
          mDoubleTapY=(int)event.getY();
        }
      }
      mLastTime=System.currentTimeMillis();
      mPrevMoveX=(int)event.getX();
      mPrevMoveY=(int)event.getY();
    }
  break;
case MotionEvent.ACTION_MOVE:
if (touchCount >= 2 && isScaling) {
  float dist=distance(event.getX(0),event.getX(1),event.getY(0),event.getY(1));
  float scale=(dist - mPrevDistance) / dispDistance();
  mPrevDistance=dist;
  scale+=1;
  scale=scale * scale;
  zoomTo(scale,mWidth / 2,mHeight / 2);
  cutting();
}
 else if (!isScaling) {
  int distanceX=mPrevMoveX - (int)event.getX();
  int distanceY=mPrevMoveY - (int)event.getY();
  mPrevMoveX=(int)event.getX();
  mPrevMoveY=(int)event.getY();
  mMatrix.postTranslate(-distanceX,-distanceY);
  cutting();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_2_UP:
if (event.getPointerCount() <= 1) {
isScaling=false;
if (isDoubleTap) {
if (30 > Math.abs(mDoubleTapX - event.getX()) + Math.abs(mDoubleTapY - event.getY())) {
  maxZoomTo(mDoubleTapX,mDoubleTapY);
  cutting();
}
}
}
isDoubleTap=false;
break;
}
return true;
}