Program: 2693
Project: 2693
Buggy source:
private void handleActionMove(MotionEvent event){
  final int historySize=event.getHistorySize();
  for (int i=0; i < historySize + 1; i++) {
    final float x=i < historySize ? event.getHistoricalX(i) : event.getX();
    final float y=i < historySize ? event.getHistoricalY(i) : event.getY();
    final int patternSizePreHitDetect=mPattern.size();
    Cell hitCell=detectAndAddHit(x,y);
    final int patternSize=mPattern.size();
    if (hitCell != null && patternSize == 1) {
      mPatternInProgress=true;
      notifyPatternStarted();
    }
    final float dx=Math.abs(x - mInProgressX);
    final float dy=Math.abs(y - mInProgressY);
    if (dx + dy > mSquareWidth * 0.01f) {
      float oldX=mInProgressX;
      float oldY=mInProgressY;
      mInProgressX=x;
      mInProgressY=y;
      if (mPatternInProgress && patternSize > 0) {
        final ArrayList<Cell> pattern=mPattern;
        final float radius=mSquareWidth * mDiameterFactor * 0.5f;
        final Cell lastCell=pattern.get(patternSize - 1);
        float startX=getCenterXForColumn(lastCell.column);
        float startY=getCenterYForRow(lastCell.row);
        float left;
        float top;
        float right;
        float bottom;
        final Rect invalidateRect=mInvalidate;
        if (startX < x) {
          left=startX;
          right=x;
        }
 else {
          left=x;
          right=startX;
        }
        if (startY < y) {
          top=startY;
          bottom=y;
        }
 else {
          top=y;
          bottom=startY;
        }
        invalidateRect.set((int)(left - radius),(int)(top - radius),(int)(right + radius),(int)(bottom + radius));
        if (startX < oldX) {
          left=startX;
          right=oldX;
        }
 else {
          left=oldX;
          right=startX;
        }
        if (startY < oldY) {
          top=startY;
          bottom=oldY;
        }
 else {
          top=oldY;
          bottom=startY;
        }
        invalidateRect.union((int)(left - radius),(int)(top - radius),(int)(right + radius),(int)(bottom + radius));
        if (hitCell != null) {
          startX=getCenterXForColumn(hitCell.column);
          startY=getCenterYForRow(hitCell.row);
          if (patternSize >= 2) {
            hitCell=pattern.get(patternSize - 1 - (patternSize - patternSizePreHitDetect));
            oldX=getCenterXForColumn(hitCell.column);
            oldY=getCenterYForRow(hitCell.row);
            if (startX < oldX) {
              left=startX;
              right=oldX;
            }
 else {
              left=oldX;
              right=startX;
            }
            if (startY < oldY) {
              top=startY;
              bottom=oldY;
            }
 else {
              top=oldY;
              bottom=startY;
            }
          }
 else {
            left=right=startX;
            top=bottom=startY;
          }
          final float widthOffset=mSquareWidth / 2f;
          final float heightOffset=mSquareHeight / 2f;
          invalidateRect.set((int)(left - widthOffset),(int)(top - heightOffset),(int)(right + widthOffset),(int)(bottom + heightOffset));
        }
        invalidate(invalidateRect);
      }
 else {
        invalidate();
      }
    }
  }
}

Fixed version (ground truth):
private void handleActionMove(MotionEvent event){
  final int historySize=event.getHistorySize();
  Rect invalidateRect=mInvalidate;
  boolean invalidateNow=false;
  for (int i=0; i < historySize + 1; i++) {
    final float x=i < historySize ? event.getHistoricalX(i) : event.getX();
    final float y=i < historySize ? event.getHistoricalY(i) : event.getY();
    Cell hitCell=detectAndAddHit(x,y);
    final int patternSize=mPattern.size();
    if (hitCell != null && patternSize == 1) {
      mPatternInProgress=true;
      notifyPatternStarted();
    }
    final float dx=Math.abs(x - mInProgressX);
    final float dy=Math.abs(y - mInProgressY);
    if (dx > DRAG_THRESHHOLD || dy > DRAG_THRESHHOLD) {
      invalidateNow=true;
    }
    if (mPatternInProgress && patternSize > 0) {
      final ArrayList<Cell> pattern=mPattern;
      final Cell lastCell=pattern.get(patternSize - 1);
      float startX=getCenterXForColumn(lastCell.column);
      float startY=getCenterYForRow(lastCell.row);
      final float radius=(mSquareWidth * mDiameterFactor * 0.5f);
      float left=Math.min(startX,x) - radius;
      float right=Math.max(startX,x) + radius;
      float top=Math.min(startY,y) - radius;
      float bottom=Math.max(startY,y) + radius;
      if (hitCell != null && patternSize >= 2) {
        final float width=mSquareWidth * 0.5f;
        final float height=mSquareHeight * 0.5f;
        final float x2=getCenterXForColumn(hitCell.column);
        final float y2=getCenterYForRow(hitCell.row);
        left=Math.min(x2,left - width);
        right=Math.max(x2,right + width);
        top=Math.min(y2,top - height);
        bottom=Math.max(y2,bottom + height);
      }
      invalidateRect.union(Math.round(left),Math.round(top),Math.round(right),Math.round(bottom));
    }
  }
  mInProgressX=event.getX();
  mInProgressY=event.getY();
  if (invalidateNow) {
    invalidate(invalidateRect);
    invalidateRect.setEmpty();
  }
}