Merge branch 'froyo' into froyo-release
diff --git a/res/xml/default_workspace.xml b/res/xml/default_workspace.xml
index d369377..30c542a 100644
--- a/res/xml/default_workspace.xml
+++ b/res/xml/default_workspace.xml
@@ -42,15 +42,6 @@
         launcher:spanX="4"
         launcher:spanY="1" />
 
-    <appwidget
-        launcher:packageName="com.android.vending"
-        launcher:className="com.android.vending.MarketWidgetProvider"
-        launcher:screen="2"
-        launcher:x="1"
-        launcher:y="2"
-        launcher:spanX="2"
-        launcher:spanY="2" />
-
     <!--  Right screen [3] -->
     <appwidget
         launcher:packageName="com.android.music"
@@ -61,6 +52,15 @@
         launcher:spanX="4"
         launcher:spanY="1" />
 
+    <appwidget
+        launcher:packageName="com.android.vending"
+        launcher:className="com.android.vending.MarketWidgetProvider"
+        launcher:screen="3"
+        launcher:x="1"
+        launcher:y="1"
+        launcher:spanX="2"
+        launcher:spanY="2" />
+
     <!--  Far-right screen [4] -->
 
 </favorites>
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index bc52af1..9d39c2c 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -584,7 +584,7 @@
             final View view = getChildAt(i);
             view.setDrawingCacheEnabled(enabled);
             // Update the drawing caches
-            view.buildDrawingCache(false);
+            view.buildDrawingCache(true);
         }
     }
 
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
index 04762e9..4bb7d08 100644
--- a/src/com/android/launcher2/IconCache.java
+++ b/src/com/android/launcher2/IconCache.java
@@ -100,24 +100,28 @@
     }
 
     public Bitmap getIcon(Intent intent) {
-        final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
-        ComponentName component = intent.getComponent();
+        synchronized (mCache) {
+            final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
+            ComponentName component = intent.getComponent();
 
-        if (resolveInfo == null || component == null) {
-            return mDefaultIcon;
+            if (resolveInfo == null || component == null) {
+                return mDefaultIcon;
+            }
+
+            CacheEntry entry = cacheLocked(component, resolveInfo);
+            return entry.icon;
         }
-
-        CacheEntry entry = cacheLocked(component, resolveInfo);
-        return entry.icon;
     }
 
     public Bitmap getIcon(ComponentName component, ResolveInfo resolveInfo) {
-        if (resolveInfo == null || component == null) {
-            return null;
-        }
+        synchronized (mCache) {
+            if (resolveInfo == null || component == null) {
+                return null;
+            }
 
-        CacheEntry entry = cacheLocked(component, resolveInfo);
-        return entry.icon;
+            CacheEntry entry = cacheLocked(component, resolveInfo);
+            return entry.icon;
+        }
     }
 
     private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info) {
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index d5b5859..a867200 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -73,6 +73,7 @@
     private boolean mBeforeFirstLoad = true; // only access this from main thread
     private WeakReference<Callbacks> mCallbacks;
 
+    private final Object mAllAppsListLock = new Object();
     private AllAppsList mAllAppsList;
     private IconCache mIconCache;
 
@@ -306,7 +307,7 @@
         ArrayList<ApplicationInfo> removed = null;
         ArrayList<ApplicationInfo> modified = null;
 
-        synchronized (mLock) {
+        synchronized (mAllAppsListLock) {
             if (mBeforeFirstLoad) {
                 // If we haven't even loaded yet, don't bother, since we'll just pick
                 // up the changes.
@@ -1047,7 +1048,7 @@
                 int i=0;
                 int batchSize = -1;
                 while (i < N && !mStopped) {
-                    synchronized (mLock) {
+                    synchronized (mAllAppsListLock) {
                         if (i == 0) {
                             // This needs to happen inside the same lock block as when we
                             // prepare the first batch for bindAllApplications.  Otherwise
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index dca40ce..0a658a4 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -109,7 +109,6 @@
     private boolean mAllowLongPress = true;
 
     private int mTouchSlop;
-    private int mPagingTouchSlop;
     private int mMaximumVelocity;
     
     private static final int INVALID_POINTER = -1;
@@ -119,9 +118,11 @@
     private Drawable mPreviousIndicator;
     private Drawable mNextIndicator;
     
-    // Touch scrolling history for smoothing
-    private float[] mLastX = new float[6];
-    private int mLastCount = 0;
+    private static final float NANOTIME_DIV = 1000000000.0f;
+    private static final float SMOOTHING_SPEED = 0.75f;
+    private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED));
+    private float mSmoothingTime;
+    private float mTouchX;
 
     private WorkspaceOvershootInterpolator mScrollInterpolator;
 
@@ -196,7 +197,6 @@
 
         final ViewConfiguration configuration = ViewConfiguration.get(getContext());
         mTouchSlop = configuration.getScaledTouchSlop();
-        mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
         mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
     }
 
@@ -431,9 +431,17 @@
     }
     
     @Override
+    public void scrollTo(int x, int y) {
+        super.scrollTo(x, y);
+        mTouchX = x;
+        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+    }
+    
+    @Override
     public void computeScroll() {
         if (mScroller.computeScrollOffset()) {
-            mScrollX = mScroller.getCurrX();
+            mTouchX = mScrollX = mScroller.getCurrX();
+            mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
             mScrollY = mScroller.getCurrY();
             updateWallpaperOffset();
             postInvalidate();
@@ -444,6 +452,18 @@
             Launcher.setScreen(mCurrentScreen);
             mNextScreen = INVALID_SCREEN;
             clearChildrenCache();
+        } else if (mTouchState == TOUCH_STATE_SCROLLING) {
+            final float now = System.nanoTime() / NANOTIME_DIV;
+            final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT);
+            final float dx = mTouchX - mScrollX;
+            mScrollX += dx * e;
+            mSmoothingTime = now;
+
+            // Keep generating points as long as we're more than 1px away from the target
+            if (dx > 1.f || dx < -1.f) {
+                updateWallpaperOffset();
+                postInvalidate();
+            }
         }
     }
 
@@ -656,17 +676,18 @@
                 final int yDiff = (int) Math.abs(y - mLastMotionY);
 
                 final int touchSlop = mTouchSlop;
-                boolean xPaged = xDiff > mPagingTouchSlop;
                 boolean xMoved = xDiff > touchSlop;
                 boolean yMoved = yDiff > touchSlop;
                 
                 if (xMoved || yMoved) {
                     
-                    if (xPaged) {
+                    if (xMoved) {
                         // Scroll if the user moved far enough along the X axis
                         mTouchState = TOUCH_STATE_SCROLLING;
                         mLastMotionX = x;
-                        enableChildrenCache(0, getChildCount());
+                        mTouchX = mScrollX;
+                        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+                        enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1);
                     }
                     // Either way, cancel any pending longpress
                     if (mAllowLongPress) {
@@ -755,7 +776,6 @@
             if (mVelocityTracker != null) {
                 mVelocityTracker.clear();
             }
-            resetFilter();
         }
     }
 
@@ -813,25 +833,6 @@
             layout.setChildrenDrawnWithCacheEnabled(false);
         }
     }
-    
-    private float filterX(float x) {
-        final float[] lastX = mLastX;
-        final int len = lastX.length;
-        final int lastCount = Math.min(len, mLastCount + 1);
-        
-        float sum = x;
-        for (int i = 1; i < lastCount; i++) {
-            sum += lastX[i] = lastX[i - 1];
-        }
-        lastX[0] = x;
-
-        mLastCount = lastCount;
-        return sum / lastCount;
-    }
-    
-    private void resetFilter() {
-        mLastCount = 0;
-    }
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
@@ -868,26 +869,31 @@
             // Remember where the motion event started
             mLastMotionX = ev.getX();
             mActivePointerId = ev.getPointerId(0);
+            if (mTouchState == TOUCH_STATE_SCROLLING) {
+                enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1);
+            }
             break;
         case MotionEvent.ACTION_MOVE:
             if (mTouchState == TOUCH_STATE_SCROLLING) {
                 // Scroll to follow the motion event
                 final int pointerIndex = ev.findPointerIndex(mActivePointerId);
-                final float x = filterX(ev.getX(pointerIndex));
+                final float x = ev.getX(pointerIndex);
                 final float deltaX = mLastMotionX - x;
                 mLastMotionX = x;
 
                 if (deltaX < 0) {
-                    if (mScrollX > 0) {
-                        scrollBy(Math.round(Math.max(-mScrollX, deltaX)), 0);
-                        updateWallpaperOffset();
+                    if (mTouchX > 0) {
+                        mTouchX += Math.max(-mTouchX, deltaX);
+                        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+                        invalidate();
                     }
                 } else if (deltaX > 0) {
-                    final int availableToScroll = getChildAt(getChildCount() - 1).getRight() -
-                            mScrollX - getWidth();
+                    final float availableToScroll = getChildAt(getChildCount() - 1).getRight() -
+                            mTouchX - getWidth();
                     if (availableToScroll > 0) {
-                        scrollBy(Math.round(Math.min(availableToScroll, deltaX)), 0);
-                        updateWallpaperOffset();
+                        mTouchX += Math.min(availableToScroll, deltaX);
+                        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+                        invalidate();
                     }
                 } else {
                     awakenScrollBars();
@@ -924,7 +930,6 @@
                     mVelocityTracker.recycle();
                     mVelocityTracker = null;
                 }
-                resetFilter();
             }
             mTouchState = TOUCH_STATE_REST;
             mActivePointerId = INVALID_POINTER;
@@ -932,7 +937,6 @@
         case MotionEvent.ACTION_CANCEL:
             mTouchState = TOUCH_STATE_REST;
             mActivePointerId = INVALID_POINTER;
-            resetFilter();
             break;
         case MotionEvent.ACTION_POINTER_UP:
             onSecondaryPointerUp(ev);