Merge "Revert "Use ObjectAnimator for fading scrollbars, set initial duration to 1500""
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 5ee3c16..6d3c07a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,9 +16,7 @@
 
 package android.view;
 
-import android.animation.Animator;
 import android.animation.AnimatorInflater;
-import android.animation.ObjectAnimator;
 import android.animation.StateListAnimator;
 import android.annotation.DrawableRes;
 import android.annotation.IdRes;
@@ -34,10 +32,13 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Insets;
+import android.graphics.Interpolator;
 import android.graphics.LinearGradient;
 import android.graphics.Matrix;
 import android.graphics.Outline;
 import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.PorterDuff;
@@ -4325,7 +4326,9 @@
      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
      */
     protected void initializeFadingEdgeInternal(TypedArray a) {
-        getScrollCache().fadingEdgeLength = a.getDimensionPixelSize(
+        initScrollCache();
+
+        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
                 R.styleable.View_fadingEdgeLength,
                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
     }
@@ -4359,7 +4362,8 @@
      *        content in this view is visible.
      */
     public void setFadingEdgeLength(int length) {
-        getScrollCache().fadingEdgeLength = length;
+        initScrollCache();
+        mScrollCache.fadingEdgeLength = length;
     }
 
     /**
@@ -4463,7 +4467,10 @@
      * @hide
      */
     protected void initializeScrollbarsInternal(TypedArray a) {
-        final ScrollabilityCache scrollabilityCache = getScrollCache();
+        initScrollCache();
+
+        final ScrollabilityCache scrollabilityCache = mScrollCache;
+
         if (scrollabilityCache.scrollBar == null) {
             scrollabilityCache.scrollBar = new ScrollBarDrawable();
             scrollabilityCache.scrollBar.setCallback(this);
@@ -4471,16 +4478,23 @@
         }
 
         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
-        scrollabilityCache.setFadingEnabled(fadeScrollbars);
+
+        if (!fadeScrollbars) {
+            scrollabilityCache.state = ScrollabilityCache.ON;
+        }
+        scrollabilityCache.fadeScrollBars = fadeScrollbars;
+
 
         scrollabilityCache.scrollBarFadeDuration = a.getInt(
-                R.styleable.View_scrollbarFadeDuration,
-                ViewConfiguration.getScrollBarFadeDuration());
+                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
+                        .getScrollBarFadeDuration());
         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
                 ViewConfiguration.getScrollDefaultDelay());
+
+
         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
-                R.styleable.View_scrollbarSize,
+                com.android.internal.R.styleable.View_scrollbarSize,
                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
 
         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
@@ -4525,12 +4539,18 @@
     }
 
     /**
-     * Returns the scrollability cache, initializing a new cache if necessary.
+     * <p>
+     * Initalizes the scrollability cache if necessary.
+     * </p>
      */
-    private ScrollabilityCache getScrollCache() {
+    private void initScrollCache() {
         if (mScrollCache == null) {
-            mScrollCache = new ScrollabilityCache(this);
+            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
         }
+    }
+
+    private ScrollabilityCache getScrollCache() {
+        initScrollCache();
         return mScrollCache;
     }
 
@@ -11559,30 +11579,31 @@
      * @see #setVerticalScrollBarEnabled(boolean)
      */
     protected boolean awakenScrollBars() {
-        return mScrollCache != null
-                && awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
+        return mScrollCache != null &&
+                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
     }
 
     /**
      * Trigger the scrollbars to draw.
-     * <p>
      * This method differs from awakenScrollBars() only in its default duration.
      * initialAwakenScrollBars() will show the scroll bars for longer than
      * usual to give the user more of a chance to notice them.
      *
      * @return true if the animation is played, false otherwise.
-     * @see #awakenScrollBars()
      */
     private boolean initialAwakenScrollBars() {
-        return mScrollCache != null
-                && awakenScrollBars(mScrollCache.scrollBarDelayBeforeInitialFade, true);
+        return mScrollCache != null &&
+                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
     }
 
     /**
+     * <p>
      * Trigger the scrollbars to draw. When invoked this method starts an
      * animation to fade the scrollbars out after a fixed delay. If a subclass
      * provides animated scrolling, the start delay should equal the duration of
      * the scrolling animation.
+     * </p>
+     *
      * <p>
      * The animation starts only if at least one of the scrollbars is enabled,
      * as specified by {@link #isHorizontalScrollBarEnabled()} and
@@ -11590,14 +11611,18 @@
      * this method returns true, and false otherwise. If the animation is
      * started, this method calls {@link #invalidate()}; in that case the caller
      * should not call {@link #invalidate()}.
+     * </p>
+     *
      * <p>
      * This method should be invoked every time a subclass directly updates the
      * scroll parameters.
+     * </p>
      *
-     * @param fadeOutDelay the delay in milliseconds before the fade out
-     *                     animation should start, or 0 to start the animation
-     *                     immediately
+     * @param startDelay the delay, in milliseconds, after which the animation
+     *        should start; when the delay is 0, the animation starts
+     *        immediately
      * @return true if the animation is played, false otherwise
+     *
      * @see #scrollBy(int, int)
      * @see #scrollTo(int, int)
      * @see #isHorizontalScrollBarEnabled()
@@ -11605,15 +11630,18 @@
      * @see #setHorizontalScrollBarEnabled(boolean)
      * @see #setVerticalScrollBarEnabled(boolean)
      */
-    protected boolean awakenScrollBars(int fadeOutDelay) {
-        return awakenScrollBars(fadeOutDelay, true);
+    protected boolean awakenScrollBars(int startDelay) {
+        return awakenScrollBars(startDelay, true);
     }
 
     /**
+     * <p>
      * Trigger the scrollbars to draw. When invoked this method starts an
      * animation to fade the scrollbars out after a fixed delay. If a subclass
      * provides animated scrolling, the start delay should equal the duration of
      * the scrolling animation.
+     * </p>
+     *
      * <p>
      * The animation starts only if at least one of the scrollbars is enabled,
      * as specified by {@link #isHorizontalScrollBarEnabled()} and
@@ -11622,18 +11650,21 @@
      * started, this method calls {@link #invalidate()} if the invalidate parameter
      * is set to true; in that case the caller
      * should not call {@link #invalidate()}.
+     * </p>
+     *
      * <p>
      * This method should be invoked every time a subclass directly updates the
      * scroll parameters.
-     * <p>
-     * <strong>Note:</strong> If the view has not explicitly requested
-     * scrollbars prior calling this method, this is a no-op.
+     * </p>
      *
-     * @param fadeOutDelay the delay in milliseconds before the fade out
-     *                     animation should start, or 0 to start the animation
-     *                     immediately
-     * @param invalidate whether this method should call invalidate
+     * @param startDelay the delay, in milliseconds, after which the animation
+     *        should start; when the delay is 0, the animation starts
+     *        immediately
+     *
+     * @param invalidate Whether this method should call invalidate
+     *
      * @return true if the animation is played, false otherwise
+     *
      * @see #scrollBy(int, int)
      * @see #scrollTo(int, int)
      * @see #isHorizontalScrollBarEnabled()
@@ -11641,15 +11672,50 @@
      * @see #setHorizontalScrollBarEnabled(boolean)
      * @see #setVerticalScrollBarEnabled(boolean)
      */
-    protected boolean awakenScrollBars(int fadeOutDelay, boolean invalidate) {
-        if (mScrollCache == null
-                || (!isHorizontalScrollBarEnabled() && !isVerticalScrollBarEnabled())) {
-            // We're not supposed to show scroll bars right now.
+    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
+        final ScrollabilityCache scrollCache = mScrollCache;
+
+        if (scrollCache == null || !scrollCache.fadeScrollBars) {
             return false;
         }
 
-        mScrollCache.awakenScrollBars(fadeOutDelay);
-        return true;
+        if (scrollCache.scrollBar == null) {
+            scrollCache.scrollBar = new ScrollBarDrawable();
+            scrollCache.scrollBar.setCallback(this);
+            scrollCache.scrollBar.setState(getDrawableState());
+        }
+
+        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
+
+            if (invalidate) {
+                // Invalidate to show the scrollbars
+                postInvalidateOnAnimation();
+            }
+
+            if (scrollCache.state == ScrollabilityCache.OFF) {
+                // FIXME: this is copied from WindowManagerService.
+                // We should get this value from the system when it
+                // is possible to do so.
+                final int KEY_REPEAT_FIRST_DELAY = 750;
+                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
+            }
+
+            // Tell mScrollCache when we should start fading. This may
+            // extend the fade start time if one was already scheduled
+            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
+            scrollCache.fadeStartTime = fadeStartTime;
+            scrollCache.state = ScrollabilityCache.ON;
+
+            // Schedule our fader to run, unscheduling any old ones first
+            if (mAttachInfo != null) {
+                mAttachInfo.mHandler.removeCallbacks(scrollCache);
+                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
+            }
+
+            return true;
+        }
+
+        return false;
     }
 
     /**
@@ -12330,7 +12396,7 @@
     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
             if (horizontalFadingEdgeEnabled) {
-                getScrollCache();
+                initScrollCache();
             }
 
             mViewFlags ^= FADING_EDGE_HORIZONTAL;
@@ -12367,7 +12433,7 @@
     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
             if (verticalFadingEdgeEnabled) {
-                getScrollCache();
+                initScrollCache();
             }
 
             mViewFlags ^= FADING_EDGE_VERTICAL;
@@ -12507,7 +12573,14 @@
      * @attr ref android.R.styleable#View_fadeScrollbars
      */
     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
-        getScrollCache().setFadingEnabled(fadeScrollbars);
+        initScrollCache();
+        final ScrollabilityCache scrollabilityCache = mScrollCache;
+        scrollabilityCache.fadeScrollBars = fadeScrollbars;
+        if (fadeScrollbars) {
+            scrollabilityCache.state = ScrollabilityCache.OFF;
+        } else {
+            scrollabilityCache.state = ScrollabilityCache.ON;
+        }
     }
 
     /**
@@ -12519,7 +12592,7 @@
      * @attr ref android.R.styleable#View_fadeScrollbars
      */
     public boolean isScrollbarFadingEnabled() {
-        return mScrollCache != null && mScrollCache.isFadingEnabled();
+        return mScrollCache != null && mScrollCache.fadeScrollBars;
     }
 
     /**
@@ -12801,85 +12874,129 @@
     }
 
     /**
-     * Request the drawing of the horizontal and the vertical scrollbar. The
-     * scrollbars are painted only if they have been awakened first.
+     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
+     * scrollbars are painted only if they have been awakened first.</p>
      *
      * @param canvas the canvas on which to draw the scrollbars
+     *
      * @see #awakenScrollBars(int)
      */
     protected final void onDrawScrollBars(Canvas canvas) {
+        // scrollbars are drawn only when the animation is running
         final ScrollabilityCache cache = mScrollCache;
-        if (cache == null) {
-            // This view does not currently support scrolling.
-            return;
-        }
+        if (cache != null) {
 
-        final int viewFlags = mViewFlags;
-        final boolean drawHorizontalScrollBar =
-            (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
-        final boolean drawVerticalScrollBar =
-            (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
-            && !isVerticalScrollBarHidden();
-        if (!drawVerticalScrollBar && !drawHorizontalScrollBar) {
-            // This view does not currently draw scrollbars.
-            return;
-        }
+            int state = cache.state;
 
-        final ScrollBarDrawable scrollBar = cache.scrollBar;
-        final int width = mRight - mLeft;
-        final int height = mBottom - mTop;
-        final int scrollX = mScrollX;
-        final int scrollY = mScrollY;
-        final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
-
-        if (drawHorizontalScrollBar) {
-            int size = scrollBar.getSize(false);
-            if (size <= 0) {
-                size = cache.scrollBarSize;
+            if (state == ScrollabilityCache.OFF) {
+                return;
             }
 
-            scrollBar.setParameters(computeHorizontalScrollRange(), computeHorizontalScrollOffset(),
-                    computeHorizontalScrollExtent(), false);
-            final int verticalScrollBarGap = drawVerticalScrollBar ?
-                    getVerticalScrollbarWidth() : 0;
+            boolean invalidate = false;
 
-            final int left = scrollX + (mPaddingLeft & inside);
-            final int right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
-            final int top = scrollY + height - size - (mUserPaddingBottom & inside);
-            final int bottom = top + size;
+            if (state == ScrollabilityCache.FADING) {
+                // We're fading -- get our fade interpolation
+                if (cache.interpolatorValues == null) {
+                    cache.interpolatorValues = new float[1];
+                }
 
-            onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
-        }
+                float[] values = cache.interpolatorValues;
 
-        if (drawVerticalScrollBar) {
-            int size = scrollBar.getSize(true);
-            if (size <= 0) {
-                size = cache.scrollBarSize;
-            }
+                // Stops the animation if we're done
+                if (cache.scrollBarInterpolator.timeToValues(values) ==
+                        Interpolator.Result.FREEZE_END) {
+                    cache.state = ScrollabilityCache.OFF;
+                } else {
+                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
+                }
 
-            scrollBar.setParameters(computeVerticalScrollRange(), computeVerticalScrollOffset(),
-                    computeVerticalScrollExtent(), true);
-
-            final int verticalScrollbarPosition;
-            if (mVerticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
-                verticalScrollbarPosition = isLayoutRtl() ?
-                        SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
+                // This will make the scroll bars inval themselves after
+                // drawing. We only want this when we're fading so that
+                // we prevent excessive redraws
+                invalidate = true;
             } else {
-                verticalScrollbarPosition = mVerticalScrollbarPosition;
+                // We're just on -- but we may have been fading before so
+                // reset alpha
+                cache.scrollBar.mutate().setAlpha(255);
             }
 
-            final int left;
-            if (verticalScrollbarPosition == SCROLLBAR_POSITION_LEFT) {
-                left = scrollX + (mUserPaddingLeft & inside);
-            } else {
-                left = scrollX + width - size - (mUserPaddingRight & inside);
+
+            final int viewFlags = mViewFlags;
+
+            final boolean drawHorizontalScrollBar =
+                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
+            final boolean drawVerticalScrollBar =
+                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
+                && !isVerticalScrollBarHidden();
+
+            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
+                final int width = mRight - mLeft;
+                final int height = mBottom - mTop;
+
+                final ScrollBarDrawable scrollBar = cache.scrollBar;
+
+                final int scrollX = mScrollX;
+                final int scrollY = mScrollY;
+                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
+
+                int left;
+                int top;
+                int right;
+                int bottom;
+
+                if (drawHorizontalScrollBar) {
+                    int size = scrollBar.getSize(false);
+                    if (size <= 0) {
+                        size = cache.scrollBarSize;
+                    }
+
+                    scrollBar.setParameters(computeHorizontalScrollRange(),
+                                            computeHorizontalScrollOffset(),
+                                            computeHorizontalScrollExtent(), false);
+                    final int verticalScrollBarGap = drawVerticalScrollBar ?
+                            getVerticalScrollbarWidth() : 0;
+                    top = scrollY + height - size - (mUserPaddingBottom & inside);
+                    left = scrollX + (mPaddingLeft & inside);
+                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
+                    bottom = top + size;
+                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
+                    if (invalidate) {
+                        invalidate(left, top, right, bottom);
+                    }
+                }
+
+                if (drawVerticalScrollBar) {
+                    int size = scrollBar.getSize(true);
+                    if (size <= 0) {
+                        size = cache.scrollBarSize;
+                    }
+
+                    scrollBar.setParameters(computeVerticalScrollRange(),
+                                            computeVerticalScrollOffset(),
+                                            computeVerticalScrollExtent(), true);
+                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
+                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
+                        verticalScrollbarPosition = isLayoutRtl() ?
+                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
+                    }
+                    switch (verticalScrollbarPosition) {
+                        default:
+                        case SCROLLBAR_POSITION_RIGHT:
+                            left = scrollX + width - size - (mUserPaddingRight & inside);
+                            break;
+                        case SCROLLBAR_POSITION_LEFT:
+                            left = scrollX + (mUserPaddingLeft & inside);
+                            break;
+                    }
+                    top = scrollY + (mPaddingTop & inside);
+                    right = left + size;
+                    bottom = scrollY + height - (mUserPaddingBottom & inside);
+                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
+                    if (invalidate) {
+                        invalidate(left, top, right, bottom);
+                    }
+                }
             }
-
-            final int top = scrollY + (mPaddingTop & inside);
-            final int right = left + size;
-            final int bottom = scrollY + height - (mUserPaddingBottom & inside);
-
-            onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
         }
     }
 
@@ -15245,7 +15362,7 @@
                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
             }
         } else {
-            scrollabilityCache.setFadingEdgeColor(solidColor);
+            scrollabilityCache.setFadeColor(solidColor);
         }
 
         // Step 3, draw the content
@@ -15255,9 +15372,9 @@
         dispatchDraw(canvas);
 
         // Step 5, draw the fade effect and restore layers
-        final Paint p = scrollabilityCache.fadingEdgePaint;
+        final Paint p = scrollabilityCache.paint;
         final Matrix matrix = scrollabilityCache.matrix;
-        final Shader fade = scrollabilityCache.fadingEdgeShader;
+        final Shader fade = scrollabilityCache.shader;
 
         if (drawTop) {
             matrix.setScale(1, fadeHeight * topFadeStrength);
@@ -20517,164 +20634,121 @@
     }
 
     /**
-     * ScrollabilityCache holds various fields used by a View when scrolling
+     * <p>ScrollabilityCache holds various fields used by a View when scrolling
      * is supported. This avoids keeping too many unused fields in most
-     * instances of View.
+     * instances of View.</p>
      */
-    private static class ScrollabilityCache {
-        public final Paint fadingEdgePaint = new Paint();
-        public final Matrix matrix = new Matrix();
-
-        /** The view that owns this cache. */
-        private final View mHost;
+    private static class ScrollabilityCache implements Runnable {
 
         /**
-         * Minimum delay in milliseconds before the fade-out animation begins.
-         * Only used if the scrollbar was previously invisible.
+         * Scrollbars are not visible
          */
-        private static final int MIN_FADE_DELAY_FROM_OFF = 750;
+        public static final int OFF = 0;
 
         /**
-         * Default delay in milliseconds before the fade-out animation begins.
+         * Scrollbars are visible
          */
+        public static final int ON = 1;
+
+        /**
+         * Scrollbars are fading away
+         */
+        public static final int FADING = 2;
+
+        public boolean fadeScrollBars;
+
+        public int fadingEdgeLength;
         public int scrollBarDefaultDelayBeforeFade;
-
-        /**
-         * Delay in milliseconds before the fade-out animation begins. Only
-         * used if the scrollbar is being shown to the user for the first time.
-         */
-        public int scrollBarDelayBeforeInitialFade;
-
-        /** Duration in milliseconds of the fade-out animation. */
         public int scrollBarFadeDuration;
 
-        public ScrollBarDrawable scrollBar;
-        public Shader fadingEdgeShader;
-        public int fadingEdgeLength;
         public int scrollBarSize;
+        public ScrollBarDrawable scrollBar;
+        public float[] interpolatorValues;
+        public View host;
+
+        public final Paint paint;
+        public final Matrix matrix;
+        public Shader shader;
+
+        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
+
+        private static final float[] OPAQUE = { 255 };
+        private static final float[] TRANSPARENT = { 0.0f };
 
         /**
-         * Whether scrollbar fading is enabled. If false, scrollbars are always
-         * visible.
+         * When fading should start. This time moves into the future every time
+         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
          */
-        private boolean mIsFadingEnabled;
+        public long fadeStartTime;
 
-        private Animator mFadeAnim;
-        private int mFadingEdgeLastColor;
 
-        public ScrollabilityCache(View host) {
-            mHost = host;
+        /**
+         * The current state of the scrollbars: ON, OFF, or FADING
+         */
+        public int state = OFF;
 
-            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
-            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
-            scrollBarDelayBeforeInitialFade = ViewConfiguration.getScrollDefaultInitialDelay();
+        private int mLastColor;
 
-            final ViewConfiguration configuration = ViewConfiguration.get(host.getContext());
-            scrollBarSize = configuration.getScaledScrollBarSize();
+        public ScrollabilityCache(ViewConfiguration configuration, View host) {
             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
+            scrollBarSize = configuration.getScaledScrollBarSize();
+            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
+            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
 
-            // Force the fading edge color to change.
-            mFadingEdgeLastColor = -1;
-            setFadingEdgeColor(0);
+            paint = new Paint();
+            matrix = new Matrix();
+            // use use a height of 1, and then wack the matrix each time we
+            // actually use it.
+            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
+            paint.setShader(shader);
+            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+
+            this.host = host;
         }
 
-        public void setFadingEdgeColor(int color) {
-            if (mFadingEdgeLastColor != color) {
-                mFadingEdgeLastColor = color;
+        public void setFadeColor(int color) {
+            if (color != mLastColor) {
+                mLastColor = color;
 
-                final int color0;
-                final int color1;
-                final PorterDuffXfermode xfermode;
                 if (color != 0) {
-                    color0 = color | 0xFF000000;
-                    color1 = color & 0x00FFFFFF;
-                    xfermode = null;
+                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
+                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
+                    paint.setShader(shader);
+                    // Restore the default transfer mode (src_over)
+                    paint.setXfermode(null);
                 } else {
-                    color0 = 0xFF000000;
-                    color1 = 0;
-                    xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
+                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
+                    paint.setShader(shader);
+                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
                 }
-
-                // Use a height of 1 and then whack the matrix each time we
-                // actually use it.
-                fadingEdgeShader = new LinearGradient(
-                        0, 0, 0, 1, color0, color1, Shader.TileMode.CLAMP);
-                fadingEdgePaint.setShader(fadingEdgeShader);
-                fadingEdgePaint.setXfermode(xfermode);
             }
         }
 
-        public void setFadingEnabled(boolean enabled) {
-            if (mIsFadingEnabled != enabled) {
-                mIsFadingEnabled = enabled;
+        public void run() {
+            long now = AnimationUtils.currentAnimationTimeMillis();
+            if (now >= fadeStartTime) {
 
-                setFadingAlpha(enabled ? 0 : 255);
+                // the animation fades the scrollbars out by changing
+                // the opacity (alpha) from fully opaque to fully
+                // transparent
+                int nextFrame = (int) now;
+                int framesCount = 0;
+
+                Interpolator interpolator = scrollBarInterpolator;
+
+                // Start opaque
+                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
+
+                // End transparent
+                nextFrame += scrollBarFadeDuration;
+                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
+
+                state = FADING;
+
+                // Kick off the fade animation
+                host.invalidate(true);
             }
         }
-
-        public boolean isFadingEnabled() {
-            return mIsFadingEnabled;
-        }
-
-        /**
-         * Cancels any ongoing or pending fade animations and immediately sets
-         * the scroll bar alpha value.
-         *
-         * @param alpha the scrollbar alpha value
-         */
-        public void setFadingAlpha(int alpha) {
-            if (mFadeAnim != null) {
-                mFadeAnim.cancel();
-                mFadeAnim = null;
-            }
-            mHost.removeCallbacks(mFadeOutRunnable);
-
-            scrollBar.setAlpha(alpha);
-        }
-
-        /**
-         * If fading is enabled, cancels any ongoing or pending fade animations
-         * and immediately sets the scroll bar alpha value to the maximum, then
-         * posts a delayed fade-out animation.
-         *
-         * @param fadeOutDelay the delay before the fade-out animation starts
-         * @return {@code true} if the scroll bars changed, false otherwise
-         */
-        public boolean awakenScrollBars(int fadeOutDelay) {
-            if (!mIsFadingEnabled) {
-                return false;
-            }
-
-            if (scrollBar == null) {
-                scrollBar = new ScrollBarDrawable();
-                scrollBar.setCallback(mHost);
-                scrollBar.setState(mHost.getDrawableState());
-            }
-
-            // Removes pending callbacks.
-            setFadingAlpha(255);
-
-            final int startingAlpha = scrollBar.getAlpha();
-            if (startingAlpha == 0) {
-                fadeOutDelay = Math.max(ScrollabilityCache.MIN_FADE_DELAY_FROM_OFF, fadeOutDelay);
-            }
-
-            mHost.postDelayed(mFadeOutRunnable, fadeOutDelay);
-
-            return true;
-        }
-
-        private final Runnable mFadeOutRunnable = new Runnable() {
-            @Override
-            public void run() {
-                final ObjectAnimator anim = ObjectAnimator.ofInt(
-                        scrollBar, ScrollBarDrawable.ALPHA, 0);
-                anim.setDuration(scrollBarFadeDuration);
-                anim.start();
-
-                mFadeAnim = anim;
-            }
-        };
     }
 
     /**
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index d733513..4e91ad4 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -47,12 +47,6 @@
     private static final int SCROLL_BAR_DEFAULT_DELAY = 300;
 
     /**
-     * Default delay before the scrollbars fade in milliseconds for the first
-     * time they are shown to the user.
-     */
-    private static final int SCROLL_BAR_DEFAULT_INITIAL_DELAY = 1500;
-
-    /**
      * Defines the length of the fading edges in dips
      */
     private static final int FADING_EDGE_LENGTH = 12;
@@ -401,23 +395,13 @@
     }
 
     /**
-     * @return Default delay in milliseconds before the scrollbars fade out
-     *         after they have been awoken.
+     * @return Default delay before the scrollbars fade in milliseconds
      */
     public static int getScrollDefaultDelay() {
         return SCROLL_BAR_DEFAULT_DELAY;
     }
 
     /**
-     * @return Default delay in milliseconds before the scrollbars fade out
-     *         after they are initially shown to the user.
-     * @hide Pending cleanup of ViewConfiguration values.
-     */
-    public static int getScrollDefaultInitialDelay() {
-        return SCROLL_BAR_DEFAULT_INITIAL_DELAY;
-    }
-
-    /**
      * @return the length of the fading edges in dips
      *
      * @deprecated Use {@link #getScaledFadingEdgeLength()} instead.
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 98767a7..247f94a 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -39,7 +39,6 @@
 import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
-import android.util.IntProperty;
 import android.util.StateSet;
 import android.util.TypedValue;
 import android.util.Xml;
@@ -1372,20 +1371,5 @@
             default: return defaultMode;
         }
     }
-
-    /** @hide */
-    public static final IntProperty<Drawable> ALPHA = new IntProperty<Drawable>("alpha") {
-        @Override
-        public void setValue(Drawable object, int value) {
-            object.mutate();
-            object.setAlpha(value);
-            object.invalidateSelf();
-        }
-
-        @Override
-        public Integer get(Drawable object) {
-            return object.getAlpha();
-        }
-    };
 }