Handle consecutive ViewPager.setCurrentItem calls.

Bug: 25113163
Change-Id: Id4711485a28c20868874e223547c220646406a3d
diff --git a/v4/java/android/support/v4/view/ViewPager.java b/v4/java/android/support/v4/view/ViewPager.java
index dc3cee4..454ac62 100644
--- a/v4/java/android/support/v4/view/ViewPager.java
+++ b/v4/java/android/support/v4/view/ViewPager.java
@@ -144,7 +144,10 @@
     private int mRestoredCurItem = -1;
     private Parcelable mRestoredAdapterState = null;
     private ClassLoader mRestoredClassLoader = null;
+
     private Scroller mScroller;
+    private boolean mIsScrollStarted;
+
     private PagerObserver mObserver;
 
     private int mPageMargin;
@@ -388,6 +391,10 @@
     @Override
     protected void onDetachedFromWindow() {
         removeCallbacks(mEndScrollRunnable);
+        // To be on the safe side, abort the scroller
+        if ((mScroller != null) && !mScroller.isFinished()) {
+            mScroller.abortAnimation();
+        }
         super.onDetachedFromWindow();
     }
 
@@ -829,7 +836,21 @@
             setScrollingCacheEnabled(false);
             return;
         }
-        int sx = getScrollX();
+
+        int sx;
+        boolean wasScrolling = (mScroller != null) && !mScroller.isFinished();
+        if (wasScrolling) {
+            // We're in the middle of a previously initiated scrolling. Check to see
+            // whether that scrolling has actually started (if we always call getStartX
+            // we can get a stale value from the scroller if it hadn't yet had its first
+            // computeScrollOffset call) to decide what is the current scrolling position.
+            sx = mIsScrollStarted ? mScroller.getCurrX() : mScroller.getStartX();
+            // And abort the current scrolling.
+            mScroller.abortAnimation();
+            setScrollingCacheEnabled(false);
+        } else {
+            sx = getScrollX();
+        }
         int sy = getScrollY();
         int dx = x - sx;
         int dy = y - sy;
@@ -849,7 +870,7 @@
         final float distance = halfWidth + halfWidth *
                 distanceInfluenceForSnapDuration(distanceRatio);
 
-        int duration = 0;
+        int duration;
         velocity = Math.abs(velocity);
         if (velocity > 0) {
             duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
@@ -860,6 +881,9 @@
         }
         duration = Math.min(duration, MAX_SETTLE_DURATION);
 
+        // Reset the "scroll started" flag. It will be flipped to true in all places
+        // where we call computeScrollOffset().
+        mIsScrollStarted = false;
         mScroller.startScroll(sx, sy, dx, dy, duration);
         ViewCompat.postInvalidateOnAnimation(this);
     }
@@ -1642,6 +1666,7 @@
 
     @Override
     public void computeScroll() {
+        mIsScrollStarted = true;
         if (!mScroller.isFinished() && mScroller.computeScrollOffset()) {
             int oldX = getScrollX();
             int oldY = getScrollY();
@@ -1822,15 +1847,18 @@
         if (needPopulate) {
             // Done with scroll, no longer want to cache view drawing.
             setScrollingCacheEnabled(false);
-            mScroller.abortAnimation();
-            int oldX = getScrollX();
-            int oldY = getScrollY();
-            int x = mScroller.getCurrX();
-            int y = mScroller.getCurrY();
-            if (oldX != x || oldY != y) {
-                scrollTo(x, y);
-                if (x != oldX) {
-                    pageScrolled(x);
+            boolean wasScrolling = !mScroller.isFinished();
+            if (wasScrolling) {
+                mScroller.abortAnimation();
+                int oldX = getScrollX();
+                int oldY = getScrollY();
+                int x = mScroller.getCurrX();
+                int y = mScroller.getCurrY();
+                if (oldX != x || oldY != y) {
+                    scrollTo(x, y);
+                    if (x != oldX) {
+                        pageScrolled(x);
+                    }
                 }
             }
         }
@@ -1964,6 +1992,7 @@
                 mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
                 mIsUnableToDrag = false;
 
+                mIsScrollStarted = true;
                 mScroller.computeScrollOffset();
                 if (mScrollState == SCROLL_STATE_SETTLING &&
                         Math.abs(mScroller.getFinalX() - mScroller.getCurrX()) > mCloseEnough) {