Program: 55683
Project: 55683
Buggy source:
public void onTouchEvent(MotionEvent e){
  boolean isPan=panStarted() || e.getPointerCount() > 1 || (e.getSource() & InputDevice.SOURCE_CLASS_MASK) == InputDevice.SOURCE_CLASS_TRACKBALL;
  if (isPan) {
    if (drawStarted()) {
      abortDraw();
    }
    if (!panStarted()) {
      endedPansX=0;
      endedPansY=0;
      panStart=getStartedPanAverage();
      startPan(panStart);
      zoomStartDistance=getPointerDistance(e);
      lastZoomFactor=1;
    }
    if (e.getAction() == MotionEvent.ACTION_POINTER_DOWN) {
      int index=getPointerIndex(e);
      Integer id=Integer.valueOf(e.getPointerId(index));
      UIPoint point=new UIPoint(e.getX(index),e.getY(index));
      panPointerStarts.put(id,point);
    }
 else     if (e.getAction() == MotionEvent.ACTION_POINTER_UP) {
      int index=getPointerIndex(e);
      Integer id=Integer.valueOf(e.getPointerId(index));
      UIPoint start=panPointerStarts.remove(id);
      if (start != null) {
        endedPansX+=(e.getX(index) - start.getX()) / e.getPointerCount();
        endedPansY-=(e.getY(index) - start.getY()) / e.getPointerCount();
      }
    }
 else {
      float factor=computeZoomFactor(e);
      if (e.getAction() == MotionEvent.ACTION_MOVE) {
        UIPoint point=computePanPoint(e);
        updatePanPosition(point);
        if (e.getPointerCount() > 1 && (factor < 1 / ZOOMSTART || factor > ZOOMSTART) && getPointerDistance(e) > ZOOM_MIN_POINTERDISTANCE) {
          doZoom=true;
          startZoom();
        }
        if (doZoom) {
          updateZoomFactor(factor);
        }
      }
 else       if (e.getAction() == MotionEvent.ACTION_UP) {
        endPan(computePanPoint(e));
        if (doZoom) {
          endZoomEvent(factor);
        }
      }
    }
  }
 else {
    if (e.getAction() == MotionEvent.ACTION_DOWN) {
      startDraw(convertToLocal(e,0));
      panPointerStarts.clear();
      for (int i=0; i < e.getPointerCount(); i++) {
        Integer index=e.getPointerId(i);
        panPointerStarts.put(index,new UIPoint(e.getX(i),e.getY(i)));
      }
    }
 else     if (e.getAction() == MotionEvent.ACTION_MOVE) {
      updateDrawPosition(convertToLocal(e,0));
    }
 else     if (e.getAction() == MotionEvent.ACTION_UP) {
      endDraw(convertToLocal(e,0));
    }
  }
}

Fixed version (ground truth):
public void onTouchEvent(MotionEvent e){
  boolean isPan=panStarted() || e.getPointerCount() > 1 || (e.getSource() & InputDevice.SOURCE_CLASS_MASK) == InputDevice.SOURCE_CLASS_TRACKBALL;
  if (isPan) {
    if (drawStarted()) {
      abortDraw();
    }
    if (!panStarted()) {
      endedPansX=0;
      endedPansY=0;
      panStart=getStartedPanAverage();
      startPan(panStart);
      zoomStartDistance=getPointerDistance(e);
      lastZoomFactor=1;
    }
    if (e.getAction() == MotionEvent.ACTION_POINTER_DOWN) {
      int index=getPointerIndex(e);
      Integer id=Integer.valueOf(e.getPointerId(index));
      UIPoint point=new UIPoint(e.getX(index),e.getY(index));
      panPointerStarts.put(id,point);
    }
 else     if (e.getAction() == MotionEvent.ACTION_POINTER_UP) {
      int index=getPointerIndex(e);
      Integer id=Integer.valueOf(e.getPointerId(index));
      UIPoint start=panPointerStarts.remove(id);
      if (start != null) {
        endedPansX+=(e.getX(index) - start.getX()) / e.getPointerCount();
        endedPansY-=(e.getY(index) - start.getY()) / e.getPointerCount();
      }
    }
 else {
      float factor=computeZoomFactor(e);
      if (e.getAction() == MotionEvent.ACTION_MOVE) {
        UIPoint point=computePanPoint(e);
        updatePanPosition(point);
        if (e.getPointerCount() > 1 && (factor < 1 / ZOOMSTART || factor > ZOOMSTART) && getPointerDistance(e) > ZOOM_MIN_POINTERDISTANCE) {
          doZoom=true;
          startZoom();
        }
        if (doZoom) {
          updateZoomFactor(factor);
        }
      }
 else       if (e.getAction() == MotionEvent.ACTION_UP) {
        endPan(computePanPoint(e));
        if (doZoom) {
          endZoomEvent(factor,null);
        }
      }
    }
  }
 else {
    if (e.getAction() == MotionEvent.ACTION_DOWN) {
      startDraw(convertToLocal(e,0));
      panPointerStarts.clear();
      for (int i=0; i < e.getPointerCount(); i++) {
        Integer index=e.getPointerId(i);
        panPointerStarts.put(index,new UIPoint(e.getX(i),e.getY(i)));
      }
    }
 else     if (e.getAction() == MotionEvent.ACTION_MOVE) {
      updateDrawPosition(convertToLocal(e,0));
    }
 else     if (e.getAction() == MotionEvent.ACTION_UP) {
      endDraw(convertToLocal(e,0));
    }
  }
}