Remove overscrolling

Change-Id: I7e9db8d8a9b8ef67f0c0c82bf57c9155b7ebabea
diff --git a/api/current.xml b/api/current.xml
index da47553..276fd32 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -5960,39 +5960,6 @@
  visibility="public"
 >
 </field>
-<field name="overscrollFooter"
- type="int"
- transient="false"
- volatile="false"
- value="16843456"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="overscrollHeader"
- type="int"
- transient="false"
- volatile="false"
- value="16843455"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="overscrollMode"
- type="int"
- transient="false"
- volatile="false"
- value="16843450"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="padding"
  type="int"
  transient="false"
@@ -6800,7 +6767,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843451"
+ value="16843450"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7911,7 +7878,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843454"
+ value="16843453"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7922,7 +7889,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843452"
+ value="16843451"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7933,7 +7900,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843453"
+ value="16843452"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -175488,17 +175455,6 @@
  visibility="public"
 >
 </method>
-<method name="getOverscrollMode"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getPaddingBottom"
  return="int"
  abstract="false"
@@ -176639,25 +176595,6 @@
 <parameter name="heightMeasureSpec" type="int">
 </parameter>
 </method>
-<method name="onOverscrolled"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="scrollX" type="int">
-</parameter>
-<parameter name="scrollY" type="int">
-</parameter>
-<parameter name="clampedX" type="boolean">
-</parameter>
-<parameter name="clampedY" type="boolean">
-</parameter>
-</method>
 <method name="onRestoreInstanceState"
  return="void"
  abstract="false"
@@ -176811,35 +176748,6 @@
 <parameter name="visibility" type="int">
 </parameter>
 </method>
-<method name="overscrollBy"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="deltaX" type="int">
-</parameter>
-<parameter name="deltaY" type="int">
-</parameter>
-<parameter name="scrollX" type="int">
-</parameter>
-<parameter name="scrollY" type="int">
-</parameter>
-<parameter name="scrollRangeX" type="int">
-</parameter>
-<parameter name="scrollRangeY" type="int">
-</parameter>
-<parameter name="maxOverscrollX" type="int">
-</parameter>
-<parameter name="maxOverscrollY" type="int">
-</parameter>
-<parameter name="isTouchEvent" type="boolean">
-</parameter>
-</method>
 <method name="performClick"
  return="boolean"
  abstract="false"
@@ -177666,19 +177574,6 @@
 <parameter name="l" type="android.view.View.OnTouchListener">
 </parameter>
 </method>
-<method name="setOverscrollMode"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="overscrollMode" type="int">
-</parameter>
-</method>
 <method name="setPadding"
  return="void"
  abstract="false"
@@ -178301,39 +178196,6 @@
  visibility="public"
 >
 </field>
-<field name="OVERSCROLL_ALWAYS"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="OVERSCROLL_IF_CONTENT_SCROLLS"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="OVERSCROLL_NEVER"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET"
  type="int[]"
  transient="false"
@@ -193178,17 +193040,6 @@
  visibility="public"
 >
 </method>
-<method name="getUseWebViewBackgroundForOverscrollBackground"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getUseWideViewPort"
  return="boolean"
  abstract="false"
@@ -193781,19 +193632,6 @@
 <parameter name="use" type="boolean">
 </parameter>
 </method>
-<method name="setUseWebViewBackgroundForOverscrollBackground"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="view" type="boolean">
-</parameter>
-</method>
 <method name="setUseWideViewPort"
  return="void"
  abstract="false"
@@ -204404,28 +204242,6 @@
  visibility="public"
 >
 </method>
-<method name="getOverscrollFooter"
- return="android.graphics.drawable.Drawable"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getOverscrollHeader"
- return="android.graphics.drawable.Drawable"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="isItemChecked"
  return="boolean"
  abstract="false"
@@ -204571,32 +204387,6 @@
 <parameter name="itemsCanFocus" type="boolean">
 </parameter>
 </method>
-<method name="setOverscrollFooter"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="footer" type="android.graphics.drawable.Drawable">
-</parameter>
-</method>
-<method name="setOverscrollHeader"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="header" type="android.graphics.drawable.Drawable">
-</parameter>
-</method>
 <method name="setSelection"
  return="void"
  abstract="false"
@@ -205168,331 +204958,6 @@
 </parameter>
 </method>
 </interface>
-<class name="OverScroller"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="OverScroller"
- type="android.widget.OverScroller"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-</constructor>
-<constructor name="OverScroller"
- type="android.widget.OverScroller"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="interpolator" type="android.view.animation.Interpolator">
-</parameter>
-</constructor>
-<constructor name="OverScroller"
- type="android.widget.OverScroller"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="interpolator" type="android.view.animation.Interpolator">
-</parameter>
-<parameter name="bounceCoefficientX" type="float">
-</parameter>
-<parameter name="bounceCoefficientY" type="float">
-</parameter>
-</constructor>
-<method name="abortAnimation"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="computeScrollOffset"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="fling"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="startX" type="int">
-</parameter>
-<parameter name="startY" type="int">
-</parameter>
-<parameter name="velocityX" type="int">
-</parameter>
-<parameter name="velocityY" type="int">
-</parameter>
-<parameter name="minX" type="int">
-</parameter>
-<parameter name="maxX" type="int">
-</parameter>
-<parameter name="minY" type="int">
-</parameter>
-<parameter name="maxY" type="int">
-</parameter>
-</method>
-<method name="fling"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="startX" type="int">
-</parameter>
-<parameter name="startY" type="int">
-</parameter>
-<parameter name="velocityX" type="int">
-</parameter>
-<parameter name="velocityY" type="int">
-</parameter>
-<parameter name="minX" type="int">
-</parameter>
-<parameter name="maxX" type="int">
-</parameter>
-<parameter name="minY" type="int">
-</parameter>
-<parameter name="maxY" type="int">
-</parameter>
-<parameter name="overX" type="int">
-</parameter>
-<parameter name="overY" type="int">
-</parameter>
-</method>
-<method name="forceFinished"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="finished" type="boolean">
-</parameter>
-</method>
-<method name="getCurrX"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getCurrY"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getFinalX"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getFinalY"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getStartX"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getStartY"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="isFinished"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="isOverscrolled"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="notifyHorizontalEdgeReached"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="startX" type="int">
-</parameter>
-<parameter name="finalX" type="int">
-</parameter>
-<parameter name="overX" type="int">
-</parameter>
-</method>
-<method name="notifyVerticalEdgeReached"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="startY" type="int">
-</parameter>
-<parameter name="finalY" type="int">
-</parameter>
-<parameter name="overY" type="int">
-</parameter>
-</method>
-<method name="springback"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="startX" type="int">
-</parameter>
-<parameter name="startY" type="int">
-</parameter>
-<parameter name="minX" type="int">
-</parameter>
-<parameter name="maxX" type="int">
-</parameter>
-<parameter name="minY" type="int">
-</parameter>
-<parameter name="maxY" type="int">
-</parameter>
-</method>
-<method name="startScroll"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="startX" type="int">
-</parameter>
-<parameter name="startY" type="int">
-</parameter>
-<parameter name="dx" type="int">
-</parameter>
-<parameter name="dy" type="int">
-</parameter>
-</method>
-<method name="startScroll"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="startX" type="int">
-</parameter>
-<parameter name="startY" type="int">
-</parameter>
-<parameter name="dx" type="int">
-</parameter>
-<parameter name="dy" type="int">
-</parameter>
-<parameter name="duration" type="int">
-</parameter>
-</method>
-</class>
 <class name="PopupWindow"
  extends="java.lang.Object"
  abstract="false"
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4744c64..d99ebc9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1512,40 +1512,6 @@
      * @hide
      */
     static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
-    
-    /**
-     * Always allow a user to overscroll this view, provided it is a
-     * view that can scroll.
-     * 
-     * @see #getOverscrollMode()
-     * @see #setOverscrollMode(int)
-     */
-    public static final int OVERSCROLL_ALWAYS = 0;
-    
-    /**
-     * Allow a user to overscroll this view only if the content is large
-     * enough to meaningfully scroll, provided it is a view that can scroll.
-     * 
-     * @see #getOverscrollMode()
-     * @see #setOverscrollMode(int)
-     */
-    public static final int OVERSCROLL_IF_CONTENT_SCROLLS = 1;
-    
-    /**
-     * Never allow a user to overscroll this view.
-     * 
-     * @see #getOverscrollMode()
-     * @see #setOverscrollMode(int)
-     */
-    public static final int OVERSCROLL_NEVER = 2;
-    
-    /**
-     * Controls the overscroll mode for this view.
-     * See {@link #overscrollBy(int, int, int, int, int, int, int, int, boolean)},
-     * {@link #OVERSCROLL_ALWAYS}, {@link #OVERSCROLL_IF_CONTENT_SCROLLS},
-     * and {@link #OVERSCROLL_NEVER}.
-     */
-    private int mOverscrollMode = OVERSCROLL_ALWAYS;
 
     /**
      * The parent this view is attached to.
@@ -2103,9 +2069,6 @@
                         });
                     }
                     break;
-                case R.styleable.View_overscrollMode:
-                    mOverscrollMode = a.getInt(attr, OVERSCROLL_ALWAYS);
-                    break;
             }
         }
 
@@ -8667,161 +8630,6 @@
         LayoutInflater factory = LayoutInflater.from(context);
         return factory.inflate(resource, root);
     }
-    
-    /**
-     * Scroll the view with standard behavior for scrolling beyond the normal
-     * content boundaries. Views that call this method should override
-     * {@link #onOverscrolled(int, int, boolean, boolean)} to respond to the
-     * results of an overscroll operation.
-     * 
-     * Views can use this method to handle any touch or fling-based scrolling.
-     * 
-     * @param deltaX Change in X in pixels 
-     * @param deltaY Change in Y in pixels
-     * @param scrollX Current X scroll value in pixels before applying deltaX
-     * @param scrollY Current Y scroll value in pixels before applying deltaY
-     * @param scrollRangeX Maximum content scroll range along the X axis
-     * @param scrollRangeY Maximum content scroll range along the Y axis
-     * @param maxOverscrollX Number of pixels to overscroll by in either direction
-     *          along the X axis.
-     * @param maxOverscrollY Number of pixels to overscroll by in either direction
-     *          along the Y axis.
-     * @param isTouchEvent true if this scroll operation is the result of a touch event.
-     * @return true if scrolling was clamped to an overscroll boundary along either
-     *          axis, false otherwise.
-     */
-    protected boolean overscrollBy(int deltaX, int deltaY,
-            int scrollX, int scrollY,
-            int scrollRangeX, int scrollRangeY,
-            int maxOverscrollX, int maxOverscrollY,
-            boolean isTouchEvent) {
-        final int overscrollMode = mOverscrollMode;
-        final boolean canScrollHorizontal = 
-                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
-        final boolean canScrollVertical = 
-                computeVerticalScrollRange() > computeVerticalScrollExtent();
-        final boolean overscrollHorizontal = overscrollMode == OVERSCROLL_ALWAYS ||
-                (overscrollMode == OVERSCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
-        final boolean overscrollVertical = overscrollMode == OVERSCROLL_ALWAYS ||
-                (overscrollMode == OVERSCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
-        
-        int newScrollX = scrollX + deltaX;
-        if (overscrollHorizontal) {
-            // Scale the scroll amount if we're in the dropoff zone
-            final int dropoffX = maxOverscrollX / 2;
-            final int dropoffLeft = -dropoffX;
-            final int dropoffRight = dropoffX + scrollRangeX;
-            if ((scrollX < dropoffLeft && deltaX < 0) ||
-                    (scrollX > dropoffRight && deltaX > 0)) {
-                newScrollX = scrollX + deltaX / 2;
-            } else {
-                if (newScrollX > dropoffRight && deltaX > 0) {
-                    int extra = newScrollX - dropoffRight;
-                    newScrollX = dropoffRight + extra / 2;
-                } else if (newScrollX < dropoffLeft && deltaX < 0) {
-                    int extra = newScrollX - dropoffLeft;
-                    newScrollX = dropoffLeft + extra / 2;
-                }
-            }
-        } else {
-            maxOverscrollX = 0;
-        }
-
-        int newScrollY = scrollY + deltaY;
-        if (overscrollVertical) {
-            final int dropoffY = maxOverscrollY / 2;
-            final int dropoffTop = -dropoffY;
-            final int dropoffBottom = dropoffY + scrollRangeY;
-            if ((scrollY < dropoffTop && deltaY < 0) ||
-                    (scrollY > dropoffBottom && deltaY > 0)) {
-                newScrollY = scrollY + deltaY / 2;
-            } else {
-                if (newScrollY > dropoffBottom && deltaY > 0) {
-                    int extra = newScrollY - dropoffBottom;
-                    newScrollY = dropoffBottom + extra / 2;
-                } else if (newScrollY < dropoffTop && deltaY < 0) {
-                    int extra = newScrollY - dropoffTop;
-                    newScrollY = dropoffTop + extra / 2;
-                }
-            }
-        } else {
-            maxOverscrollY = 0;
-        }
-        
-        // Clamp values if at the limits and record
-        final int left = -maxOverscrollX;
-        final int right = maxOverscrollX + scrollRangeX;
-        final int top = -maxOverscrollY;
-        final int bottom = maxOverscrollY + scrollRangeY;
-
-        boolean clampedX = false;
-        if (newScrollX > right) {
-            newScrollX = right;
-            clampedX = true;
-        } else if (newScrollX < left) {
-            newScrollX = left;
-            clampedX = true;
-        }
-        
-        boolean clampedY = false;
-        if (newScrollY > bottom) {
-            newScrollY = bottom;
-            clampedY = true;
-        } else if (newScrollY < top) {
-            newScrollY = top;
-            clampedY = true;
-        }
-
-        onOverscrolled(newScrollX, newScrollY, clampedX, clampedY);
-        
-        return clampedX || clampedY;
-    }
-    
-    /**
-     * Called by {@link #overscrollBy(int, int, int, int, int, int, int, int, boolean)} to
-     * respond to the results of an overscroll operation.
-     * 
-     * @param scrollX New X scroll value in pixels
-     * @param scrollY New Y scroll value in pixels
-     * @param clampedX True if scrollX was clamped to an overscroll boundary
-     * @param clampedY True if scrollY was clamped to an overscroll boundary
-     */
-    protected void onOverscrolled(int scrollX, int scrollY,
-            boolean clampedX, boolean clampedY) {
-        // Intentionally empty.
-    }
-    
-    /**
-     * Returns the overscroll mode for this view. The result will be
-     * one of {@link #OVERSCROLL_ALWAYS} (default), {@link #OVERSCROLL_IF_CONTENT_SCROLLS}
-     * (allow overscrolling only if the view content is larger than the container),
-     * or {@link #OVERSCROLL_NEVER}.
-     * 
-     * @return This view's overscroll mode.
-     */
-    public int getOverscrollMode() {
-        return mOverscrollMode;
-    }
-    
-    /**
-     * Set the overscroll mode for this view. Valid overscroll modes are
-     * {@link #OVERSCROLL_ALWAYS} (default), {@link #OVERSCROLL_IF_CONTENT_SCROLLS}
-     * (allow overscrolling only if the view content is larger than the container),
-     * or {@link #OVERSCROLL_NEVER}.
-     * 
-     * Setting the overscroll mode of a view will have an effect only if the
-     * view is capable of scrolling.
-     * 
-     * @param overscrollMode The new overscroll mode for this view.
-     */
-    public void setOverscrollMode(int overscrollMode) {
-        if (overscrollMode != OVERSCROLL_ALWAYS &&
-                overscrollMode != OVERSCROLL_IF_CONTENT_SCROLLS &&
-                overscrollMode != OVERSCROLL_NEVER) {
-            throw new IllegalArgumentException("Invalid overscroll mode " + overscrollMode);
-        }
-        mOverscrollMode = overscrollMode;
-    }
 
     /**
      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 1b801d4..b767f11 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -207,7 +207,6 @@
     private boolean         mBuiltInZoomControls = false;
     private boolean         mAllowFileAccess = true;
     private boolean         mLoadWithOverviewMode = false;
-    private boolean         mUseWebViewBackgroundOverscrollBackground = true;
 
     // private WebSettings, not accessible by the host activity
     static private int      mDoubleTapToastCount = 3;
@@ -486,23 +485,6 @@
     }
 
     /**
-     * Set whether the WebView uses its background for over scroll background.
-     * If true, it will use the WebView's background. If false, it will use an
-     * internal pattern. Default is true.
-     */
-    public void setUseWebViewBackgroundForOverscrollBackground(boolean view) {
-        mUseWebViewBackgroundOverscrollBackground = view;
-    }
-
-    /**
-     * Returns true if this WebView uses WebView's background instead of
-     * internal pattern for over scroll background.
-     */
-    public boolean getUseWebViewBackgroundForOverscrollBackground() {
-        return mUseWebViewBackgroundOverscrollBackground;
-    }
-
-    /**
      * Store whether the WebView is saving form data.
      */
     public void setSaveFormData(boolean save) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 030290f..7388295 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -37,8 +37,8 @@
 import android.graphics.Region;
 import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
-import android.net.http.SslCertificate;
 import android.net.Uri;
+import android.net.http.SslCertificate;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -77,7 +77,7 @@
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.ListView;
-import android.widget.OverScroller;
+import android.widget.Scroller;
 import android.widget.Toast;
 import android.widget.ZoomButtonsController;
 import android.widget.ZoomControls;
@@ -90,8 +90,8 @@
 import java.io.IOException;
 import java.net.URLDecoder;
 import java.util.ArrayList;
-import java.util.List;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -469,10 +469,7 @@
     // time for the longest scroll animation
     private static final int MAX_DURATION = 750;   // milliseconds
     private static final int SLIDE_TITLE_DURATION = 500;   // milliseconds
-    private OverScroller mScroller;
-    private boolean mInOverScrollMode = false;
-    private static Paint mOverScrollBackground;
-    private static Paint mOverScrollBorder;
+    private Scroller mScroller;
 
     private boolean mWrapContent;
     private static final int MOTIONLESS_FALSE           = 0;
@@ -848,7 +845,7 @@
         mViewManager = new ViewManager(this);
         mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javascriptInterfaces);
         mDatabase = WebViewDatabase.getInstance(context);
-        mScroller = new OverScroller(context);
+        mScroller = new Scroller(context);
 
         updateMultiTouchSupport(context);
     }
@@ -1051,8 +1048,7 @@
      * Return the amount of the titlebarview (if any) that is visible
      */
     private int getVisibleTitleHeight() {
-        // need to restrict mScrollY due to over scroll
-        return Math.max(getTitleHeight() - Math.max(0, mScrollY), 0);
+        return Math.max(getTitleHeight() - mScrollY, 0);
     }
 
     /*
@@ -1662,7 +1658,7 @@
         }
         nativeClearCursor(); // start next trackball movement from page edge
         if (bottom) {
-            return pinScrollTo(mScrollX, computeRealVerticalScrollRange(), true, 0);
+            return pinScrollTo(mScrollX, computeVerticalScrollRange(), true, 0);
         }
         // Page down.
         int h = getHeight();
@@ -1893,15 +1889,13 @@
 
     // Expects x in view coordinates
     private int pinLocX(int x) {
-        if (mInOverScrollMode) return x;
-        return pinLoc(x, getViewWidth(), computeRealHorizontalScrollRange());
+        return pinLoc(x, getViewWidth(), computeHorizontalScrollRange());
     }
 
     // Expects y in view coordinates
     private int pinLocY(int y) {
-        if (mInOverScrollMode) return y;
         return pinLoc(y, getViewHeightWithTitle(),
-                      computeRealVerticalScrollRange() + getTitleHeight());
+                      computeVerticalScrollRange() + getTitleHeight());
     }
 
     /**
@@ -2189,7 +2183,7 @@
     // Sets r to be our visible rectangle in content coordinates
     private void calcOurContentVisibleRect(Rect r) {
         calcOurVisibleRect(r);
-        // since we might overscroll, pin the rect to the bounds of the content
+        // pin the rect to the bounds of the content
         r.left = Math.max(viewToContentX(r.left), 0);
         // viewToContentY will remove the total height of the title bar.  Add
         // the visible height back in to account for the fact that if the title
@@ -2252,7 +2246,8 @@
         return false;
     }
 
-    private int computeRealHorizontalScrollRange() {
+    @Override
+    protected int computeHorizontalScrollRange() {
         if (mDrawHistory) {
             return mHistoryWidth;
         } else {
@@ -2262,27 +2257,7 @@
     }
 
     @Override
-    protected int computeHorizontalScrollRange() {
-        int range = computeRealHorizontalScrollRange();
-
-        // Adjust reported range if overscrolled to compress the scroll bars
-        final int scrollX = mScrollX;
-        final int overscrollRight = computeMaxScrollX();
-        if (scrollX < 0) {
-            range -= scrollX;
-        } else if (scrollX > overscrollRight) {
-            range += scrollX - overscrollRight;
-        }
-
-        return range;
-    }
-
-    @Override
-    protected int computeHorizontalScrollOffset() {
-        return Math.max(mScrollX, 0);
-    }
-
-    private int computeRealVerticalScrollRange() {
+    protected int computeVerticalScrollRange() {
         if (mDrawHistory) {
             return mHistoryHeight;
         } else {
@@ -2292,22 +2267,6 @@
     }
 
     @Override
-    protected int computeVerticalScrollRange() {
-        int range = computeRealVerticalScrollRange();
-
-        // Adjust reported range if overscrolled to compress the scroll bars
-        final int scrollY = mScrollY;
-        final int overscrollBottom = computeMaxScrollY();
-        if (scrollY < 0) {
-            range -= scrollY;
-        } else if (scrollY > overscrollBottom) {
-            range += scrollY - overscrollBottom;
-        }
-
-        return range;
-    }
-
-    @Override
     protected int computeVerticalScrollOffset() {
         return Math.max(mScrollY - getTitleHeight(), 0);
     }
@@ -2326,23 +2285,6 @@
         scrollBar.draw(canvas);
     }
 
-    @Override
-    protected void onOverscrolled(int scrollX, int scrollY, boolean clampedX,
-            boolean clampedY) {
-        mInOverScrollMode = false;
-        int maxX = computeMaxScrollX();
-        if (maxX == 0) {
-            // do not over scroll x if the page just fits the screen
-            scrollX = pinLocX(scrollX);
-        } else if (scrollX < 0 || scrollX > maxX) {
-            mInOverScrollMode = true;
-        }
-        if (scrollY < 0 || scrollY > computeMaxScrollY()) {
-            mInOverScrollMode = true;
-        }
-        super.scrollTo(scrollX, scrollY);
-    }
-
     /**
      * Get the url for the current page. This is not always the same as the url
      * passed to WebViewClient.onPageStarted because although the load for
@@ -2688,14 +2630,13 @@
         if (mScroller.computeScrollOffset()) {
             int oldX = mScrollX;
             int oldY = mScrollY;
-            int x = mScroller.getCurrX();
-            int y = mScroller.getCurrY();
+            mScrollX = mScroller.getCurrX();
+            mScrollY = mScroller.getCurrY();
             postInvalidate();  // So we draw again
-            if (oldX != x || oldY != y) {
-                overscrollBy(x - oldX, y - oldY, oldX, oldY,
-                        computeMaxScrollX(), computeMaxScrollY(),
-                        getViewWidth() / 3, getViewHeight() / 3, false);
-                onScrollChanged(mScrollX, mScrollY, oldX, oldY);
+            if (oldX != mScrollX || oldY != mScrollY) {
+                // As onScrollChanged() is not called, sendOurVisibleRect()
+                // needs to be called explicitly.
+                sendOurVisibleRect();
             }
         } else {
             super.computeScroll();
@@ -3106,13 +3047,8 @@
     protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
         if (child == mTitleBar) {
             // When drawing the title bar, move it horizontally to always show
-            // at the top of the WebView. While overscroll, stick the title bar
-            // on the top otherwise we may have two during loading, one is drawn
-            // here, another is drawn by the Browser.
+            // at the top of the WebView.
             mTitleBar.offsetLeftAndRight(mScrollX - mTitleBar.getLeft());
-            if (mScrollY <= 0) {
-                mTitleBar.offsetTopAndBottom(mScrollY - mTitleBar.getTop());
-            }
         }
         return super.drawChild(canvas, child, drawingTime);
     }
@@ -3148,36 +3084,6 @@
         }
 
         int saveCount = canvas.save();
-        if (mInOverScrollMode && !getSettings()
-                .getUseWebViewBackgroundForOverscrollBackground()) {
-            if (mOverScrollBackground == null) {
-                mOverScrollBackground = new Paint();
-                Bitmap bm = BitmapFactory.decodeResource(
-                        mContext.getResources(),
-                        com.android.internal.R.drawable.status_bar_background);
-                mOverScrollBackground.setShader(new BitmapShader(bm,
-                        Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
-                mOverScrollBorder = new Paint();
-                mOverScrollBorder.setStyle(Paint.Style.STROKE);
-                mOverScrollBorder.setStrokeWidth(0);
-                mOverScrollBorder.setColor(0xffbbbbbb);
-            }
-
-            int top = getTitleHeight();
-            int right = computeRealHorizontalScrollRange();
-            int bottom = top + computeRealVerticalScrollRange();
-            // first draw the background and anchor to the top of the view
-            canvas.save();
-            canvas.translate(mScrollX, mScrollY);
-            canvas.clipRect(-mScrollX, top - mScrollY, right - mScrollX, bottom
-                    - mScrollY, Region.Op.DIFFERENCE);
-            canvas.drawPaint(mOverScrollBackground);
-            canvas.restore();
-            // then draw the border
-            canvas.drawRect(-1, top - 1, right, bottom, mOverScrollBorder);
-            // next clip the region for the content
-            canvas.clipRect(0, top, right, bottom);
-        }
         if (mTitleBar != null) {
             canvas.translate(0, (int) mTitleBar.getHeight());
         }
@@ -3195,12 +3101,12 @@
         canvas.restoreToCount(saveCount);
 
         // Now draw the shadow.
-        int titleH = getVisibleTitleHeight();
-        if (mTitleBar != null && titleH == 0) {
+        if (mTitleBar != null) {
+            int y = mScrollY + getVisibleTitleHeight();
             int height = (int) (5f * getContext().getResources()
                     .getDisplayMetrics().density);
-            mTitleShadow.setBounds(mScrollX, mScrollY, mScrollX + getWidth(),
-                    mScrollY + height);
+            mTitleShadow.setBounds(mScrollX, y, mScrollX + getWidth(),
+                    y + height);
             mTitleShadow.draw(canvas);
         }
         if (AUTO_REDRAW_HACK && mAutoRedraw) {
@@ -4232,14 +4138,12 @@
     @Override
     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
         super.onScrollChanged(l, t, oldl, oldt);
-        if (!mInOverScrollMode) {
-            sendOurVisibleRect();
-            // update WebKit if visible title bar height changed. The logic is same
-            // as getVisibleTitleHeight.
-            int titleHeight = getTitleHeight();
-            if (Math.max(titleHeight - t, 0) != Math.max(titleHeight - oldt, 0)) {
-                sendViewSizeZoom();
-            }
+        sendOurVisibleRect();
+        // update WebKit if visible title bar height changed. The logic is same
+        // as getVisibleTitleHeight.
+        int titleHeight = getTitleHeight();
+        if (Math.max(titleHeight - t, 0) != Math.max(titleHeight - oldt, 0)) {
+            sendViewSizeZoom();
         }
     }
 
@@ -4309,7 +4213,7 @@
         public DragTrackerHandler(float x, float y, DragTracker proxy) {
             mProxy = proxy;
 
-            int docBottom = computeRealVerticalScrollRange() + getTitleHeight();
+            int docBottom = computeVerticalScrollRange() + getTitleHeight();
             int viewTop = getScrollY();
             int viewBottom = viewTop + getHeight();
 
@@ -4322,7 +4226,7 @@
                       " up/down= " + mMinDY + " " + mMaxDY);
             }
 
-            int docRight = computeRealHorizontalScrollRange();
+            int docRight = computeHorizontalScrollRange();
             int viewLeft = getScrollX();
             int viewRight = viewLeft + getWidth();
             mStartX = x;
@@ -4826,6 +4730,18 @@
                 }
 
                 // do pan
+                int newScrollX = pinLocX(mScrollX + deltaX);
+                int newDeltaX = newScrollX - mScrollX;
+                if (deltaX != newDeltaX) {
+                    deltaX = newDeltaX;
+                    fDeltaX = (float) newDeltaX;
+                }
+                int newScrollY = pinLocY(mScrollY + deltaY);
+                int newDeltaY = newScrollY - mScrollY;
+                if (deltaY != newDeltaY) {
+                    deltaY = newDeltaY;
+                    fDeltaY = (float) newDeltaY;
+                }
                 boolean done = false;
                 boolean keepScrollBarsVisible = false;
                 if (Math.abs(fDeltaX) < 1.0f && Math.abs(fDeltaY) < 1.0f) {
@@ -4985,12 +4901,6 @@
                             mVelocityTracker.addMovement(ev);
                             doFling();
                             break;
-                        } else {
-                            if (mScroller.springback(mScrollX, mScrollY, 0,
-                                    computeMaxScrollX(), 0,
-                                    computeMaxScrollY())) {
-                                invalidate();
-                            }
                         }
                         mLastVelocity = 0;
                         WebViewCore.resumePriority();
@@ -5001,8 +4911,6 @@
             }
             case MotionEvent.ACTION_CANCEL: {
                 if (mTouchMode == TOUCH_DRAG_MODE) {
-                    mScroller.springback(mScrollX, mScrollY, 0,
-                            computeMaxScrollX(), 0, computeMaxScrollY());
                     invalidate();
                 }
                 cancelWebCoreTouchEvent(contentX, contentY, false);
@@ -5062,9 +4970,7 @@
 
     private void doDrag(int deltaX, int deltaY) {
         if ((deltaX | deltaY) != 0) {
-            overscrollBy(deltaX, deltaY, mScrollX, mScrollY,
-                    computeMaxScrollX(), computeMaxScrollY(),
-                    getViewWidth() / 3, getViewHeight() / 3, true);
+            scrollBy(deltaX, deltaY);
         }
         if (!getSettings().getBuiltInZoomControls()) {
             boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
@@ -5401,17 +5307,17 @@
     }
 
     private int computeMaxScrollX() {
-        return Math.max(computeRealHorizontalScrollRange() - getViewWidth(), 0);
+        return Math.max(computeHorizontalScrollRange() - getViewWidth(), 0);
     }
 
     private int computeMaxScrollY() {
-        return Math.max(computeRealVerticalScrollRange() + getTitleHeight()
+        return Math.max(computeVerticalScrollRange() + getTitleHeight()
                 - getViewHeightWithTitle(), 0);
     }
 
     public void flingScroll(int vx, int vy) {
         mScroller.fling(mScrollX, mScrollY, vx, vy, 0, computeMaxScrollX(), 0,
-                computeMaxScrollY(), getViewWidth() / 3, getViewHeight() / 3);
+                computeMaxScrollY());
         invalidate();
     }
 
@@ -5440,10 +5346,6 @@
         }
         if ((maxX == 0 && vy == 0) || (maxY == 0 && vx == 0)) {
             WebViewCore.resumePriority();
-            if (mScroller.springback(mScrollX, mScrollY, 0, computeMaxScrollX(),
-                    0, computeMaxScrollY())) {
-                invalidate();
-            }
             return;
         }
         float currentVelocity = mScroller.getCurrVelocity();
@@ -5471,9 +5373,7 @@
         mLastVelY = vy;
         mLastVelocity = (float) Math.hypot(vx, vy);
 
-        // no horizontal overscroll if the content just fits
-        mScroller.fling(mScrollX, mScrollY, -vx, -vy, 0, maxX, 0, maxY,
-                maxX == 0 ? 0 : getViewWidth() / 3, getViewHeight() / 3);
+        mScroller.fling(mScrollX, mScrollY, -vx, -vy, 0, maxX, 0, maxY);
         // TODO: duration is calculated based on velocity, if the range is
         // small, the animation will stop before duration is up. We may
         // want to calculate how long the animation is going to run to precisely
@@ -6523,10 +6423,6 @@
                             case MotionEvent.ACTION_CANCEL:
                                 if (mDeferTouchMode == TOUCH_DRAG_MODE) {
                                     // no fling in defer process
-                                    mScroller.springback(mScrollX, mScrollY, 0,
-                                            computeMaxScrollX(), 0,
-                                            computeMaxScrollY());
-                                    invalidate();
                                     WebViewCore.resumePriority();
                                 }
                                 mDeferTouchMode = TOUCH_DONE_MODE;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index bd6105f..d615fd0 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -128,17 +128,6 @@
     static final int TOUCH_MODE_FLING = 4;
 
     /**
-     * Indicates the touch gesture is an overscroll - a scroll beyond the beginning or end.
-     */
-    static final int TOUCH_MODE_OVERSCROLL = 5;
-    
-    /**
-     * Indicates the view is being flung outside of normal content bounds
-     * and will spring back.
-     */
-    static final int TOUCH_MODE_OVERFLING = 6;
-
-    /**
      * Regular layout - usually an unsolicited layout from the view system
      */
     static final int LAYOUT_NORMAL = 0;
@@ -380,16 +369,6 @@
     private ContextMenuInfo mContextMenuInfo = null;
     
     /**
-     * Maximum distance to overscroll by
-     */
-    int mOverscrollMax;
-    
-    /**
-     * Content height divided by this is the overscroll limit.
-     */
-    static final int OVERSCROLL_LIMIT_DIVISOR = 3;
-
-    /**
      * Used to request a layout when we changed touch mode
      */
     private static final int TOUCH_MODE_UNKNOWN = -1;
@@ -1095,10 +1074,6 @@
         int result;
         if (mSmoothScrollbarEnabled) {
             result = Math.max(mItemCount * 100, 0);
-            if (mScrollY != 0) {
-                // Compensate for overscroll
-                result += Math.abs((int) ((float) mScrollY / getHeight() * mItemCount * 100));
-            }
         } else {
             result = mItemCount;
         }
@@ -1171,8 +1146,6 @@
 
         layoutChildren();
         mInLayout = false;
-        
-        mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
     }
 
     /**
@@ -1947,10 +1920,9 @@
         // Check if we have moved far enough that it looks more like a
         // scroll than a tap
         final int distance = Math.abs(deltaY);
-        final boolean overscroll = mScrollY != 0;
-        if (overscroll || distance > mTouchSlop) {
+        if (distance > mTouchSlop) {
             createScrollingCache();
-            mTouchMode = overscroll ? TOUCH_MODE_OVERSCROLL : TOUCH_MODE_SCROLL;
+            mTouchMode = TOUCH_MODE_SCROLL;
             mMotionCorrection = deltaY;
             final Handler handler = getHandler();
             // Handler should not be null unless the AbsListView is not attached to a
@@ -1986,18 +1958,6 @@
                 // touch mode). Force an initial layout to get rid of the selection.
                 layoutChildren();
             }
-        } else {
-            int touchMode = mTouchMode;
-            if (touchMode == TOUCH_MODE_OVERSCROLL || touchMode == TOUCH_MODE_OVERFLING) {
-                if (mFlingRunnable != null) {
-                    mFlingRunnable.endFling();
-                }
-
-                if (mScrollY != 0) {
-                    mScrollY = 0;
-                    invalidate();
-                }
-            }
         }
     }
 
@@ -2028,63 +1988,49 @@
 
         switch (action & MotionEvent.ACTION_MASK) {
         case MotionEvent.ACTION_DOWN: {
-            switch (mTouchMode) {
-            case TOUCH_MODE_OVERFLING: {
-                mFlingRunnable.endFling();
-                mTouchMode = TOUCH_MODE_OVERSCROLL;
-                mLastY = (int) ev.getY();
-                mMotionCorrection = 0;
-                mActivePointerId = ev.getPointerId(0);
-                break;
-            }
-            
-            default: {
-                mActivePointerId = ev.getPointerId(0);
-                final int x = (int) ev.getX();
-                final int y = (int) ev.getY();
-                int motionPosition = pointToPosition(x, y);
-                if (!mDataChanged) {
-                    if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
-                            && (getAdapter().isEnabled(motionPosition))) {
-                        // User clicked on an actual view (and was not stopping a fling). It might be a
-                        // click or a scroll. Assume it is a click until proven otherwise
-                        mTouchMode = TOUCH_MODE_DOWN;
-                        // FIXME Debounce
-                        if (mPendingCheckForTap == null) {
-                            mPendingCheckForTap = new CheckForTap();
-                        }
-                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
-                    } else {
-                        if (ev.getEdgeFlags() != 0 && motionPosition < 0) {
-                            // If we couldn't find a view to click on, but the down event was touching
-                            // the edge, we will bail out and try again. This allows the edge correcting
-                            // code in ViewRoot to try to find a nearby view to select
-                            return false;
-                        }
-                        
-                        if (mTouchMode == TOUCH_MODE_FLING) {
-                            // Stopped a fling. It is a scroll.
-                            createScrollingCache();
-                            mTouchMode = TOUCH_MODE_SCROLL;
-                            mMotionCorrection = 0;
-                            motionPosition = findMotionRow(y);
-                            reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
-                        }
+            mActivePointerId = ev.getPointerId(0);
+            final int x = (int) ev.getX();
+            final int y = (int) ev.getY();
+            int motionPosition = pointToPosition(x, y);
+            if (!mDataChanged) {
+                if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
+                        && (getAdapter().isEnabled(motionPosition))) {
+                    // User clicked on an actual view (and was not stopping a fling). It might be a
+                    // click or a scroll. Assume it is a click until proven otherwise
+                    mTouchMode = TOUCH_MODE_DOWN;
+                    // FIXME Debounce
+                    if (mPendingCheckForTap == null) {
+                        mPendingCheckForTap = new CheckForTap();
+                    }
+                    postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
+                } else {
+                    if (ev.getEdgeFlags() != 0 && motionPosition < 0) {
+                        // If we couldn't find a view to click on, but the down event was touching
+                        // the edge, we will bail out and try again. This allows the edge correcting
+                        // code in ViewRoot to try to find a nearby view to select
+                        return false;
+                    }
+
+                    if (mTouchMode == TOUCH_MODE_FLING) {
+                        // Stopped a fling. It is a scroll.
+                        createScrollingCache();
+                        mTouchMode = TOUCH_MODE_SCROLL;
+                        mMotionCorrection = 0;
+                        motionPosition = findMotionRow(y);
+                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
                     }
                 }
+            }
 
-                if (motionPosition >= 0) {
-                    // Remember where the motion event started
-                    v = getChildAt(motionPosition - mFirstPosition);
-                    mMotionViewOriginalTop = v.getTop();
-                }
-                mMotionX = x;
-                mMotionY = y;
-                mMotionPosition = motionPosition;
-                mLastY = Integer.MIN_VALUE;
-                break;
+            if (motionPosition >= 0) {
+                // Remember where the motion event started
+                v = getChildAt(motionPosition - mFirstPosition);
+                mMotionViewOriginalTop = v.getTop();
             }
-            }
+            mMotionX = x;
+            mMotionY = y;
+            mMotionPosition = motionPosition;
+            mLastY = Integer.MIN_VALUE;
             break;
         }
 
@@ -2131,62 +2077,12 @@
                         // supposed to be
                         final int motionViewRealTop = motionView.getTop();
                         if (atEdge) {
-                            // Apply overscroll
-                            
-                            int overscroll = -incrementalDeltaY - 
-                                    (motionViewRealTop - motionViewPrevTop);
-                            overscrollBy(0, overscroll, 0, mScrollY, 0, 0,
-                                    0, getOverscrollMax(), true);
-                            mTouchMode = TOUCH_MODE_OVERSCROLL;
                             invalidate();
                         }
                     }
                     mLastY = y;
                 }
                 break;
-                
-            case TOUCH_MODE_OVERSCROLL:
-                if (y != mLastY) {
-                    deltaY -= mMotionCorrection;
-                    int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY;
-                    
-                    final int oldScroll = mScrollY;
-                    final int newScroll = oldScroll - incrementalDeltaY; 
-                    
-                    if ((oldScroll >= 0 && newScroll <= 0) ||
-                            (oldScroll <= 0 && newScroll >= 0)) {
-                        // Coming back to 'real' list scrolling
-                        incrementalDeltaY = -newScroll;
-                        mScrollY = 0;
-                        
-                        // No need to do all this work if we're not going to move anyway
-                        if (incrementalDeltaY != 0) {
-                            trackMotionScroll(incrementalDeltaY, incrementalDeltaY);
-                        }
-
-                        // Check to see if we are back in 
-                        View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
-                        if (motionView != null) {
-                            mTouchMode = TOUCH_MODE_SCROLL;
-
-                            // We did not scroll the full amount. Treat this essentially like the
-                            // start of a new touch scroll
-                            final int motionPosition = findClosestMotionRow(y);
-
-                            mMotionCorrection = 0;
-                            motionView = getChildAt(motionPosition - mFirstPosition);
-                            mMotionViewOriginalTop = motionView.getTop();
-                            mMotionY = y;
-                            mMotionPosition = motionPosition;
-                        }
-                    } else {
-                        overscrollBy(0, -incrementalDeltaY, 0, mScrollY, 0, 0,
-                                0, getOverscrollMax(), true);
-                        invalidate();
-                    }
-                    mLastY = y;
-                }
-                break;
             }
 
             break;
@@ -2286,23 +2182,6 @@
                     reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
                 }
                 break;
-                
-            case TOUCH_MODE_OVERSCROLL:
-                if (mFlingRunnable == null) {
-                    mFlingRunnable = new FlingRunnable();
-                }
-                final VelocityTracker velocityTracker = mVelocityTracker;
-                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
-                final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
-
-                reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
-                if (Math.abs(initialVelocity) > mMinimumVelocity) {
-                    mFlingRunnable.startOverfling(-initialVelocity);
-                } else {
-                    mFlingRunnable.startSpringback();
-                }
-
-                break;
             }
 
             setPressed(false);
@@ -2332,36 +2211,22 @@
         }
 
         case MotionEvent.ACTION_CANCEL: {
-            switch (mTouchMode) {
-            case TOUCH_MODE_OVERSCROLL:
-                if (mFlingRunnable == null) {
-                    mFlingRunnable = new FlingRunnable();
-                }
-                mFlingRunnable.startSpringback();
-                break;
-                
-            case TOUCH_MODE_OVERFLING:
-                // Do nothing - let it play out.
-                break;
-                
-            default:
-                mTouchMode = TOUCH_MODE_REST;
-                setPressed(false);
-                View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
-                if (motionView != null) {
-                    motionView.setPressed(false);
-                }
-                clearScrollingCache();
+            mTouchMode = TOUCH_MODE_REST;
+            setPressed(false);
+            View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
+            if (motionView != null) {
+                motionView.setPressed(false);
+            }
+            clearScrollingCache();
 
-                final Handler handler = getHandler();
-                if (handler != null) {
-                    handler.removeCallbacks(mPendingCheckForLongPress);
-                }
+            final Handler handler = getHandler();
+            if (handler != null) {
+                handler.removeCallbacks(mPendingCheckForLongPress);
+            }
 
-                if (mVelocityTracker != null) {
-                    mVelocityTracker.recycle();
-                    mVelocityTracker = null;
-                }
+            if (mVelocityTracker != null) {
+                mVelocityTracker.recycle();
+                mVelocityTracker = null;
             }
             
             mActivePointerId = INVALID_POINTER;
@@ -2386,45 +2251,12 @@
 
         return true;
     }
-    
-    @Override
-    protected void onOverscrolled(int scrollX, int scrollY,
-            boolean clampedX, boolean clampedY) {
-        mScrollY = scrollY;
-
-        if (clampedY) {
-            // Velocity is broken by hitting the limit; don't start a fling off of this.
-            if (mVelocityTracker != null) {
-                mVelocityTracker.clear();
-            }
-        }
-        awakenScrollBars();
-    }
-    
-    int getOverscrollMax() {
-        final int childCount = getChildCount();
-        if (childCount > 0) {
-            return Math.min(mOverscrollMax,
-                    getChildAt(childCount - 1).getBottom() / OVERSCROLL_LIMIT_DIVISOR);
-        } else {
-            return mOverscrollMax;
-        }
-    }
 
     @Override
     public void draw(Canvas canvas) {
         super.draw(canvas);
         if (mFastScroller != null) {
-            final int scrollY = mScrollY;
-            if (scrollY != 0) {
-                // Pin the fast scroll thumb to the top/bottom during overscroll.
-                int restoreCount = canvas.save();
-                canvas.translate(0, (float) scrollY);
-                mFastScroller.draw(canvas);
-                canvas.restoreToCount(restoreCount);
-            } else {
-                mFastScroller.draw(canvas);
-            }
+            mFastScroller.draw(canvas);
         }
     }
 
@@ -2443,9 +2275,6 @@
         switch (action & MotionEvent.ACTION_MASK) {
         case MotionEvent.ACTION_DOWN: {
             int touchMode = mTouchMode;
-            if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) {
-                return true;
-            }
             
             final int x = (int) ev.getX();
             final int y = (int) ev.getY();
@@ -2565,7 +2394,7 @@
         /**
          * Tracks the decay of a fling scroll
          */
-        private final OverScroller mScroller;
+        private final Scroller mScroller;
 
         /**
          * Y value reported by mScroller on the previous fling
@@ -2573,7 +2402,7 @@
         private int mLastFlingY;
 
         FlingRunnable() {
-            mScroller = new OverScroller(getContext());
+            mScroller = new Scroller(getContext());
         }
 
         void start(int initialVelocity) {
@@ -2592,32 +2421,6 @@
             }
         }
 
-        void startSpringback() {
-            if (mScroller.springback(0, mScrollY, 0, 0, 0, 0)) {
-                mTouchMode = TOUCH_MODE_OVERFLING;
-                invalidate();
-                post(this);
-            } else {
-                mTouchMode = TOUCH_MODE_REST;
-            }
-        }
-
-        void startOverfling(int initialVelocity) {
-            final int min = mScrollY > 0 ? Integer.MIN_VALUE : 0;
-            final int max = mScrollY > 0 ? 0 : Integer.MAX_VALUE;
-            mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0, min, max, 0, getHeight());
-            mTouchMode = TOUCH_MODE_OVERFLING;
-            invalidate();
-            post(this);
-        }
-
-        void edgeReached() {
-            mScroller.notifyVerticalEdgeReached(mScrollY, 0, getOverscrollMax());
-            mTouchMode = TOUCH_MODE_OVERFLING;
-            invalidate();
-            post(this);
-        }
-
         void startScroll(int distance, int duration) {
             int initialY = distance < 0 ? Integer.MAX_VALUE : 0;
             mLastFlingY = initialY;
@@ -2650,7 +2453,7 @@
                     return;
                 }
 
-                final OverScroller scroller = mScroller;
+                final Scroller scroller = mScroller;
                 boolean more = scroller.computeScrollOffset();
                 final int y = scroller.getCurrY();
 
@@ -2685,16 +2488,8 @@
                 if (motionView != null) {
                     oldTop = motionView.getTop();
                 }
-                if (trackMotionScroll(delta, delta)) {
-                    if (motionView != null) {
-                        // Tweak the scroll for how far we overshot
-                        int overshoot = -(delta - (motionView.getTop() - oldTop));
-                        overscrollBy(0, overshoot, 0, mScrollY, 0, 0,
-                                0, getOverscrollMax(), false);
-                    }
-                    edgeReached();
-                    break;
-                }
+
+                trackMotionScroll(delta, delta);
 
                 if (more) {
                     invalidate();
@@ -2712,24 +2507,6 @@
                 }
                 break;
             }
-                
-            case TOUCH_MODE_OVERFLING: {
-                final OverScroller scroller = mScroller;
-                if (scroller.computeScrollOffset()) {
-                    final int scrollY = mScrollY;
-                    final int deltaY = scroller.getCurrY() - scrollY;
-                    if (overscrollBy(0, deltaY, 0, scrollY, 0, 0,
-                            0, getOverscrollMax(), false)) {
-                        startSpringback();
-                    } else {
-                        invalidate();
-                        post(this);
-                    }
-                } else {
-                    endFling();
-                }
-                break;
-            }
             }
 
         }
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index d867980..d2829db 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1873,12 +1873,7 @@
         // TODO: Account for vertical spacing too
         final int numColumns = mNumColumns;
         final int rowCount = (mItemCount + numColumns - 1) / numColumns;
-        int result = Math.max(rowCount * 100, 0);
-        if (mScrollY != 0) {
-            // Compensate for overscroll
-            result += Math.abs((int) ((float) mScrollY / getHeight() * rowCount * 100));
-        }
-        return result;
+        return Math.max(rowCount * 100, 0);
     }
 }
 
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 3bd4767..20c2fe4 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -16,19 +16,19 @@
 
 package android.widget;
 
-import android.util.AttributeSet;
-import android.graphics.Rect;
-import android.view.View;
-import android.view.VelocityTracker;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.KeyEvent;
-import android.view.FocusFinder;
-import android.view.MotionEvent;
-import android.view.ViewParent;
-import android.view.animation.AnimationUtils;
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.FocusFinder;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.animation.AnimationUtils;
 
 import java.util.List;
 
@@ -63,7 +63,7 @@
     private long mLastScroll;
 
     private final Rect mTempRect = new Rect();
-    private OverScroller mScroller;
+    private Scroller mScroller;
 
     /**
      * Flag to indicate that we are moving focus ourselves. This is so the
@@ -189,7 +189,7 @@
 
 
     private void initScrollView() {
-        mScroller = new OverScroller(getContext());
+        mScroller = new Scroller(getContext());
         setFocusable(true);
         setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
         setWillNotDraw(false);
@@ -456,9 +456,6 @@
                 /* Release the drag */
                 mIsBeingDragged = false;
                 mActivePointerId = INVALID_POINTER;
-                if (mScroller.springback(mScrollX, mScrollY, 0, getScrollRange(), 0, 0)) {
-                    invalidate();
-                }
                 break;
             case MotionEvent.ACTION_POINTER_UP:
                 onSecondaryPointerUp(ev);
@@ -516,11 +513,7 @@
                     final int deltaX = (int) (mLastMotionX - x);
                     mLastMotionX = x;
 
-                    final int oldX = mScrollX;
-                    final int oldY = mScrollY;                    
-                    overscrollBy(deltaX, 0, mScrollX, 0, getScrollRange(), 0,
-                            getOverscrollMax(), 0, true);
-                    onScrollChanged(mScrollX, mScrollY, oldX, oldY);
+                    scrollBy(deltaX, 0);
                 }
                 break;
             case MotionEvent.ACTION_UP:
@@ -529,15 +522,8 @@
                     velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                     int initialVelocity = (int) velocityTracker.getXVelocity(mActivePointerId);
 
-                    if (getChildCount() > 0) {
-                        if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
-                            fling(-initialVelocity);
-                        } else {
-                            final int right = getScrollRange();
-                            if (mScroller.springback(mScrollX, mScrollY, 0, right, 0, 0)) {
-                                invalidate();
-                            }
-                        }
+                    if (getChildCount() > 0 && Math.abs(initialVelocity) > mMinimumVelocity) {
+                        fling(-initialVelocity);
                     }
                     
                     mActivePointerId = INVALID_POINTER;
@@ -551,9 +537,6 @@
                 break;
             case MotionEvent.ACTION_CANCEL:
                 if (mIsBeingDragged && getChildCount() > 0) {
-                    if (mScroller.springback(mScrollX, mScrollY, 0, getScrollRange(), 0, 0)) {
-                        invalidate();
-                    }
                     mActivePointerId = INVALID_POINTER;
                     mIsBeingDragged = false;
                     if (mVelocityTracker != null) {
@@ -586,32 +569,6 @@
         }
     }
     
-    @Override
-    protected void onOverscrolled(int scrollX, int scrollY,
-            boolean clampedX, boolean clampedY) {
-        // Treat animating scrolls differently; see #computeScroll() for why.
-        if (!mScroller.isFinished()) {
-            mScrollX = scrollX;
-            mScrollY = scrollY;
-            if (clampedX) {
-                mScroller.springback(mScrollX, mScrollY, 0, getScrollRange(), 0, 0);
-            }
-        } else {
-            super.scrollTo(scrollX, scrollY);
-        }
-        awakenScrollBars();
-    }
-    
-    private int getOverscrollMax() {
-        int childCount = getChildCount();
-        int containerOverscroll = (getWidth() - mPaddingLeft - mPaddingRight) / 3;
-        if (childCount > 0) {
-            return Math.min(containerOverscroll, getChildAt(0).getWidth() / 3);
-        } else {
-            return containerOverscroll;
-        }
-    }
-    
     private int getScrollRange() {
         int scrollRange = 0;
         if (getChildCount() > 0) {
@@ -994,16 +951,7 @@
             return contentWidth;
         }
         
-        int scrollRange = getChildAt(0).getRight();
-        final int scrollX = mScrollX;
-        final int overscrollRight = Math.max(0, scrollRange - contentWidth);
-        if (scrollX < 0) {
-            scrollRange -= scrollX;
-        } else if (scrollX > overscrollRight) {
-            scrollRange += scrollX - overscrollRight;
-        }
-        
-        return scrollRange;
+        return getChildAt(0).getRight();
     }
     
     @Override
@@ -1064,10 +1012,15 @@
             int x = mScroller.getCurrX();
             int y = mScroller.getCurrY();
 
-            if (oldX != x || oldY != y) {
-                overscrollBy(x - oldX, y - oldY, oldX, oldY, getScrollRange(), 0,
-                        getOverscrollMax(), 0, false);
-                onScrollChanged(mScrollX, mScrollY, oldX, oldY);
+            if (getChildCount() > 0) {
+                View child = getChildAt(0);
+                x = clamp(x, getWidth() - mPaddingRight - mPaddingLeft, child.getWidth());
+                y = clamp(y, getHeight() - mPaddingBottom - mPaddingTop, child.getHeight());
+                if (x != oldX || y != oldY) {
+                    mScrollX = x;
+                    mScrollY = y;
+                    onScrollChanged(x, y, oldX, oldY);
+                }
             }
 
             // Keep on drawing until the animation has finished.
@@ -1302,7 +1255,7 @@
             int right = getChildAt(0).getWidth();
     
             mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0, 
-                    Math.max(0, right - width), 0, 0, width/2, 0);
+                    Math.max(0, right - width), 0, 0);
     
             final boolean movingRight = velocityX > 0;
     
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 27700fd..892c44a 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -118,9 +118,6 @@
     Drawable mDivider;
     int mDividerHeight;
     
-    Drawable mOverscrollHeader;
-    Drawable mOverscrollFooter;
-
     private boolean mIsCacheColorOpaque;
     private boolean mDividerIsOpaque;
     private boolean mClipDivider;
@@ -175,16 +172,6 @@
             setDivider(d);
         }
         
-        final Drawable osHeader = a.getDrawable(com.android.internal.R.styleable.ListView_overscrollHeader);
-        if (osHeader != null) {
-            setOverscrollHeader(osHeader);
-        }
-        
-        final Drawable osFooter = a.getDrawable(com.android.internal.R.styleable.ListView_overscrollFooter);
-        if (osFooter != null) {
-            setOverscrollFooter(osFooter);
-        }
-
         // Use the height specified, zero being the default
         final int dividerHeight = a.getDimensionPixelSize(
                 com.android.internal.R.styleable.ListView_dividerHeight, 0);
@@ -2955,52 +2942,14 @@
         }
         super.setCacheColorHint(color);
     }
-
-    void drawOverscrollHeader(Canvas canvas, Drawable drawable, Rect bounds) {
-        final int height = drawable.getMinimumHeight();
-
-        canvas.save();
-        canvas.clipRect(bounds);
-
-        final int span = bounds.bottom - bounds.top;
-        if (span < height) {
-            bounds.top = bounds.bottom - height; 
-        }
-
-        drawable.setBounds(bounds);
-        drawable.draw(canvas);
-
-        canvas.restore();
-    }
-
-    void drawOverscrollFooter(Canvas canvas, Drawable drawable, Rect bounds) {
-        final int height = drawable.getMinimumHeight();
-
-        canvas.save();
-        canvas.clipRect(bounds);
-
-        final int span = bounds.bottom - bounds.top;
-        if (span < height) {
-            bounds.bottom = bounds.top + height;
-        }
-
-        drawable.setBounds(bounds);
-        drawable.draw(canvas);
-
-        canvas.restore();
-    }
-
+    
     @Override
     protected void dispatchDraw(Canvas canvas) {
         // Draw the dividers
         final int dividerHeight = mDividerHeight;
-        final Drawable overscrollHeader = mOverscrollHeader;
-        final Drawable overscrollFooter = mOverscrollFooter;
-        final boolean drawOverscrollHeader = overscrollHeader != null;
-        final boolean drawOverscrollFooter = overscrollFooter != null;
         final boolean drawDividers = dividerHeight > 0 && mDivider != null;
 
-        if (drawDividers || drawOverscrollHeader || drawOverscrollFooter) {
+        if (drawDividers) {
             // Only modify the top and bottom in the loop, we set the left and right here
             final Rect bounds = mTempRect;
             bounds.left = mPaddingLeft;
@@ -3031,28 +2980,14 @@
             if (!mStackFromBottom) {
                 int bottom = 0;
                 
-                // Draw top divider or header for overscroll
                 final int scrollY = mScrollY;
-                if (count > 0 && scrollY < 0) {
-                    if (drawOverscrollHeader) {
-                        bounds.bottom = 0;
-                        bounds.top = scrollY;
-                        drawOverscrollHeader(canvas, overscrollHeader, bounds);
-                    } else if (drawDividers) {
-                        bounds.bottom = 0;
-                        bounds.top = -dividerHeight;
-                        drawDivider(canvas, bounds, -1);
-                    }
-                }
-
                 for (int i = 0; i < count; i++) {
                     if ((headerDividers || first + i >= headerCount) &&
                             (footerDividers || first + i < footerLimit)) {
                         View child = getChildAt(i);
                         bottom = child.getBottom();
                         // Don't draw dividers next to items that are not enabled
-                        if (drawDividers &&
-                                (bottom < listBottom && !(drawOverscrollFooter && i == count - 1))) {
+                        if (drawDividers) {
                             if ((areAllItemsSelectable ||
                                     (adapter.isEnabled(first + i) && (i == count - 1 ||
                                             adapter.isEnabled(first + i + 1))))) {
@@ -3067,28 +3002,13 @@
                         }
                     }
                 }
-                
-                final int overFooterBottom = mBottom + mScrollY;
-                if (drawOverscrollFooter && first + count == itemCount &&
-                        overFooterBottom > bottom) {
-                    bounds.top = bottom;
-                    bounds.bottom = overFooterBottom;
-                    drawOverscrollFooter(canvas, overscrollFooter, bounds);
-                }
             } else {
                 int top;
                 int listTop = mListPadding.top;
 
                 final int scrollY = mScrollY;
-                
-                if (count > 0 && drawOverscrollHeader) {
-                    bounds.top = scrollY;
-                    bounds.bottom = getChildAt(0).getTop();
-                    drawOverscrollHeader(canvas, overscrollHeader, bounds);
-                }
 
-                final int start = drawOverscrollHeader ? 1 : 0;
-                for (int i = start; i < count; i++) {
+                for (int i = 0; i < count; i++) {
                     if ((headerDividers || first + i >= headerCount) &&
                             (footerDividers || first + i < footerLimit)) {
                         View child = getChildAt(i);
@@ -3114,17 +3034,10 @@
                     }
                 }
                 
-                if (count > 0 && scrollY > 0) {
-                    if (drawOverscrollFooter) {
-                        final int absListBottom = mBottom;
-                        bounds.top = absListBottom;
-                        bounds.bottom = absListBottom + scrollY;
-                        drawOverscrollFooter(canvas, overscrollFooter, bounds);
-                    } else if (drawDividers) {
-                        bounds.top = listBottom;
-                        bounds.bottom = listBottom + dividerHeight;
-                        drawDivider(canvas, bounds, -1);
-                    }
+                if (count > 0 && scrollY > 0 && drawDividers) {
+                    bounds.top = listBottom;
+                    bounds.bottom = listBottom + dividerHeight;
+                    drawDivider(canvas, bounds, -1);
                 }
             }
         }
@@ -3233,45 +3146,6 @@
         invalidate();
     }
     
-    /**
-     * Sets the drawable that will be drawn above all other list content.
-     * This area can become visible when the user overscrolls the list.
-     * 
-     * @param header The drawable to use
-     */
-    public void setOverscrollHeader(Drawable header) {
-        mOverscrollHeader = header;
-        if (mScrollY < 0) {
-            invalidate();
-        }
-    }
-    
-    /**
-     * @return The drawable that will be drawn above all other list content
-     */
-    public Drawable getOverscrollHeader() {
-        return mOverscrollHeader;
-    }
-    
-    /**
-     * Sets the drawable that will be drawn below all other list content.
-     * This area can become visible when the user overscrolls the list,
-     * or when the list's content does not fully fill the container area.
-     * 
-     * @param footer The drawable to use
-     */
-    public void setOverscrollFooter(Drawable footer) {
-        mOverscrollFooter = footer;
-        invalidate();
-    }
-    
-    /**
-     * @return The drawable that will be drawn below all other list content
-     */
-    public Drawable getOverscrollFooter() {
-        return mOverscrollFooter;
-    }
-
     @Override
     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
         super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
@@ -3691,20 +3565,6 @@
             mCheckedIdStates.clear();
         }
     }
-    
-    @Override
-    int getOverscrollMax() {
-        if (mStackFromBottom) {
-            final int childCount = getChildCount();
-            if (childCount > 0) {
-                return Math.min(mOverscrollMax,
-                        (getHeight() - getChildAt(0).getTop()) / OVERSCROLL_LIMIT_DIVISOR);
-            } else {
-                return mOverscrollMax;
-            }
-        }
-        return super.getOverscrollMax();
-    }
 
     static class SavedState extends BaseSavedState {
         SparseBooleanArray checkState;
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
deleted file mode 100644
index e8d92de..0000000
--- a/core/java/android/widget/OverScroller.java
+++ /dev/null
@@ -1,682 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.util.FloatMath;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-import android.widget.Scroller.MagneticScroller;
-
-/**
- * This class encapsulates scrolling with the ability to overshoot the bounds
- * of a scrolling operation. This class is a drop-in replacement for
- * {@link android.widget.Scroller} in most cases.
- */
-public class OverScroller {
-    private int mMode;
-
-    private MagneticOverScroller mScrollerX;
-    private MagneticOverScroller mScrollerY;
-
-    private final Interpolator mInterpolator;
-
-    private static final int DEFAULT_DURATION = 250;
-    private static final int SCROLL_MODE = 0;
-    private static final int FLING_MODE = 1;
-
-    /**
-     * Creates an OverScroller with a viscous fluid scroll interpolator.
-     * @param context
-     */
-    public OverScroller(Context context) {
-        this(context, null);
-    }
-
-    /**
-     * Creates an OverScroller with default edge bounce coefficients.
-     * @param context The context of this application.
-     * @param interpolator The scroll interpolator. If null, a default (viscous) interpolator will
-     * be used.
-     */
-    public OverScroller(Context context, Interpolator interpolator) {
-        this(context, interpolator, MagneticOverScroller.DEFAULT_BOUNCE_COEFFICIENT,
-                MagneticOverScroller.DEFAULT_BOUNCE_COEFFICIENT);
-    }
-
-    /**
-     * Creates an OverScroller.
-     * @param context The context of this application.
-     * @param interpolator The scroll interpolator. If null, a default (viscous) interpolator will
-     * be used.
-     * @param bounceCoefficientX A value between 0 and 1 that will determine the proportion of the
-     * velocity which is preserved in the bounce when the horizontal edge is reached. A null value
-     * means no bounce.
-     * @param bounceCoefficientY Same as bounceCoefficientX but for the vertical direction.
-     */
-    public OverScroller(Context context, Interpolator interpolator,
-            float bounceCoefficientX, float bounceCoefficientY) {
-        mInterpolator = interpolator;
-        mScrollerX = new MagneticOverScroller();
-        mScrollerY = new MagneticOverScroller();
-        MagneticScroller.initializeFromContext(context);
-
-        mScrollerX.setBounceCoefficient(bounceCoefficientX);
-        mScrollerY.setBounceCoefficient(bounceCoefficientY);
-    }
-
-    /**
-     *
-     * Returns whether the scroller has finished scrolling.
-     *
-     * @return True if the scroller has finished scrolling, false otherwise.
-     */
-    public final boolean isFinished() {
-        return mScrollerX.mFinished && mScrollerY.mFinished;
-    }
-
-    /**
-     * Force the finished field to a particular value. Contrary to
-     * {@link #abortAnimation()}, forcing the animation to finished
-     * does NOT cause the scroller to move to the final x and y
-     * position.
-     *
-     * @param finished The new finished value.
-     */
-    public final void forceFinished(boolean finished) {
-        mScrollerX.mFinished = mScrollerY.mFinished = finished;
-    }
-
-    /**
-     * Returns the current X offset in the scroll.
-     *
-     * @return The new X offset as an absolute distance from the origin.
-     */
-    public final int getCurrX() {
-        return mScrollerX.mCurrentPosition;
-    }
-
-    /**
-     * Returns the current Y offset in the scroll.
-     *
-     * @return The new Y offset as an absolute distance from the origin.
-     */
-    public final int getCurrY() {
-        return mScrollerY.mCurrentPosition;
-    }
-
-    /**
-     * @hide
-     * Returns the current velocity.
-     *
-     * @return The original velocity less the deceleration, norm of the X and Y velocity vector.
-     */
-    public float getCurrVelocity() {
-        float squaredNorm = mScrollerX.mCurrVelocity * mScrollerX.mCurrVelocity;
-        squaredNorm += mScrollerY.mCurrVelocity * mScrollerY.mCurrVelocity;
-        return FloatMath.sqrt(squaredNorm);
-    }
-
-    /**
-     * Returns the start X offset in the scroll.
-     *
-     * @return The start X offset as an absolute distance from the origin.
-     */
-    public final int getStartX() {
-        return mScrollerX.mStart;
-    }
-
-    /**
-     * Returns the start Y offset in the scroll.
-     *
-     * @return The start Y offset as an absolute distance from the origin.
-     */
-    public final int getStartY() {
-        return mScrollerY.mStart;
-    }
-
-    /**
-     * Returns where the scroll will end. Valid only for "fling" scrolls.
-     *
-     * @return The final X offset as an absolute distance from the origin.
-     */
-    public final int getFinalX() {
-        return mScrollerX.mFinal;
-    }
-
-    /**
-     * Returns where the scroll will end. Valid only for "fling" scrolls.
-     *
-     * @return The final Y offset as an absolute distance from the origin.
-     */
-    public final int getFinalY() {
-        return mScrollerY.mFinal;
-    }
-
-    /**
-     * Returns how long the scroll event will take, in milliseconds.
-     *
-     * @return The duration of the scroll in milliseconds.
-     *
-     * @hide Pending removal once nothing depends on it
-     * @deprecated OverScrollers don't necessarily have a fixed duration.
-     *             This function will lie to the best of its ability.
-     */
-    public final int getDuration() {
-        return Math.max(mScrollerX.mDuration, mScrollerY.mDuration);
-    }
-
-    /**
-     * Extend the scroll animation. This allows a running animation to scroll
-     * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}.
-     *
-     * @param extend Additional time to scroll in milliseconds.
-     * @see #setFinalX(int)
-     * @see #setFinalY(int)
-     *
-     * @hide Pending removal once nothing depends on it
-     * @deprecated OverScrollers don't necessarily have a fixed duration.
-     *             Instead of setting a new final position and extending
-     *             the duration of an existing scroll, use startScroll
-     *             to begin a new animation.
-     */
-    public void extendDuration(int extend) {
-        mScrollerX.extendDuration(extend);
-        mScrollerY.extendDuration(extend);
-    }
-
-    /**
-     * Sets the final position (X) for this scroller.
-     *
-     * @param newX The new X offset as an absolute distance from the origin.
-     * @see #extendDuration(int)
-     * @see #setFinalY(int)
-     *
-     * @hide Pending removal once nothing depends on it
-     * @deprecated OverScroller's final position may change during an animation.
-     *             Instead of setting a new final position and extending
-     *             the duration of an existing scroll, use startScroll
-     *             to begin a new animation.
-     */
-    public void setFinalX(int newX) {
-        mScrollerX.setFinalPosition(newX);
-    }
-
-    /**
-     * Sets the final position (Y) for this scroller.
-     *
-     * @param newY The new Y offset as an absolute distance from the origin.
-     * @see #extendDuration(int)
-     * @see #setFinalX(int)
-     *
-     * @hide Pending removal once nothing depends on it
-     * @deprecated OverScroller's final position may change during an animation.
-     *             Instead of setting a new final position and extending
-     *             the duration of an existing scroll, use startScroll
-     *             to begin a new animation.
-     */
-    public void setFinalY(int newY) {
-        mScrollerY.setFinalPosition(newY);
-    }
-
-    /**
-     * Call this when you want to know the new location. If it returns true, the
-     * animation is not yet finished.
-     */
-    public boolean computeScrollOffset() {
-        if (isFinished()) {
-            return false;
-        }
-
-        switch (mMode) {
-            case SCROLL_MODE:
-                long time = AnimationUtils.currentAnimationTimeMillis();
-                // Any scroller can be used for time, since they were started
-                // together in scroll mode. We use X here.
-                final long elapsedTime = time - mScrollerX.mStartTime;
-
-                final int duration = mScrollerX.mDuration;
-                if (elapsedTime < duration) {
-                    float q = (float) (elapsedTime) / duration;
-
-                    if (mInterpolator == null)
-                        q = Scroller.viscousFluid(q);
-                    else
-                        q = mInterpolator.getInterpolation(q);
-
-                    mScrollerX.updateScroll(q);
-                    mScrollerY.updateScroll(q);
-                } else {
-                    abortAnimation();
-                }
-                break;
-
-            case FLING_MODE:
-                if (!mScrollerX.mFinished) {
-                    if (!mScrollerX.update()) {
-                        if (!mScrollerX.continueWhenFinished()) {
-                            mScrollerX.finish();
-                        }
-                    }
-                }
-
-                if (!mScrollerY.mFinished) {
-                    if (!mScrollerY.update()) {
-                        if (!mScrollerY.continueWhenFinished()) {
-                            mScrollerY.finish();
-                        }
-                    }
-                }
-
-                break;
-        }
-
-        return true;
-    }
-
-    /**
-     * Start scrolling by providing a starting point and the distance to travel.
-     * The scroll will use the default value of 250 milliseconds for the
-     * duration.
-     *
-     * @param startX Starting horizontal scroll offset in pixels. Positive
-     *        numbers will scroll the content to the left.
-     * @param startY Starting vertical scroll offset in pixels. Positive numbers
-     *        will scroll the content up.
-     * @param dx Horizontal distance to travel. Positive numbers will scroll the
-     *        content to the left.
-     * @param dy Vertical distance to travel. Positive numbers will scroll the
-     *        content up.
-     */
-    public void startScroll(int startX, int startY, int dx, int dy) {
-        startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
-    }
-
-    /**
-     * Start scrolling by providing a starting point and the distance to travel.
-     *
-     * @param startX Starting horizontal scroll offset in pixels. Positive
-     *        numbers will scroll the content to the left.
-     * @param startY Starting vertical scroll offset in pixels. Positive numbers
-     *        will scroll the content up.
-     * @param dx Horizontal distance to travel. Positive numbers will scroll the
-     *        content to the left.
-     * @param dy Vertical distance to travel. Positive numbers will scroll the
-     *        content up.
-     * @param duration Duration of the scroll in milliseconds.
-     */
-    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
-        mMode = SCROLL_MODE;
-        mScrollerX.startScroll(startX, dx, duration);
-        mScrollerY.startScroll(startY, dy, duration);
-    }
-
-    /**
-     * Call this when you want to 'spring back' into a valid coordinate range.
-     *
-     * @param startX Starting X coordinate
-     * @param startY Starting Y coordinate
-     * @param minX Minimum valid X value
-     * @param maxX Maximum valid X value
-     * @param minY Minimum valid Y value
-     * @param maxY Minimum valid Y value
-     * @return true if a springback was initiated, false if startX and startY were
-     *          already within the valid range.
-     */
-    public boolean springback(int startX, int startY, int minX, int maxX, int minY, int maxY) {
-        mMode = FLING_MODE;
-
-        // Make sure both methods are called.
-        final boolean spingbackX = mScrollerX.springback(startX, minX, maxX);
-        final boolean spingbackY = mScrollerY.springback(startY, minY, maxY);
-        return spingbackX || spingbackY;
-    }
-
-    public void fling(int startX, int startY, int velocityX, int velocityY,
-            int minX, int maxX, int minY, int maxY) {
-        fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, 0, 0);
-    }
-
-    /**
-     * Start scrolling based on a fling gesture. The distance traveled will
-     * depend on the initial velocity of the fling.
-     *
-     * @param startX Starting point of the scroll (X)
-     * @param startY Starting point of the scroll (Y)
-     * @param velocityX Initial velocity of the fling (X) measured in pixels per
-     *            second.
-     * @param velocityY Initial velocity of the fling (Y) measured in pixels per
-     *            second
-     * @param minX Minimum X value. The scroller will not scroll past this point
-     *            unless overX > 0. If overfling is allowed, it will use minX as
-     *            a springback boundary.
-     * @param maxX Maximum X value. The scroller will not scroll past this point
-     *            unless overX > 0. If overfling is allowed, it will use maxX as
-     *            a springback boundary.
-     * @param minY Minimum Y value. The scroller will not scroll past this point
-     *            unless overY > 0. If overfling is allowed, it will use minY as
-     *            a springback boundary.
-     * @param maxY Maximum Y value. The scroller will not scroll past this point
-     *            unless overY > 0. If overfling is allowed, it will use maxY as
-     *            a springback boundary.
-     * @param overX Overfling range. If > 0, horizontal overfling in either
-     *            direction will be possible.
-     * @param overY Overfling range. If > 0, vertical overfling in either
-     *            direction will be possible.
-     */
-    public void fling(int startX, int startY, int velocityX, int velocityY,
-            int minX, int maxX, int minY, int maxY, int overX, int overY) {
-        mMode = FLING_MODE;
-        mScrollerX.fling(startX, velocityX, minX, maxX, overX);
-        mScrollerY.fling(startY, velocityY, minY, maxY, overY);
-    }
-
-    /**
-     * Notify the scroller that we've reached a horizontal boundary.
-     * Normally the information to handle this will already be known
-     * when the animation is started, such as in a call to one of the
-     * fling functions. However there are cases where this cannot be known
-     * in advance. This function will transition the current motion and
-     * animate from startX to finalX as appropriate.
-     *
-     * @param startX Starting/current X position
-     * @param finalX Desired final X position
-     * @param overX Magnitude of overscroll allowed. This should be the maximum
-     *              desired distance from finalX. Absolute value - must be positive.
-     */
-    public void notifyHorizontalEdgeReached(int startX, int finalX, int overX) {
-        mScrollerX.notifyEdgeReached(startX, finalX, overX);
-    }
-
-    /**
-     * Notify the scroller that we've reached a vertical boundary.
-     * Normally the information to handle this will already be known
-     * when the animation is started, such as in a call to one of the
-     * fling functions. However there are cases where this cannot be known
-     * in advance. This function will animate a parabolic motion from
-     * startY to finalY.
-     *
-     * @param startY Starting/current Y position
-     * @param finalY Desired final Y position
-     * @param overY Magnitude of overscroll allowed. This should be the maximum
-     *              desired distance from finalY.
-     */
-    public void notifyVerticalEdgeReached(int startY, int finalY, int overY) {
-        mScrollerY.notifyEdgeReached(startY, finalY, overY);
-    }
-
-    /**
-     * Returns whether the current Scroller is currently returning to a valid position.
-     * Valid bounds were provided by the
-     * {@link #fling(int, int, int, int, int, int, int, int, int, int)} method.
-     *
-     * One should check this value before calling
-     * {@link #startScroll(int, int, int, int)} as the interpolation currently in progress
-     * to restore a valid position will then be stopped. The caller has to take into account
-     * the fact that the started scroll will start from an overscrolled position.
-     * 
-     * @return true when the current position is overscrolled and in the process of
-     *         interpolating back to a valid value.
-     */
-    public boolean isOverscrolled() {
-        return ((!mScrollerX.mFinished &&
-                mScrollerX.mState != MagneticOverScroller.TO_EDGE) ||
-                (!mScrollerY.mFinished &&
-                        mScrollerY.mState != MagneticOverScroller.TO_EDGE));
-    }
-
-    /**
-     * Stops the animation. Contrary to {@link #forceFinished(boolean)},
-     * aborting the animating causes the scroller to move to the final x and y
-     * positions.
-     *
-     * @see #forceFinished(boolean)
-     */
-    public void abortAnimation() {
-        mScrollerX.finish();
-        mScrollerY.finish();
-    }
-
-    /**
-     * Returns the time elapsed since the beginning of the scrolling.
-     *
-     * @return The elapsed time in milliseconds.
-     * 
-     * @hide
-     */
-    public int timePassed() {
-        final long time = AnimationUtils.currentAnimationTimeMillis();
-        final long startTime = Math.min(mScrollerX.mStartTime, mScrollerY.mStartTime);
-        return (int) (time - startTime);
-    }
-
-    static class MagneticOverScroller extends Scroller.MagneticScroller {
-        private static final int TO_EDGE = 0;
-        private static final int TO_BOUNDARY = 1;
-        private static final int TO_BOUNCE = 2;
-
-        private int mState = TO_EDGE;
-
-        // The allowed overshot distance before boundary is reached.
-        private int mOver;
-
-        // Duration in milliseconds to go back from edge to edge. Springback is half of it.
-        private static final int OVERSCROLL_SPRINGBACK_DURATION = 200;
-
-        // Oscillation period
-        private static final float TIME_COEF =
-            1000.0f * (float) Math.PI / OVERSCROLL_SPRINGBACK_DURATION;
-
-        // If the velocity is smaller than this value, no bounce is triggered
-        // when the edge limits are reached (would result in a zero pixels
-        // displacement anyway).
-        private static final float MINIMUM_VELOCITY_FOR_BOUNCE = 140.0f;
-
-        // Proportion of the velocity that is preserved when the edge is reached.
-        private static final float DEFAULT_BOUNCE_COEFFICIENT = 0.16f;
-
-        private float mBounceCoefficient = DEFAULT_BOUNCE_COEFFICIENT;
-
-        void setBounceCoefficient(float coefficient) {
-            mBounceCoefficient = coefficient;
-        }
-
-        boolean springback(int start, int min, int max) {
-            mFinished = true;
-
-            mStart = start;
-            mVelocity = 0;
-
-            mStartTime = AnimationUtils.currentAnimationTimeMillis();
-            mDuration = 0;
-
-            if (start < min) {
-                startSpringback(start, min, false);
-            } else if (start > max) {
-                startSpringback(start, max, true);
-            }
-
-            return !mFinished;
-        }
-
-        private void startSpringback(int start, int end, boolean positive) {
-            mFinished = false;
-            mState = TO_BOUNCE;
-            mStart = mFinal = end;
-            mDuration = OVERSCROLL_SPRINGBACK_DURATION;
-            mStartTime -= OVERSCROLL_SPRINGBACK_DURATION / 2;
-            mVelocity = (int) (Math.abs(end - start) * TIME_COEF * (positive ? 1.0 : -1.0f));
-        }
-
-        void fling(int start, int velocity, int min, int max, int over) {
-            mState = TO_EDGE;
-            mOver = over;
-
-            super.fling(start, velocity, min, max);
-
-            if (start > max) {
-                if (start >= max + over) {
-                    springback(max + over, min, max);
-                } else {
-                    if (velocity <= 0) {
-                        springback(start, min, max);
-                    } else {
-                        long time = AnimationUtils.currentAnimationTimeMillis();
-                        final double durationSinceEdge =
-                            Math.atan((start-max) * TIME_COEF / velocity) / TIME_COEF;
-                        mStartTime = (int) (time - 1000.0f * durationSinceEdge);
-
-                        // Simulate a bounce that started from edge
-                        mStart = max;
-
-                        mVelocity = (int) (velocity / Math.cos(durationSinceEdge * TIME_COEF));
-
-                        onEdgeReached();
-                    }
-                }
-            } else {
-                if (start < min) {
-                    if (start <= min - over) {
-                        springback(min - over, min, max);
-                    } else {
-                        if (velocity >= 0) {
-                            springback(start, min, max);
-                        } else {
-                            long time = AnimationUtils.currentAnimationTimeMillis();
-                            final double durationSinceEdge =
-                                Math.atan((start-min) * TIME_COEF / velocity) / TIME_COEF;
-                            mStartTime = (int) (time - 1000.0f * durationSinceEdge);
-
-                            // Simulate a bounce that started from edge
-                            mStart = min;
-
-                            mVelocity = (int) (velocity / Math.cos(durationSinceEdge * TIME_COEF));
-
-                            onEdgeReached();
-                        }
-
-                    }
-                }
-            }
-        }
-
-        void notifyEdgeReached(int start, int end, int over) {
-            mDeceleration = getDeceleration(mVelocity);
-
-            // Local time, used to compute edge crossing time.
-            float timeCurrent = mCurrVelocity / mDeceleration;
-            final int distance = end - start;
-            float timeEdge = -(float) Math.sqrt((2.0f * distance / mDeceleration)
-                    + (timeCurrent * timeCurrent));
-
-            mVelocity = (int) (mDeceleration * timeEdge);
-
-            // Simulate a symmetric bounce that started from edge
-            mStart = end;
-
-            mOver = over;
-
-            long time = AnimationUtils.currentAnimationTimeMillis();
-            mStartTime = (int) (time - 1000.0f * (timeCurrent - timeEdge));
-
-            onEdgeReached();
-        }
-
-        private void onEdgeReached() {
-            // mStart, mVelocity and mStartTime were adjusted to their values when edge was reached.
-            final float distance = mVelocity / TIME_COEF;
-
-            if (Math.abs(distance) < mOver) {
-                // Spring force will bring us back to final position
-                mState = TO_BOUNCE;
-                mFinal = mStart;
-                mDuration = OVERSCROLL_SPRINGBACK_DURATION;
-            } else {
-                // Velocity is too high, we will hit the boundary limit
-                mState = TO_BOUNDARY;
-                int over = mVelocity > 0 ? mOver : -mOver;
-                mFinal = mStart + over;
-                mDuration = (int) (1000.0f * Math.asin(over / distance) / TIME_COEF);
-            }
-        }
-
-        @Override
-        boolean continueWhenFinished() {
-            switch (mState) {
-                case TO_EDGE:
-                    // Duration from start to null velocity
-                    int duration = (int) (-1000.0f * mVelocity / mDeceleration);
-                    if (mDuration < duration) {
-                        // If the animation was clamped, we reached the edge
-                        mStart = mFinal;
-                        // Speed when edge was reached
-                        mVelocity = (int) (mVelocity + mDeceleration * mDuration / 1000.0f);
-                        mStartTime += mDuration;
-                        onEdgeReached();
-                    } else {
-                        // Normal stop, no need to continue
-                        return false;
-                    }
-                    break;
-                case TO_BOUNDARY:
-                    mStartTime += mDuration;
-                    startSpringback(mFinal, mFinal - (mVelocity > 0 ? mOver:-mOver), mVelocity > 0);
-                    break;
-                case TO_BOUNCE:
-                    //mVelocity = (int) (mVelocity * BOUNCE_COEFFICIENT);
-                    mVelocity = (int) (mVelocity * mBounceCoefficient);
-                    if (Math.abs(mVelocity) < MINIMUM_VELOCITY_FOR_BOUNCE) {
-                        return false;
-                    }
-                    mStartTime += mDuration;
-                    break;
-            }
-
-            update();
-            return true;
-        }
-
-        /*
-         * Update the current position and velocity for current time. Returns
-         * true if update has been done and false if animation duration has been
-         * reached.
-         */
-        @Override
-        boolean update() {
-            final long time = AnimationUtils.currentAnimationTimeMillis();
-            final long duration = time - mStartTime;
-
-            if (duration > mDuration) {
-                return false;
-            }
-
-            double distance;
-            final float t = duration / 1000.0f;
-            if (mState == TO_EDGE) {
-                mCurrVelocity = mVelocity + mDeceleration * t;
-                distance = mVelocity * t + mDeceleration * t * t / 2.0f;
-            } else {
-                final float d = t * TIME_COEF;
-                mCurrVelocity = mVelocity * (float)Math.cos(d);
-                distance = mVelocity / TIME_COEF * Math.sin(d);
-            }
-
-            mCurrentPosition = mStart + (int) distance;
-            return true;
-        }
-    }
-}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 23e1234..a02aa00 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -59,7 +59,7 @@
     private long mLastScroll;
 
     private final Rect mTempRect = new Rect();
-    private OverScroller mScroller;
+    private Scroller mScroller;
 
     /**
      * Flag to indicate that we are moving focus ourselves. This is so the
@@ -185,7 +185,7 @@
 
 
     private void initScrollView() {
-        mScroller = new OverScroller(getContext());
+        mScroller = new Scroller(getContext());
         setFocusable(true);
         setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
         setWillNotDraw(false);
@@ -453,9 +453,6 @@
                 /* Release the drag */
                 mIsBeingDragged = false;
                 mActivePointerId = INVALID_POINTER;
-                if (mScroller.springback(mScrollX, mScrollY, 0, 0, 0, getScrollRange())) {
-                    invalidate();
-                }
                 break;
             case MotionEvent.ACTION_POINTER_UP:
                 onSecondaryPointerUp(ev);
@@ -513,11 +510,7 @@
                     final int deltaY = (int) (mLastMotionY - y);
                     mLastMotionY = y;
 
-                    final int oldX = mScrollX;
-                    final int oldY = mScrollY;
-                    overscrollBy(0, deltaY, 0, mScrollY, 0, getScrollRange(),
-                            0, getOverscrollMax(), true);
-                    onScrollChanged(mScrollX, mScrollY, oldX, oldY);
+                    scrollBy(0, deltaY);
                 }
                 break;
             case MotionEvent.ACTION_UP: 
@@ -526,15 +519,8 @@
                     velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                     int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
 
-                    if (getChildCount() > 0) {
-                        if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
-                            fling(-initialVelocity);
-                        } else {
-                            final int bottom = getScrollRange();
-                            if (mScroller.springback(mScrollX, mScrollY, 0, 0, 0, bottom)) {
-                                invalidate();
-                            }
-                        }
+                    if (getChildCount() > 0 && Math.abs(initialVelocity) > mMinimumVelocity) {
+                        fling(-initialVelocity);
                     }
 
                     mActivePointerId = INVALID_POINTER;
@@ -548,9 +534,6 @@
                 break;
             case MotionEvent.ACTION_CANCEL:
                 if (mIsBeingDragged && getChildCount() > 0) {
-                    if (mScroller.springback(mScrollX, mScrollY, 0, 0, 0, getScrollRange())) {
-                        invalidate();
-                    }
                     mActivePointerId = INVALID_POINTER;
                     mIsBeingDragged = false;
                     if (mVelocityTracker != null) {
@@ -583,32 +566,6 @@
         }
     }
     
-    @Override
-    protected void onOverscrolled(int scrollX, int scrollY,
-            boolean clampedX, boolean clampedY) {
-        // Treat animating scrolls differently; see #computeScroll() for why.
-        if (!mScroller.isFinished()) {
-            mScrollX = scrollX;
-            mScrollY = scrollY;
-            if (clampedY) {
-                mScroller.springback(mScrollX, mScrollY, 0, 0, 0, getScrollRange());
-            }
-        } else {
-            super.scrollTo(scrollX, scrollY);
-        }
-        awakenScrollBars();
-    }
-    
-    private int getOverscrollMax() {
-        int childCount = getChildCount();
-        int containerOverscroll = (getHeight() - mPaddingBottom - mPaddingTop) / 3;
-        if (childCount > 0) {
-            return Math.min(containerOverscroll, getChildAt(0).getHeight() / 3);
-        } else {
-            return containerOverscroll;
-        }
-    }
-    
     private int getScrollRange() {
         int scrollRange = 0;
         if (getChildCount() > 0) {
@@ -995,16 +952,7 @@
             return contentHeight;
         }
         
-        int scrollRange = getChildAt(0).getBottom();
-        final int scrollY = mScrollY;
-        final int overscrollBottom = Math.max(0, scrollRange - contentHeight);
-        if (scrollY < 0) {
-            scrollRange -= scrollY;
-        } else if (scrollY > overscrollBottom) {
-            scrollRange += scrollY - overscrollBottom;
-        }
-        
-        return scrollRange;
+        return getChildAt(0).getBottom();
     }
 
     @Override
@@ -1065,12 +1013,17 @@
             int x = mScroller.getCurrX();
             int y = mScroller.getCurrY();
 
-            if (oldX != x || oldY != y) {
-                overscrollBy(x - oldX, y - oldY, oldX, oldY, 0, getScrollRange(),
-                        0, getOverscrollMax(), false);
-                onScrollChanged(mScrollX, mScrollY, oldX, oldY);
+            if (getChildCount() > 0) {
+                View child = getChildAt(0);
+                x = clamp(x, getWidth() - mPaddingRight - mPaddingLeft, child.getWidth());
+                y = clamp(y, getHeight() - mPaddingBottom - mPaddingTop, child.getHeight());
+                if (x != oldX || y != oldY) {
+                    mScrollX = x;
+                    mScrollY = y;
+                    onScrollChanged(x, y, oldX, oldY);
+                }
             }
-            
+
             // Keep on drawing until the animation has finished.
             postInvalidate();
         }
@@ -1304,7 +1257,7 @@
             int bottom = getChildAt(0).getHeight();
     
             mScroller.fling(mScrollX, mScrollY, 0, velocityY, 0, 0, 0, 
-                    Math.max(0, bottom - height), 0, height/2);
+                    Math.max(0, bottom - height));
     
             final boolean movingDown = velocityY > 0;
     
diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java
index abb3e32..11dab02 100644
--- a/core/java/android/widget/Scroller.java
+++ b/core/java/android/widget/Scroller.java
@@ -16,10 +16,8 @@
 
 package android.widget;
 
-
 import android.content.Context;
 import android.hardware.SensorManager;
-import android.util.FloatMath;
 import android.view.ViewConfiguration;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
@@ -27,34 +25,48 @@
 
 /**
  * This class encapsulates scrolling.  The duration of the scroll
- * is either specified along with the distance or depends on the initial fling velocity.
- * Past this time, the scrolling is automatically moved to its final stage and
- * computeScrollOffset() will always return false to indicate that scrolling is over.
+ * can be passed in the constructor and specifies the maximum time that
+ * the scrolling animation should take.  Past this time, the scrolling is 
+ * automatically moved to its final stage and computeScrollOffset()
+ * will always return false to indicate that scrolling is over.
  */
 public class Scroller  {
     private int mMode;
 
-    private MagneticScroller mScrollerX;
-    private MagneticScroller mScrollerY;
+    private int mStartX;
+    private int mStartY;
+    private int mFinalX;
+    private int mFinalY;
 
-    private final Interpolator mInterpolator;
+    private int mMinX;
+    private int mMaxX;
+    private int mMinY;
+    private int mMaxY;
+
+    private int mCurrX;
+    private int mCurrY;
+    private long mStartTime;
+    private int mDuration;
+    private float mDurationReciprocal;
+    private float mDeltaX;
+    private float mDeltaY;
+    private float mViscousFluidScale;
+    private float mViscousFluidNormalize;
+    private boolean mFinished;
+    private Interpolator mInterpolator;
+
+    private float mCoeffX = 0.0f;
+    private float mCoeffY = 1.0f;
+    private float mVelocity;
 
     private static final int DEFAULT_DURATION = 250;
     private static final int SCROLL_MODE = 0;
     private static final int FLING_MODE = 1;
 
-    // This controls the viscous fluid effect (how much of it)
-    private final static float VISCOUS_FLUID_SCALE = 8.0f;
-    private static float VISCOUS_FLUID_NORMALIZE;
-
-    static {
-        // Set a neutral value that will be used in the next call to viscousFluid().
-        VISCOUS_FLUID_NORMALIZE = 1.0f;
-        VISCOUS_FLUID_NORMALIZE = 1.0f / viscousFluid(1.0f);
-    }
+    private final float mDeceleration;
 
     /**
-     * Create a Scroller with a viscous fluid scroll interpolator.
+     * Create a Scroller with the default duration and interpolator.
      */
     public Scroller(Context context) {
         this(context, null);
@@ -65,13 +77,15 @@
      * null, the default (viscous) interpolator will be used.
      */
     public Scroller(Context context, Interpolator interpolator) {
-        mScrollerX = new MagneticScroller();
-        mScrollerY = new MagneticScroller();
-        MagneticScroller.initializeFromContext(context);
-
+        mFinished = true;
         mInterpolator = interpolator;
+        float ppi = context.getResources().getDisplayMetrics().density * 160.0f;
+        mDeceleration = SensorManager.GRAVITY_EARTH   // g (m/s^2)
+                      * 39.37f                        // inch/meter
+                      * ppi                           // pixels per inch
+                      * ViewConfiguration.getScrollFriction();
     }
-
+    
     /**
      * 
      * Returns whether the scroller has finished scrolling.
@@ -79,148 +93,150 @@
      * @return True if the scroller has finished scrolling, false otherwise.
      */
     public final boolean isFinished() {
-        return mScrollerX.mFinished && mScrollerY.mFinished;
+        return mFinished;
     }
-
+    
     /**
      * Force the finished field to a particular value.
-     * 
+     *  
      * @param finished The new finished value.
      */
     public final void forceFinished(boolean finished) {
-        mScrollerX.mFinished = mScrollerY.mFinished = finished;
+        mFinished = finished;
     }
-
+    
     /**
      * Returns how long the scroll event will take, in milliseconds.
      * 
      * @return The duration of the scroll in milliseconds.
      */
     public final int getDuration() {
-        return Math.max(mScrollerX.mDuration, mScrollerY.mDuration);
+        return mDuration;
     }
-
+    
     /**
-     * Returns the current X offset in the scroll.
+     * Returns the current X offset in the scroll. 
      * 
      * @return The new X offset as an absolute distance from the origin.
      */
     public final int getCurrX() {
-        return mScrollerX.mCurrentPosition;
+        return mCurrX;
     }
-
+    
     /**
-     * Returns the current Y offset in the scroll.
+     * Returns the current Y offset in the scroll. 
      * 
      * @return The new Y offset as an absolute distance from the origin.
      */
     public final int getCurrY() {
-        return mScrollerY.mCurrentPosition;
+        return mCurrY;
     }
-
+    
     /**
      * @hide
      * Returns the current velocity.
-     * 
-     * @return The original velocity less the deceleration, norm of the X and Y velocity vector.
+     *
+     * @return The original velocity less the deceleration. Result may be
+     * negative.
      */
     public float getCurrVelocity() {
-        float squaredNorm = mScrollerX.mCurrVelocity * mScrollerX.mCurrVelocity;
-        squaredNorm += mScrollerY.mCurrVelocity * mScrollerY.mCurrVelocity;
-        return FloatMath.sqrt(squaredNorm);
+        return mVelocity - mDeceleration * timePassed() / 2000.0f;
     }
 
     /**
-     * Returns the start X offset in the scroll.
+     * Returns the start X offset in the scroll. 
      * 
      * @return The start X offset as an absolute distance from the origin.
      */
     public final int getStartX() {
-        return mScrollerX.mStart;
+        return mStartX;
     }
-
+    
     /**
-     * Returns the start Y offset in the scroll.
+     * Returns the start Y offset in the scroll. 
      * 
      * @return The start Y offset as an absolute distance from the origin.
      */
     public final int getStartY() {
-        return mScrollerY.mStart;
+        return mStartY;
     }
-
+    
     /**
      * Returns where the scroll will end. Valid only for "fling" scrolls.
      * 
      * @return The final X offset as an absolute distance from the origin.
      */
     public final int getFinalX() {
-        return mScrollerX.mFinal;
+        return mFinalX;
     }
-
+    
     /**
      * Returns where the scroll will end. Valid only for "fling" scrolls.
      * 
      * @return The final Y offset as an absolute distance from the origin.
      */
     public final int getFinalY() {
-        return mScrollerY.mFinal;
+        return mFinalY;
     }
 
     /**
-     * Call this when you want to know the new location. If it returns true, the
-     * animation is not yet finished.
-     */
+     * Call this when you want to know the new location.  If it returns true,
+     * the animation is not yet finished.  loc will be altered to provide the
+     * new location.
+     */ 
     public boolean computeScrollOffset() {
-        if (isFinished()) {
+        if (mFinished) {
             return false;
         }
 
-        switch (mMode) {
+        int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
+    
+        if (timePassed < mDuration) {
+            switch (mMode) {
             case SCROLL_MODE:
-                long time = AnimationUtils.currentAnimationTimeMillis();
-                // Any scroller can be used for time, since they were started
-                // together in scroll mode. We use X here.
-                final long elapsedTime = time - mScrollerX.mStartTime;
-
-                final int duration = mScrollerX.mDuration;
-                if (elapsedTime < duration) {
-                    float q = (float) (elapsedTime) / duration;
-
-                    if (mInterpolator == null)
-                        q = viscousFluid(q);
-                    else
-                        q = mInterpolator.getInterpolation(q);
-
-                    mScrollerX.updateScroll(q);
-                    mScrollerY.updateScroll(q);
-                } else {
-                    abortAnimation();
+                float x = (float)timePassed * mDurationReciprocal;
+    
+                if (mInterpolator == null)
+                    x = viscousFluid(x); 
+                else
+                    x = mInterpolator.getInterpolation(x);
+    
+                mCurrX = mStartX + Math.round(x * mDeltaX);
+                mCurrY = mStartY + Math.round(x * mDeltaY);
+                if ((mCurrX == mFinalX) && (mCurrY == mFinalY)) {
+                    mFinished = true;
                 }
                 break;
-
             case FLING_MODE:
-                if (!mScrollerX.mFinished) {
-                    if (!mScrollerX.update()) {
-                        if (!mScrollerX.continueWhenFinished()) {
-                            mScrollerX.finish();
-                        }
-                    }
-                }
+                float timePassedSeconds = timePassed / 1000.0f;
+                float distance = (mVelocity * timePassedSeconds)
+                        - (mDeceleration * timePassedSeconds * timePassedSeconds / 2.0f);
+                
+                mCurrX = mStartX + Math.round(distance * mCoeffX);
+                // Pin to mMinX <= mCurrX <= mMaxX
+                mCurrX = Math.min(mCurrX, mMaxX);
+                mCurrX = Math.max(mCurrX, mMinX);
+                
+                mCurrY = mStartY + Math.round(distance * mCoeffY);
+                // Pin to mMinY <= mCurrY <= mMaxY
+                mCurrY = Math.min(mCurrY, mMaxY);
+                mCurrY = Math.max(mCurrY, mMinY);
 
-                if (!mScrollerY.mFinished) {
-                    if (!mScrollerY.update()) {
-                        if (!mScrollerY.continueWhenFinished()) {
-                            mScrollerY.finish();
-                        }
-                    }
+                if (mCurrX == mFinalX && mCurrY == mFinalY) {
+                    mFinished = true;
                 }
-
+                
                 break;
+            }
         }
-
+        else {
+            mCurrX = mFinalX;
+            mCurrY = mFinalY;
+            mFinished = true;
+        }
         return true;
     }
-
+    
     /**
      * Start scrolling by providing a starting point and the distance to travel.
      * The scroll will use the default value of 250 milliseconds for the
@@ -254,39 +270,83 @@
      */
     public void startScroll(int startX, int startY, int dx, int dy, int duration) {
         mMode = SCROLL_MODE;
-        mScrollerX.startScroll(startX, dx, duration);
-        mScrollerY.startScroll(startY, dy, duration);
+        mFinished = false;
+        mDuration = duration;
+        mStartTime = AnimationUtils.currentAnimationTimeMillis();
+        mStartX = startX;
+        mStartY = startY;
+        mFinalX = startX + dx;
+        mFinalY = startY + dy;
+        mDeltaX = dx;
+        mDeltaY = dy;
+        mDurationReciprocal = 1.0f / (float) mDuration;
+        // This controls the viscous fluid effect (how much of it)
+        mViscousFluidScale = 8.0f;
+        // must be set to 1.0 (used in viscousFluid())
+        mViscousFluidNormalize = 1.0f;
+        mViscousFluidNormalize = 1.0f / viscousFluid(1.0f);
     }
 
     /**
-     * Start scrolling based on a fling gesture. The distance traveled will
-     * depend on the initial velocity of the fling. Velocity is slowed down by a
-     * constant deceleration until it reaches 0 or the limits are reached.
+     * Start scrolling based on a fling gesture. The distance travelled will
+     * depend on the initial velocity of the fling.
      * 
      * @param startX Starting point of the scroll (X)
      * @param startY Starting point of the scroll (Y)
      * @param velocityX Initial velocity of the fling (X) measured in pixels per
-     *            second.
+     *        second.
      * @param velocityY Initial velocity of the fling (Y) measured in pixels per
-     *            second.
+     *        second
      * @param minX Minimum X value. The scroller will not scroll past this
-     *            point.
+     *        point.
      * @param maxX Maximum X value. The scroller will not scroll past this
-     *            point.
+     *        point.
      * @param minY Minimum Y value. The scroller will not scroll past this
-     *            point.
+     *        point.
      * @param maxY Maximum Y value. The scroller will not scroll past this
-     *            point.
+     *        point.
      */
     public void fling(int startX, int startY, int velocityX, int velocityY,
             int minX, int maxX, int minY, int maxY) {
         mMode = FLING_MODE;
-        mScrollerX.fling(startX, velocityX, minX, maxX);
-        mScrollerY.fling(startY, velocityY, minY, maxY);
-    }
+        mFinished = false;
 
-    static float viscousFluid(float x) {
-        x *= VISCOUS_FLUID_SCALE;
+        float velocity = (float)Math.hypot(velocityX, velocityY);
+     
+        mVelocity = velocity;
+        mDuration = (int) (1000 * velocity / mDeceleration); // Duration is in
+                                                            // milliseconds
+        mStartTime = AnimationUtils.currentAnimationTimeMillis();
+        mStartX = startX;
+        mStartY = startY;
+
+        mCoeffX = velocity == 0 ? 1.0f : velocityX / velocity; 
+        mCoeffY = velocity == 0 ? 1.0f : velocityY / velocity;
+
+        int totalDistance = (int) ((velocity * velocity) / (2 * mDeceleration));
+        
+        mMinX = minX;
+        mMaxX = maxX;
+        mMinY = minY;
+        mMaxY = maxY;
+        
+        
+        mFinalX = startX + Math.round(totalDistance * mCoeffX);
+        // Pin to mMinX <= mFinalX <= mMaxX
+        mFinalX = Math.min(mFinalX, mMaxX);
+        mFinalX = Math.max(mFinalX, mMinX);
+        
+        mFinalY = startY + Math.round(totalDistance * mCoeffY);
+        // Pin to mMinY <= mFinalY <= mMaxY
+        mFinalY = Math.min(mFinalY, mMaxY);
+        mFinalY = Math.max(mFinalY, mMinY);
+    }
+    
+    
+    
+    private float viscousFluid(float x)
+    {
+        x *= mViscousFluidScale;
         if (x < 1.0f) {
             x -= (1.0f - (float)Math.exp(-x));
         } else {
@@ -294,237 +354,70 @@
             x = 1.0f - (float)Math.exp(1.0f - x);
             x = start + x * (1.0f - start);
         }
-        x *= VISCOUS_FLUID_NORMALIZE;
+        x *= mViscousFluidNormalize;
         return x;
     }
-
+    
     /**
      * Stops the animation. Contrary to {@link #forceFinished(boolean)},
      * aborting the animating cause the scroller to move to the final x and y
      * position
-     * 
+     *
      * @see #forceFinished(boolean)
      */
     public void abortAnimation() {
-        mScrollerX.finish();
-        mScrollerY.finish();
+        mCurrX = mFinalX;
+        mCurrY = mFinalY;
+        mFinished = true;
     }
-
+    
     /**
      * Extend the scroll animation. This allows a running animation to scroll
      * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}.
-     * 
+     *
      * @param extend Additional time to scroll in milliseconds.
      * @see #setFinalX(int)
      * @see #setFinalY(int)
      */
     public void extendDuration(int extend) {
-        mScrollerX.extendDuration(extend);
-        mScrollerY.extendDuration(extend);
+        int passed = timePassed();
+        mDuration = passed + extend;
+        mDurationReciprocal = 1.0f / (float)mDuration;
+        mFinished = false;
     }
 
     /**
      * Returns the time elapsed since the beginning of the scrolling.
-     * 
+     *
      * @return The elapsed time in milliseconds.
      */
     public int timePassed() {
-        final long time = AnimationUtils.currentAnimationTimeMillis();
-        final long startTime = Math.min(mScrollerX.mStartTime, mScrollerY.mStartTime);
-        return (int) (time - startTime);
+        return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
     }
 
     /**
      * Sets the final position (X) for this scroller.
-     * 
+     *
      * @param newX The new X offset as an absolute distance from the origin.
      * @see #extendDuration(int)
      * @see #setFinalY(int)
      */
     public void setFinalX(int newX) {
-        mScrollerX.setFinalPosition(newX);
+        mFinalX = newX;
+        mDeltaX = mFinalX - mStartX;
+        mFinished = false;
     }
 
     /**
      * Sets the final position (Y) for this scroller.
-     * 
+     *
      * @param newY The new Y offset as an absolute distance from the origin.
      * @see #extendDuration(int)
      * @see #setFinalX(int)
      */
     public void setFinalY(int newY) {
-        mScrollerY.setFinalPosition(newY);
-    }
-
-    static class MagneticScroller {
-        // Initial position
-        int mStart;
-
-        // Current position
-        int mCurrentPosition;
-
-        // Final position
-        int mFinal;
-
-        // Initial velocity
-        int mVelocity;
-
-        // Current velocity
-        float mCurrVelocity;
-
-        // Constant current deceleration
-        float mDeceleration;
-
-        // Animation starting time, in system milliseconds
-        long mStartTime;
-
-        // Animation duration, in milliseconds
-        int mDuration;
-
-        // Whether the animation is currently in progress
-        boolean mFinished;
-
-        // Constant gravity value, used to scale deceleration
-        static float GRAVITY;
-
-        static void initializeFromContext(Context context) {
-            final float ppi = context.getResources().getDisplayMetrics().density * 160.0f;
-            GRAVITY = SensorManager.GRAVITY_EARTH // g (m/s^2)
-                    * 39.37f // inch/meter
-                    * ppi // pixels per inch
-                    * ViewConfiguration.getScrollFriction();
-        }
-
-        MagneticScroller() {
-            mFinished = true;
-        }
-
-        void updateScroll(float q) {
-            mCurrentPosition = mStart + Math.round(q * (mFinal - mStart));
-        }
-
-        /*
-         * Update the current position and velocity for current time. Returns
-         * true if update has been done and false if animation duration has been
-         * reached.
-         */
-        boolean update() {
-            final long time = AnimationUtils.currentAnimationTimeMillis();
-            final long duration = time - mStartTime;
-
-            if (duration > mDuration) {
-                return false;
-            }
-
-            final float t = duration / 1000.0f;
-            mCurrVelocity = mVelocity + mDeceleration * t;
-            final float distance = mVelocity * t + mDeceleration * t * t / 2.0f;
-            mCurrentPosition = mStart + (int) distance;
-
-            return true;
-        }
-
-        /*
-         * Get a signed deceleration that will reduce the velocity.
-         */
-        static float getDeceleration(int velocity) {
-            return velocity > 0 ? -GRAVITY : GRAVITY;
-        }
-
-        /*
-         * Returns the time (in milliseconds) it will take to go from start to end.
-         */
-        static int computeDuration(int start, int end, float initialVelocity, float deceleration) {
-            final int distance = start - end;
-            final float discriminant = initialVelocity * initialVelocity - 2.0f * deceleration
-                    * distance;
-            if (discriminant >= 0.0f) {
-                float delta = (float) Math.sqrt(discriminant);
-                if (deceleration < 0.0f) {
-                    delta = -delta;
-                }
-                return (int) (1000.0f * (-initialVelocity - delta) / deceleration);
-            }
-
-            // End position can not be reached
-            return 0;
-        }
-
-        void startScroll(int start, int distance, int duration) {
-            mFinished = false;
-
-            mStart = start;
-            mFinal = start + distance;
-
-            mStartTime = AnimationUtils.currentAnimationTimeMillis();
-            mDuration = duration;
-
-            // Unused
-            mDeceleration = 0.0f;
-            mVelocity = 0;
-        }
-
-        void fling(int start, int velocity, int min, int max) {
-            mFinished = false;
-
-            mStart = start;
-            mStartTime = AnimationUtils.currentAnimationTimeMillis();
-
-            mVelocity = velocity;
-
-            mDeceleration = getDeceleration(velocity);
-
-            // A start from an invalid position immediately brings back to a valid position
-            if (mStart < min) {
-                mDuration = 0;
-                mFinal = min;
-                return;
-            }
-
-            if (mStart > max) {
-                mDuration = 0;
-                mFinal = max;
-                return;
-            }
-
-            // Duration are expressed in milliseconds
-            mDuration = (int) (-1000.0f * velocity / mDeceleration);
-
-            mFinal = start - Math.round((velocity * velocity) / (2.0f * mDeceleration));
-
-            // Clamp to a valid final position
-            if (mFinal < min) {
-                mFinal = min;
-                mDuration = computeDuration(mStart, min, mVelocity, mDeceleration);
-            }
-
-            if (mFinal > max) {
-                mFinal = max;
-                mDuration = computeDuration(mStart, max, mVelocity, mDeceleration);
-            }
-        }
-
-        void finish() {
-            mCurrentPosition = mFinal;
-            // Not reset since WebView relies on this value for fast fling.
-            // mCurrVelocity = 0.0f;
-            mFinished = true;
-        }
-
-        boolean continueWhenFinished() {
-            return false;
-        }
-
-        void setFinalPosition(int position) {
-            mFinal = position;
-            mFinished = false;
-        }
-
-        void extendDuration(int extend) {
-            final long time = AnimationUtils.currentAnimationTimeMillis();
-            final int elapsedTime = (int) (time - mStartTime);
-            mDuration = elapsedTime + extend;
-            mFinished = false;
-        }
+        mFinalY = newY;
+        mDeltaY = mFinalY - mStartY;
+        mFinished = false;
     }
 }
diff --git a/core/res/res/layout/alert_dialog.xml b/core/res/res/layout/alert_dialog.xml
index 25a41f8..7ae68f9 100644
--- a/core/res/res/layout/alert_dialog.xml
+++ b/core/res/res/layout/alert_dialog.xml
@@ -80,8 +80,7 @@
             android:paddingTop="2dip"
             android:paddingBottom="12dip"
             android:paddingLeft="14dip"
-            android:paddingRight="10dip"
-            android:overscrollMode="ifContentScrolls">
+            android:paddingRight="10dip">
             <TextView android:id="@+id/message"
                 style="?android:attr/textAppearanceMedium"
                 android:layout_width="match_parent"
diff --git a/core/res/res/layout/preference_dialog_edittext.xml b/core/res/res/layout/preference_dialog_edittext.xml
index b41e774..5be5773 100644
--- a/core/res/res/layout/preference_dialog_edittext.xml
+++ b/core/res/res/layout/preference_dialog_edittext.xml
@@ -17,8 +17,7 @@
 <!-- Layout used as the dialog's content View for EditTextPreference. -->
 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:overscrollMode="ifContentScrolls">
+    android:layout_height="match_parent">
 
     <LinearLayout
         android:id="@+android:id/edittext_container"
diff --git a/core/res/res/layout/select_dialog.xml b/core/res/res/layout/select_dialog.xml
index 6e4e5e1..c665f7a 100644
--- a/core/res/res/layout/select_dialog.xml
+++ b/core/res/res/layout/select_dialog.xml
@@ -31,5 +31,4 @@
     android:layout_marginTop="5px"
     android:cacheColorHint="@null"
     android:divider="@android:drawable/divider_horizontal_bright"
-    android:scrollbars="vertical"
-    android:overscrollMode="ifContentScrolls" />
+    android:scrollbars="vertical" />
diff --git a/core/res/res/layout/status_bar_expanded.xml b/core/res/res/layout/status_bar_expanded.xml
index d443247..30138a7 100644
--- a/core/res/res/layout/status_bar_expanded.xml
+++ b/core/res/res/layout/status_bar_expanded.xml
@@ -86,7 +86,6 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:fadingEdge="none"
-            android:overscrollMode="ifContentScrolls"
             >
             <com.android.server.status.NotificationLinearLayout
                 android:id="@+id/notificationLinearLayout"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f92dd9b..24808ec 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1307,19 +1307,6 @@
              <code>public void sayHello(View v)</code> method of your context
              (typically, your Activity). -->
         <attr name="onClick" format="string" />
-
-        <!-- Defines overscrolling behavior. This property is used only if the
-             View is scrollable. Overscrolling is the ability for the user to
-             scroll a View beyond its content boundaries into empty space. -->
-        <attr name="overscrollMode">
-            <!-- Always allow the user to overscroll the content. -->
-            <enum name="always" value="0" />
-            <!-- Only allow the user to overscroll content if the content is large
-                 enough to meaningfully scroll. -->
-            <enum name="ifContentScrolls" value="1" />
-            <!-- Never overscroll. -->
-            <enum name="never" value="2" />
-        </attr>
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -1747,10 +1734,6 @@
         <!-- When set to false, the ListView will not draw the divider before each footer view.
              The default value is true. -->
         <attr name="footerDividersEnabled" format="boolean" />
-        <!-- Drawable to draw above list content. -->
-        <attr name="overscrollHeader" format="reference|color" />
-        <!-- Drawable to draw below list content. -->
-        <attr name="overscrollFooter" format="reference|color" />
     </declare-styleable>
     <declare-styleable name="MenuView">
         <!-- Default appearance of menu item text. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 940cbf7..98c3a0a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1230,13 +1230,10 @@
   <public type="attr" name="installLocation" id="0x010102b7" />
   <public type="attr" name="vmSafeMode" id="0x010102b8" />
   <public type="attr" name="webTextViewStyle" id="0x010102b9" />
-  <public type="attr" name="overscrollMode" id="0x010102ba" />
-  <public type="attr" name="restoreAnyVersion" id="0x010102bb" />
-  <public type="attr" name="tabStripLeft" id="0x010102bc" />
-  <public type="attr" name="tabStripRight" id="0x010102bd" />
-  <public type="attr" name="tabStripEnabled" id="0x010102be" />
-  <public type="attr" name="overscrollHeader" id="0x010102bf" />
-  <public type="attr" name="overscrollFooter" id="0x010102c0" />
+  <public type="attr" name="restoreAnyVersion" id="0x010102ba" />
+  <public type="attr" name="tabStripLeft" id="0x010102bb" />
+  <public type="attr" name="tabStripRight" id="0x010102bc" />
+  <public type="attr" name="tabStripEnabled" id="0x010102bd" />
 
   <public type="id" name="custom" id="0x0102002b" />