Program: 194363
Project: 194363
Buggy source:
@Override public void updatePosition(float x,float y){
  final Layout layout=mTextView.getLayout();
  if (layout == null) {
    positionAtCursorOffset(mTextView.getOffsetForPosition(x,y),false);
    return;
  }
  boolean positionCursor=false;
  final int selectionStart=mTextView.getSelectionStart();
  int currLine=getCurrentLineAdjustedForSlop(layout,mPrevLine,y);
  int initialOffset=mTextView.getOffsetAtCoordinate(currLine,x);
  if (initialOffset <= selectionStart) {
    currLine=layout.getLineForOffset(selectionStart);
    initialOffset=mTextView.getOffsetAtCoordinate(currLine,x);
  }
  int offset=initialOffset;
  int end=getWordEnd(offset);
  int start=getWordStart(offset);
  if (mPrevX == UNSET_X_VALUE) {
    mPrevX=x;
  }
  final int selectionEnd=mTextView.getSelectionEnd();
  final boolean selectionEndRtl=layout.isRtlCharAt(selectionEnd);
  final boolean atRtl=layout.isRtlCharAt(offset);
  final boolean isLvlBoundary=layout.isLevelBoundary(offset);
  boolean isExpanding;
  if (isLvlBoundary || (selectionEndRtl && !atRtl) || (!selectionEndRtl && atRtl)) {
    mLanguageDirectionChanged=true;
    mTouchWordDelta=0.0f;
    positionAtCursorOffset(offset,false);
    return;
  }
 else   if (mLanguageDirectionChanged && !isLvlBoundary) {
    positionAtCursorOffset(offset,false);
    mTouchWordDelta=0.0f;
    mLanguageDirectionChanged=false;
    return;
  }
 else {
    final float xDiff=x - mPrevX;
    if (atRtl) {
      isExpanding=xDiff < 0 || currLine < mPrevLine;
    }
 else {
      isExpanding=xDiff > 0 || currLine > mPrevLine;
    }
  }
  if (isExpanding) {
    if (!mInWord || currLine > mPrevLine) {
      int wordEndOnCurrLine=end;
      if (layout != null && layout.getLineForOffset(end) != currLine) {
        wordEndOnCurrLine=layout.getLineEnd(currLine);
      }
      final int offsetThresholdToSnap=start + ((wordEndOnCurrLine - start) / 2);
      if (offset >= offsetThresholdToSnap || currLine > mPrevLine) {
        offset=end;
      }
 else {
        offset=mPreviousOffset;
      }
    }
    if (offset > initialOffset) {
      final float adjustedX=layout.getPrimaryHorizontal(offset);
      mTouchWordDelta=adjustedX - mTextView.convertToLocalHorizontalCoordinate(x);
    }
 else {
      mTouchWordDelta=0.0f;
    }
    positionCursor=true;
  }
 else {
    final int adjustedOffset=mTextView.getOffsetAtCoordinate(currLine,x + mTouchWordDelta);
    if (adjustedOffset < mPreviousOffset || currLine < mPrevLine) {
      if (currLine < mPrevLine) {
        offset=end;
        if (offset > initialOffset) {
          final float adjustedX=layout.getPrimaryHorizontal(offset);
          mTouchWordDelta=adjustedX - mTextView.convertToLocalHorizontalCoordinate(x);
        }
 else {
          mTouchWordDelta=0.0f;
        }
      }
 else {
        offset=adjustedOffset;
      }
      positionCursor=true;
    }
 else     if (adjustedOffset > mPreviousOffset) {
      mTouchWordDelta=layout.getPrimaryHorizontal(mPreviousOffset) - mTextView.convertToLocalHorizontalCoordinate(x);
    }
  }
  if (positionCursor) {
    if (offset <= selectionStart) {
      offset=getNextCursorOffset(selectionStart,true);
      mTouchWordDelta=0.0f;
    }
    positionAtCursorOffset(offset,false);
  }
  mPrevX=x;
}

Fixed version (ground truth):
@Override public void updatePosition(float x,float y){
  final Layout layout=mTextView.getLayout();
  if (layout == null) {
    positionAtCursorOffset(mTextView.getOffsetForPosition(x,y),false);
    return;
  }
  if (mPreviousLineTouched == UNSET_LINE) {
    mPreviousLineTouched=mTextView.getLineAtCoordinate(y);
  }
  boolean positionCursor=false;
  final int selectionStart=mTextView.getSelectionStart();
  int currLine=getCurrentLineAdjustedForSlop(layout,mPreviousLineTouched,y);
  int initialOffset=mTextView.getOffsetAtCoordinate(currLine,x);
  if (initialOffset <= selectionStart) {
    currLine=layout.getLineForOffset(selectionStart);
    initialOffset=mTextView.getOffsetAtCoordinate(currLine,x);
  }
  int offset=initialOffset;
  int end=getWordEnd(offset);
  int start=getWordStart(offset);
  if (mPrevX == UNSET_X_VALUE) {
    mPrevX=x;
  }
  final int selectionEnd=mTextView.getSelectionEnd();
  final boolean selectionEndRtl=layout.isRtlCharAt(selectionEnd);
  final boolean atRtl=layout.isRtlCharAt(offset);
  final boolean isLvlBoundary=layout.isLevelBoundary(offset);
  boolean isExpanding;
  if (isLvlBoundary || (selectionEndRtl && !atRtl) || (!selectionEndRtl && atRtl)) {
    mLanguageDirectionChanged=true;
    mTouchWordDelta=0.0f;
    positionAtCursorOffset(offset,false);
    return;
  }
 else   if (mLanguageDirectionChanged && !isLvlBoundary) {
    positionAtCursorOffset(offset,false);
    mTouchWordDelta=0.0f;
    mLanguageDirectionChanged=false;
    return;
  }
 else {
    final float xDiff=x - mPrevX;
    if (atRtl) {
      isExpanding=xDiff < 0 || currLine < mPreviousLineTouched;
    }
 else {
      isExpanding=xDiff > 0 || currLine > mPreviousLineTouched;
    }
  }
  if (isExpanding) {
    if (!mInWord || currLine > mPrevLine) {
      int wordEndOnCurrLine=end;
      if (layout != null && layout.getLineForOffset(end) != currLine) {
        wordEndOnCurrLine=layout.getLineEnd(currLine);
      }
      final int offsetThresholdToSnap=start + ((wordEndOnCurrLine - start) / 2);
      if (offset >= offsetThresholdToSnap || currLine > mPrevLine) {
        offset=end;
      }
 else {
        offset=mPreviousOffset;
      }
    }
    if (offset > initialOffset) {
      final float adjustedX=layout.getPrimaryHorizontal(offset);
      mTouchWordDelta=adjustedX - mTextView.convertToLocalHorizontalCoordinate(x);
    }
 else {
      mTouchWordDelta=0.0f;
    }
    positionCursor=true;
  }
 else {
    final int adjustedOffset=mTextView.getOffsetAtCoordinate(currLine,x + mTouchWordDelta);
    if (adjustedOffset < mPreviousOffset || currLine < mPrevLine) {
      if (currLine < mPrevLine) {
        offset=end;
        if (offset > initialOffset) {
          final float adjustedX=layout.getPrimaryHorizontal(offset);
          mTouchWordDelta=adjustedX - mTextView.convertToLocalHorizontalCoordinate(x);
        }
 else {
          mTouchWordDelta=0.0f;
        }
      }
 else {
        offset=adjustedOffset;
      }
      positionCursor=true;
    }
 else     if (adjustedOffset > mPreviousOffset) {
      mTouchWordDelta=layout.getPrimaryHorizontal(mPreviousOffset) - mTextView.convertToLocalHorizontalCoordinate(x);
    }
  }
  if (positionCursor) {
    if (offset <= selectionStart) {
      offset=getNextCursorOffset(selectionStart,true);
      mTouchWordDelta=0.0f;
    }
    mPreviousLineTouched=currLine;
    positionAtCursorOffset(offset,false);
  }
  mPrevX=x;
}