Merge "Fix FastScroller regression for non-UI threads"
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 2d7637c..e7227e3 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -223,6 +223,11 @@
     public static final int CHOICE_MODE_MULTIPLE_MODAL = 3;
 
     /**
+     * The thread that created this view.
+     */
+    private final Thread mOwnerThread;
+
+    /**
      * Controls if/how the user may choose/check items in the list
      */
     int mChoiceMode = CHOICE_MODE_NONE;
@@ -438,6 +443,11 @@
     boolean mFastScrollEnabled;
 
     /**
+     * Whether or not to always show the fast scroll feature on this list
+     */
+    boolean mFastScrollAlwaysVisible;
+
+    /**
      * Optional callback to notify client when scroll position has changed
      */
     private OnScrollListener mOnScrollListener;
@@ -756,6 +766,8 @@
         super(context);
         initAbsListView();
 
+        mOwnerThread = Thread.currentThread();
+
         setVerticalScrollBarEnabled(true);
         TypedArray a = context.obtainStyledAttributes(R.styleable.View);
         initializeScrollbars(a);
@@ -770,6 +782,8 @@
         super(context, attrs, defStyle);
         initAbsListView();
 
+        mOwnerThread = Thread.currentThread();
+
         TypedArray a = context.obtainStyledAttributes(attrs,
                 com.android.internal.R.styleable.AbsListView, defStyle, 0);
 
@@ -1205,15 +1219,28 @@
      * @see #isFastScrollEnabled()
      * @param enabled whether or not to enable fast scrolling
      */
-    public void setFastScrollEnabled(boolean enabled) {
-        mFastScrollEnabled = enabled;
+    public void setFastScrollEnabled(final boolean enabled) {
+        if (mFastScrollEnabled != enabled) {
+            mFastScrollEnabled = enabled;
 
-        if (enabled && mFastScroller == null) {
-            mFastScroller = new FastScroller(getContext(), this);
+            if (isOwnerThread()) {
+                setFastScrollerEnabledUiThread(enabled);
+            } else {
+                post(new Runnable() {
+                    @Override
+                    public void run() {
+                        setFastScrollerEnabledUiThread(enabled);
+                    }
+                });
+            }
         }
+    }
 
+    private void setFastScrollerEnabledUiThread(boolean enabled) {
         if (mFastScroller != null) {
             mFastScroller.setEnabled(enabled);
+        } else if (enabled) {
+            mFastScroller = new FastScroller(this);
         }
     }
 
@@ -1228,17 +1255,38 @@
      * @see #setScrollBarStyle(int)
      * @see #setFastScrollEnabled(boolean)
      */
-    public void setFastScrollAlwaysVisible(boolean alwaysShow) {
-        if (alwaysShow && !mFastScrollEnabled) {
-            setFastScrollEnabled(true);
-        }
+    public void setFastScrollAlwaysVisible(final boolean alwaysShow) {
+        if (mFastScrollAlwaysVisible != alwaysShow) {
+            if (alwaysShow && !mFastScrollEnabled) {
+                setFastScrollEnabled(true);
+            }
 
+            mFastScrollAlwaysVisible = alwaysShow;
+
+            if (isOwnerThread()) {
+                setFastScrollerAlwaysVisibleUiThread(alwaysShow);
+            } else {
+                post(new Runnable() {
+                    @Override
+                    public void run() {
+                        setFastScrollerAlwaysVisibleUiThread(alwaysShow);
+                    }
+                });
+            }
+        }
+    }
+
+    private void setFastScrollerAlwaysVisibleUiThread(boolean alwaysShow) {
         if (mFastScroller != null) {
             mFastScroller.setAlwaysShow(alwaysShow);
         }
+    }
 
-        computeOpaqueFlags();
-        recomputePadding();
+    /**
+     * @return whether the current thread is the one that created the view
+     */
+    private boolean isOwnerThread() {
+        return mOwnerThread == Thread.currentThread();
     }
 
     /**
@@ -1249,12 +1297,12 @@
      * @see #setFastScrollAlwaysVisible(boolean)
      */
     public boolean isFastScrollAlwaysVisible() {
-        return mFastScrollEnabled && mFastScroller.isAlwaysShowEnabled();
+        return mFastScrollEnabled && mFastScrollAlwaysVisible;
     }
 
     @Override
     public int getVerticalScrollbarWidth() {
-        if (isFastScrollAlwaysVisible()) {
+        if (isFastScrollAlwaysVisible() && mFastScroller != null) {
             return Math.max(super.getVerticalScrollbarWidth(), mFastScroller.getWidth());
         }
         return super.getVerticalScrollbarWidth();
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index d08e38e..b3b00b1 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -231,10 +231,11 @@
         }
     };
 
-    public FastScroller(Context context, AbsListView listView) {
+    public FastScroller(AbsListView listView) {
         mList = listView;
         mOverlay = listView.getOverlay();
 
+        final Context context = listView.getContext();
         mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
 
         final Resources res = context.getResources();