Program: 194962
Project: 194962
Buggy source:
public void onTouchEvent(MotionEvent event){
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
    final float x=event.getX();
  final float y=event.getY();
mMinTouchOffset=mMaxTouchOffset=mTextView.getOffsetForPosition(x,y);
if (mGestureStayedInTapRegion) {
if (mDoubleTap) {
  final float deltaX=x - mDownPositionX;
  final float deltaY=y - mDownPositionY;
  final float distanceSquared=deltaX * deltaX + deltaY * deltaY;
  ViewConfiguration viewConfiguration=ViewConfiguration.get(mTextView.getContext());
  int doubleTapSlop=viewConfiguration.getScaledDoubleTapSlop();
  boolean stayedInArea=distanceSquared < doubleTapSlop * doubleTapSlop;
  if (stayedInArea && isPositionOnText(x,y)) {
    startSelectionActionModeWithSelectionAndStartDrag();
    mDiscardNextActionUp=true;
  }
}
}
mDownPositionX=x;
mDownPositionY=y;
mGestureStayedInTapRegion=true;
break;
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP:
if (mTextView.getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) {
updateMinAndMaxOffsets(event);
}
break;
case MotionEvent.ACTION_MOVE:
final ViewConfiguration viewConfiguration=ViewConfiguration.get(mTextView.getContext());
if (mGestureStayedInTapRegion) {
final float deltaX=event.getX() - mDownPositionX;
final float deltaY=event.getY() - mDownPositionY;
final float distanceSquared=deltaX * deltaX + deltaY * deltaY;
int doubleTapTouchSlop=viewConfiguration.getScaledDoubleTapTouchSlop();
if (distanceSquared > doubleTapTouchSlop * doubleTapTouchSlop) {
mGestureStayedInTapRegion=false;
}
}
if (mStartHandle != null && mStartHandle.isShowing()) {
break;
}
if (mStartOffset != -1) {
final int rawOffset=mTextView.getOffsetForPosition(event.getX(),event.getY());
int offset=rawOffset;
int firstWordStart=getWordStart(mStartOffset);
int firstWordEnd=getWordEnd(mStartOffset);
if (offset > firstWordEnd || offset < firstWordStart) {
int fingerOffset=viewConfiguration.getScaledTouchSlop();
float mx=event.getX();
float my=event.getY();
if (mx > fingerOffset) mx-=fingerOffset;
if (my > fingerOffset) my-=fingerOffset;
offset=mTextView.getOffsetForPosition(mx,my);
if (mTextView.getWidth() - fingerOffset > mx) {
final WordIterator wordIterator=getWordIteratorWithText();
final int precedingOffset=wordIterator.preceding(offset);
if (mStartOffset < offset) {
offset=Math.max(precedingOffset - 1,0);
}
 else {
if (precedingOffset == WordIterator.DONE) {
offset=0;
}
 else {
offset=wordIterator.preceding(precedingOffset);
}
}
}
if (offset == WordIterator.DONE) offset=rawOffset;
int newStart=mStartOffset < offset ? getWordStart(mStartOffset) : getWordEnd(mStartOffset);
Selection.setSelection((Spannable)mTextView.getText(),newStart,offset);
}
}
break;
case MotionEvent.ACTION_UP:
if (mDragAcceleratorActive) {
mTextView.getParent().requestDisallowInterceptTouchEvent(false);
show();
int startOffset=mTextView.getSelectionStart();
int endOffset=mTextView.getSelectionEnd();
if (endOffset < startOffset) {
int tmp=endOffset;
endOffset=startOffset;
startOffset=tmp;
Selection.setSelection((Spannable)mTextView.getText(),startOffset,endOffset);
}
mStartHandle.showAtLocation(startOffset);
mEndHandle.showAtLocation(endOffset);
mDragAcceleratorActive=false;
mStartOffset=-1;
}
break;
}
}

Fixed version (ground truth):
public void onTouchEvent(MotionEvent event){
  final float eventX=event.getX();
  final float eventY=event.getY();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
    mMinTouchOffset=mMaxTouchOffset=mTextView.getOffsetForPosition(eventX,eventY);
  if (mGestureStayedInTapRegion) {
    if (mDoubleTap) {
      final float deltaX=eventX - mDownPositionX;
      final float deltaY=eventY - mDownPositionY;
      final float distanceSquared=deltaX * deltaX + deltaY * deltaY;
      ViewConfiguration viewConfiguration=ViewConfiguration.get(mTextView.getContext());
      int doubleTapSlop=viewConfiguration.getScaledDoubleTapSlop();
      boolean stayedInArea=distanceSquared < doubleTapSlop * doubleTapSlop;
      if (stayedInArea && isPositionOnText(eventX,eventY)) {
        startSelectionActionModeWithSelectionAndStartDrag();
        mDiscardNextActionUp=true;
      }
    }
  }
mDownPositionX=eventX;
mDownPositionY=eventY;
mGestureStayedInTapRegion=true;
mHaventMovedEnoughToStartDrag=true;
break;
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP:
if (mTextView.getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) {
updateMinAndMaxOffsets(event);
}
break;
case MotionEvent.ACTION_MOVE:
final ViewConfiguration viewConfig=ViewConfiguration.get(mTextView.getContext());
final int touchSlop=viewConfig.getScaledTouchSlop();
if (mGestureStayedInTapRegion || mHaventMovedEnoughToStartDrag) {
final float deltaX=eventX - mDownPositionX;
final float deltaY=eventY - mDownPositionY;
final float distanceSquared=deltaX * deltaX + deltaY * deltaY;
if (mGestureStayedInTapRegion) {
int doubleTapTouchSlop=viewConfig.getScaledDoubleTapTouchSlop();
mGestureStayedInTapRegion=distanceSquared <= doubleTapTouchSlop * doubleTapTouchSlop;
}
if (mHaventMovedEnoughToStartDrag) {
mHaventMovedEnoughToStartDrag=distanceSquared <= touchSlop * touchSlop;
}
}
if (mStartHandle != null && mStartHandle.isShowing()) {
break;
}
if (mStartOffset != -1) {
if (!mHaventMovedEnoughToStartDrag) {
final float fingerOffset=(mStartHandle != null) ? mStartHandle.getIdealVerticalOffset() : touchSlop;
int offset=mTextView.getOffsetForPosition(eventX,eventY - fingerOffset);
int startOffset;
if (mStartOffset < offset) {
offset=getWordEnd(offset);
startOffset=getWordStart(mStartOffset);
}
 else {
offset=getWordStart(offset);
startOffset=getWordEnd(mStartOffset);
}
Selection.setSelection((Spannable)mTextView.getText(),startOffset,offset);
}
}
break;
case MotionEvent.ACTION_UP:
if (mDragAcceleratorActive) {
mTextView.getParent().requestDisallowInterceptTouchEvent(false);
show();
int startOffset=mTextView.getSelectionStart();
int endOffset=mTextView.getSelectionEnd();
if (endOffset < startOffset) {
int tmp=endOffset;
endOffset=startOffset;
startOffset=tmp;
Selection.setSelection((Spannable)mTextView.getText(),startOffset,endOffset);
}
mStartHandle.showAtLocation(startOffset);
mEndHandle.showAtLocation(endOffset);
mDragAcceleratorActive=false;
mStartOffset=-1;
}
break;
}
}