resolved conflicts for merge of c0728cc0 to gingerbread-plus-aosp

Change-Id: I1b941e0610e498365d441c7bd23af276d1b5f986
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a5e144a..70dc8cb 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -91,6 +91,7 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
@@ -6841,16 +6842,17 @@
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         final int action = event.getActionMasked();
-        if (action == MotionEvent.ACTION_DOWN) {
-            if (hasInsertionController()) {
-                getInsertionController().onTouchEvent(event);
-            }
-            if (hasSelectionController()) {
-                getSelectionController().onTouchEvent(event);
-            }
 
-            // Reset this state; it will be re-set if super.onTouchEvent
-            // causes focus to move to the view.
+        if (mInsertionPointCursorController != null) {
+            mInsertionPointCursorController.onTouchEvent(event);
+        }
+        if (mSelectionModifierCursorController != null) {
+            mSelectionModifierCursorController.onTouchEvent(event);
+        }
+
+        if (action == MotionEvent.ACTION_DOWN) {
+        // Reset this state; it will be re-set if super.onTouchEvent
+        // causes focus to move to the view.
             mTouchFocusSelected = false;
             mScrolled = false;
         }
@@ -6869,13 +6871,6 @@
 
         if ((mMovement != null || onCheckIsTextEditor()) && isEnabled() &&
                 mText instanceof Spannable && mLayout != null) {
-            if (hasInsertionController()) {
-                getInsertionController().onTouchEvent(event);
-            }
-            if (hasSelectionController()) {
-                getSelectionController().onTouchEvent(event);
-            }
-
             boolean handled = false;
 
             // Save previous selection, in case this event is used to show the IME.
@@ -7804,7 +7799,7 @@
                 }
                 mDrawable = mSelectHandleLeft;
                 handleWidth = mDrawable.getIntrinsicWidth();
-                mHotspotX = handleWidth / 4 * 3;
+                mHotspotX = (handleWidth * 3) / 4;
                 break;
             }
 
@@ -7971,6 +7966,7 @@
                 mIsDragging = true;
                 break;
             }
+
             case MotionEvent.ACTION_MOVE: {
                 final float rawX = ev.getRawX();
                 final float rawY = ev.getRawY();
@@ -7981,6 +7977,7 @@
 
                 break;
             }
+
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
                 mIsDragging = false;
@@ -8095,6 +8092,10 @@
         private int mMinTouchOffset, mMaxTouchOffset;
         // Whether selection anchors are active
         private boolean mIsShowing;
+        // Double tap detection
+        private long mPreviousTapUpTime = 0;
+        private int mPreviousTapPositionX;
+        private int mPreviousTapPositionY;
 
         SelectionModifierCursorController() {
             mStartHandle = new HandleView(this, HandleView.LEFT);
@@ -8189,6 +8190,24 @@
                         // Remember finger down position, to be able to start selection from there
                         mMinTouchOffset = mMaxTouchOffset = getOffset(x, y);
 
+                        // Double tap detection
+                        long duration = SystemClock.uptimeMillis() - mPreviousTapUpTime;
+                        if (duration <= ViewConfiguration.getDoubleTapTimeout()) {
+                            final int deltaX = x - mPreviousTapPositionX;
+                            final int deltaY = y - mPreviousTapPositionY;
+                            final int distanceSquared = deltaX * deltaX + deltaY * deltaY;
+                            final int doubleTapSlop = ViewConfiguration.get(getContext()).getScaledDoubleTapSlop();
+                            final int slopSquared = doubleTapSlop * doubleTapSlop;
+                            if (distanceSquared < slopSquared) {
+                                startTextSelectionMode();
+                                // Hacky: onTapUpEvent will open a context menu with cut/copy
+                                // Prevent this by hiding handles which will be revived instead.
+                                hide();
+                            }
+                        }
+                        mPreviousTapPositionX = x;
+                        mPreviousTapPositionY = y;
+
                         break;
 
                     case MotionEvent.ACTION_POINTER_DOWN:
@@ -8200,6 +8219,10 @@
                             updateMinAndMaxOffsets(event);
                         }
                         break;
+
+                    case MotionEvent.ACTION_UP:
+                        mPreviousTapUpTime = SystemClock.uptimeMillis();
+                        break;
                 }
             }
             return false;