am 7e0a4037: Merge "Shifting hotseat icons to aling with all-apps icon, if the hotseat size is different from the source device" into ub-launcher3-burnaby

* commit '7e0a403759c401d3b94f4576bca3aa8fb94fe542':
  Shifting hotseat icons to aling with all-apps icon, if the hotseat size is different from the source device
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 827332a..c2017e2 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -75,10 +75,6 @@
     <!-- PagedView specific attributes. These attributes are used to customize
          a PagedView view in XML files. -->
     <declare-styleable name="PagedView">
-        <!-- A spacing override for the icons within a page -->
-        <attr name="pageLayoutWidthGap" format="dimension" />
-        <attr name="pageLayoutHeightGap" format="dimension" />
-
         <!-- The page indicator for this workspace -->
         <attr name="pageIndicator" format="reference" />
     </declare-styleable>
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index c95d558..7249c64 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -28,13 +28,11 @@
 import com.android.launcher3.util.ComponentKey;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 
 /**
  * Represents an app in AllAppsView.
  */
 public class AppInfo extends ItemInfo {
-    private static final String TAG = "Launcher3.AppInfo";
 
     /**
      * The intent used to start the application.
@@ -118,8 +116,7 @@
         return "ApplicationInfo(title=" + title + " id=" + this.id
                 + " type=" + this.itemType + " container=" + this.container
                 + " screen=" + screenId + " cellX=" + cellX + " cellY=" + cellY
-                + " spanX=" + spanX + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos)
-                + " user=" + user + ")";
+                + " spanX=" + spanX + " spanY=" + spanY + " user=" + user + ")";
     }
 
     /**
@@ -128,7 +125,7 @@
     public static void dumpApplicationInfoList(String tag, String label, ArrayList<AppInfo> list) {
         Log.d(tag, label + " size=" + list.size());
         for (AppInfo info: list) {
-            Log.d(tag, "   title=\"" + info.title + "\" iconBitmap=" + info.iconBitmap 
+            Log.d(tag, "   title=\"" + info.title + "\" iconBitmap=" + info.iconBitmap
                     + " firstInstallTime=" + info.firstInstallTime
                     + " componentName=" + info.componentName.getPackageName());
         }
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index b7f89d0..574f229 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -24,7 +24,6 @@
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.content.res.Configuration;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.PointF;
@@ -185,8 +184,8 @@
         }
     }
 
-	@Override
-    public final void onDragStart(DragSource source, Object info, int dragAction) {
+    @Override
+    public final void onDragStart(DragSource source, ItemInfo info, int dragAction) {
         mActive = supportsDrop(source, info);
         mDrawable.setColorFilter(null);
         if (mCurrentColorAnim != null) {
@@ -202,7 +201,7 @@
         return supportsDrop(dragObject.dragSource, dragObject.dragInfo);
     }
 
-    protected abstract boolean supportsDrop(DragSource source, Object info);
+    protected abstract boolean supportsDrop(DragSource source, ItemInfo info);
 
     @Override
     public boolean isDropEnabled() {
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 8096887..e96768f 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -50,6 +50,7 @@
 
 import com.android.launcher3.BubbleTextView.BubbleTextShadowHandler;
 import com.android.launcher3.FolderIcon.FolderRingAnimator;
+import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
 import com.android.launcher3.accessibility.FolderAccessibilityHelper;
 import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
@@ -1090,23 +1091,6 @@
      *
      * @param pixelX The X location at which you want to search for a vacant area.
      * @param pixelY The Y location at which you want to search for a vacant area.
-     * @param spanX Horizontal span of the object.
-     * @param spanY Vertical span of the object.
-     * @param result Array in which to place the result, or null (in which case a new array will
-     *        be allocated)
-     * @return The X, Y cell of a vacant area that can contain this object,
-     *         nearest the requested location.
-     */
-    int[] findNearestVacantArea(int pixelX, int pixelY, int spanX, int spanY, int[] result) {
-        return findNearestVacantArea(pixelX, pixelY, spanX, spanY, spanX, spanY, result, null);
-    }
-
-    /**
-     * Find a vacant area that will fit the given bounds nearest the requested
-     * cell location. Uses Euclidean distance to score multiple vacant areas.
-     *
-     * @param pixelX The X location at which you want to search for a vacant area.
-     * @param pixelY The Y location at which you want to search for a vacant area.
      * @param minSpanX The minimum horizontal span required
      * @param minSpanY The minimum vertical span required
      * @param spanX Horizontal span of the object.
@@ -2198,6 +2182,15 @@
                 mOccupied[i][j] = mTmpOccupied[i][j];
             }
         }
+
+        long screenId = mLauncher.getWorkspace().getIdForScreen(this);
+        int container = Favorites.CONTAINER_DESKTOP;
+
+        if (mLauncher.isHotseatLayout(this)) {
+            screenId = -1;
+            container = Favorites.CONTAINER_HOTSEAT;
+        }
+
         int childCount = mShortcutsAndWidgets.getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = mShortcutsAndWidgets.getChildAt(i);
@@ -2206,17 +2199,21 @@
             // We do a null check here because the item info can be null in the case of the
             // AllApps button in the hotseat.
             if (info != null) {
-                if (info.cellX != lp.tmpCellX || info.cellY != lp.tmpCellY ||
-                        info.spanX != lp.cellHSpan || info.spanY != lp.cellVSpan) {
-                    info.requiresDbUpdate = true;
-                }
+                final boolean requiresDbUpdate = (info.cellX != lp.tmpCellX
+                        || info.cellY != lp.tmpCellY || info.spanX != lp.cellHSpan
+                        || info.spanY != lp.cellVSpan);
+
                 info.cellX = lp.cellX = lp.tmpCellX;
                 info.cellY = lp.cellY = lp.tmpCellY;
                 info.spanX = lp.cellHSpan;
                 info.spanY = lp.cellVSpan;
+
+                if (requiresDbUpdate) {
+                    LauncherModel.modifyItemInDatabase(mLauncher, info, container, screenId,
+                            info.cellX, info.cellY, info.spanX, info.spanY);
+                }
             }
         }
-        mLauncher.getWorkspace().updateItemLocationsInDatabase(this);
     }
 
     private void setUseTempCoords(boolean useTempCoords) {
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 9c8659c..ae6e3ba 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -46,20 +46,20 @@
         setDrawable(R.drawable.ic_remove_launcher);
     }
 
-    public static boolean supportsDrop(Object info) {
+    public static boolean supportsDrop(ItemInfo info) {
         return (info instanceof ShortcutInfo)
                 || (info instanceof LauncherAppWidgetInfo)
                 || (info instanceof FolderInfo);
     }
 
     @Override
-    protected boolean supportsDrop(DragSource source, Object info) {
+    protected boolean supportsDrop(DragSource source, ItemInfo info) {
         return source.supportsDeleteDropTarget() && supportsDrop(info);
     }
 
     @Override
     @Thunk void completeDrop(DragObject d) {
-        ItemInfo item = (ItemInfo) d.dragInfo;
+        ItemInfo item = d.dragInfo;
         if ((d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder)) {
             removeWorkspaceOrFolderItem(mLauncher, item, null);
         }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 62b05b0..5966112 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -349,13 +349,13 @@
     }
 
     // The rect returned will be extended to below the system ui that covers the workspace
-    Rect getHotseatRect() {
+    public boolean isInHotseatRect(int x, int y) {
         if (isVerticalBarLayout()) {
-            return new Rect(availableWidthPx - hotseatBarHeightPx, 0,
-                    Integer.MAX_VALUE, availableHeightPx);
+            return (x >= (availableWidthPx - hotseatBarHeightPx))
+                    && (y >= 0) && (y <= availableHeightPx);
         } else {
-            return new Rect(0, availableHeightPx - hotseatBarHeightPx,
-                    availableWidthPx, Integer.MAX_VALUE);
+            return (x >= 0) && (x <= availableWidthPx)
+                    && (y >= (availableHeightPx - hotseatBarHeightPx));
         }
     }
 
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index 2191455..410271d 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -135,14 +135,14 @@
          * @param dragAction The drag action: either {@link DragController#DRAG_ACTION_MOVE}
          *        or {@link DragController#DRAG_ACTION_COPY}
          */
-        void onDragStart(DragSource source, Object info, int dragAction);
+        void onDragStart(DragSource source, ItemInfo info, int dragAction);
 
         /**
          * The drag has ended
          */
         void onDragEnd();
     }
-    
+
     /**
      * Used to create a new DragLayer from XML.
      *
@@ -178,7 +178,7 @@
      * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
      *          Makes dragging feel more precise, e.g. you can clip out a transparent border
      */
-    public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo,
+    public void startDrag(View v, Bitmap bmp, DragSource source, ItemInfo dragInfo,
             Rect viewImageBounds, int dragAction, float initialDragViewScale) {
         int[] loc = mCoordinatesTemp;
         mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
@@ -211,7 +211,7 @@
      * @param accessible whether this drag should occur in accessibility mode
      */
     public DragView startDrag(Bitmap b, int dragLayerX, int dragLayerY,
-            DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion,
+            DragSource source, ItemInfo dragInfo, int dragAction, Point dragOffset, Rect dragRegion,
             float initialDragViewScale, boolean accessible) {
         if (PROFILE_DRAWING_DURING_DRAG) {
             android.os.Debug.startMethodTracing("Launcher");
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index c8fac54..3748464 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -47,7 +47,7 @@
         public DragView dragView = null;
 
         /** The data associated with the object being dragged */
-        public Object dragInfo = null;
+        public ItemInfo dragInfo = null;
 
         /** Where the drag originated */
         public DragSource dragSource = null;
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index 2e19f6e..21f23b5 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -600,7 +600,7 @@
     }
 
     @Override
-    public void onDragStart(DragSource source, Object info, int dragAction) { }
+    public void onDragStart(DragSource source, ItemInfo info, int dragAction) { }
 
     @Override
     public void onDragEnd() {
@@ -649,7 +649,7 @@
     }
 
     public boolean acceptDrop(DragObject d) {
-        final ItemInfo item = (ItemInfo) d.dragInfo;
+        final ItemInfo item = d.dragInfo;
         final int itemType = item.itemType;
         return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
                     itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index 8d534d2..de0df0d 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -330,8 +330,8 @@
                 !mFolder.isFull() && item != mInfo && !mInfo.opened);
     }
 
-    public boolean acceptDrop(Object dragInfo) {
-        final ItemInfo item = (ItemInfo) dragInfo;
+    public boolean acceptDrop(ItemInfo dragInfo) {
+        final ItemInfo item = dragInfo;
         return !mFolder.isDestroyed() && willAcceptItem(item);
     }
 
@@ -339,8 +339,8 @@
         mInfo.add(item);
     }
 
-    public void onDragEnter(Object dragInfo) {
-        if (mFolder.isDestroyed() || !willAcceptItem((ItemInfo) dragInfo)) return;
+    public void onDragEnter(ItemInfo dragInfo) {
+        if (mFolder.isDestroyed() || !willAcceptItem(dragInfo)) return;
         CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
         CellLayout layout = (CellLayout) getParent().getParent();
         mFolderRingAnimator.setCell(lp.cellX, lp.cellY);
@@ -356,7 +356,7 @@
             // Workspace#onDropExternal.
             mOpenAlarm.setAlarm(ON_OPEN_DELAY);
         }
-        mDragInfo = (ItemInfo) dragInfo;
+        mDragInfo = dragInfo;
     }
 
     public void onDragOver(Object dragInfo) {
diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java
index aea21c9..6e0dcd4 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -22,7 +22,6 @@
 import com.android.launcher3.compat.UserHandleCompat;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 
 /**
  * Represents a folder containing shortcuts or apps.
@@ -140,7 +139,7 @@
         return "FolderInfo(id=" + this.id + " type=" + this.itemType
                 + " container=" + this.container + " screen=" + screenId
                 + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
-                + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos) + ")";
+                + " spanY=" + spanY + ")";
     }
 
     public boolean hasOption(int optionFlag) {
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index d93cdcc..b4a1445 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -20,8 +20,6 @@
 import android.content.Context;
 import android.util.AttributeSet;
 
-import com.android.launcher3.compat.UserHandleCompat;
-
 public class InfoDropTarget extends ButtonDropTarget {
 
     public InfoDropTarget(Context context, AttributeSet attrs) {
@@ -41,7 +39,7 @@
         setDrawable(R.drawable.ic_info_launcher);
     }
 
-    public static void startDetailsActivityForInfo(Object info, Launcher launcher) {
+    public static void startDetailsActivityForInfo(ItemInfo info, Launcher launcher) {
         ComponentName componentName = null;
         if (info instanceof AppInfo) {
             componentName = ((AppInfo) info).componentName;
@@ -50,24 +48,17 @@
         } else if (info instanceof PendingAddItemInfo) {
             componentName = ((PendingAddItemInfo) info).componentName;
         }
-        final UserHandleCompat user;
-        if (info instanceof ItemInfo) {
-            user = ((ItemInfo) info).user;
-        } else {
-            user = UserHandleCompat.myUserHandle();
-        }
-
         if (componentName != null) {
-            launcher.startApplicationDetailsActivity(componentName, user);
+            launcher.startApplicationDetailsActivity(componentName, info.user);
         }
     }
 
     @Override
-    protected boolean supportsDrop(DragSource source, Object info) {
+    protected boolean supportsDrop(DragSource source, ItemInfo info) {
         return source.supportsAppInfoDropTarget() && supportsDrop(getContext(), info);
     }
 
-    public static boolean supportsDrop(Context context, Object info) {
+    public static boolean supportsDrop(Context context, ItemInfo info) {
         return info instanceof AppInfo || info instanceof PendingAddItemInfo;
     }
 
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index f7e0ea4..4bc5019 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -24,8 +24,6 @@
 import com.android.launcher3.compat.UserHandleCompat;
 import com.android.launcher3.compat.UserManagerCompat;
 
-import java.util.Arrays;
-
 /**
  * Represents an item in the launcher.
  */
@@ -35,14 +33,14 @@
      * Intent extra to store the profile. Format: UserHandle
      */
     static final String EXTRA_PROFILE = "profile";
-    
+
     public static final int NO_ID = -1;
-    
+
     /**
      * The id in the settings database for this item
      */
     public long id = NO_ID;
-    
+
     /**
      * One of {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
      * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
@@ -50,20 +48,20 @@
      * {@link LauncherSettings.Favorites#ITEM_TYPE_APPWIDGET}.
      */
     public int itemType;
-    
+
     /**
-     * The id of the container that holds this item. For the desktop, this will be 
+     * The id of the container that holds this item. For the desktop, this will be
      * {@link LauncherSettings.Favorites#CONTAINER_DESKTOP}. For the all applications folder it
      * will be {@link #NO_ID} (since it is not stored in the settings DB). For user folders
      * it will be the id of the folder.
      */
     public long container = NO_ID;
-    
+
     /**
      * Iindicates the screen in which the shortcut appears.
      */
     public long screenId = -1;
-    
+
     /**
      * Indicates the X position of the associated cell.
      */
@@ -100,11 +98,6 @@
     public int rank = 0;
 
     /**
-     * Indicates that this item needs to be updated in the db
-     */
-    public boolean requiresDbUpdate = false;
-
-    /**
      * Title of the item
      */
     public CharSequence title;
@@ -114,11 +107,6 @@
      */
     public CharSequence contentDescription;
 
-    /**
-     * The position of the item in a drag-and-drop operation.
-     */
-    public int[] dropPos = null;
-
     public UserHandleCompat user;
 
     public ItemInfo() {
@@ -194,7 +182,6 @@
     public String toString() {
         return "Item(id=" + this.id + " type=" + this.itemType + " container=" + this.container
             + " screen=" + screenId + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
-            + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos)
-            + " user=" + user + ")";
+            + " spanY=" + spanY + " user=" + user + ")";
     }
 }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 6648b6e..279a82b 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -165,8 +165,6 @@
      */
     protected static final int REQUEST_LAST = 100;
 
-    static final int SCREEN_COUNT = 5;
-
     // To turn on these properties, type
     // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
     static final String DUMP_STATE_PROPERTY = "launcher_dump_state";
@@ -253,7 +251,7 @@
     private AppWidgetManagerCompat mAppWidgetManager;
     private LauncherAppWidgetHost mAppWidgetHost;
 
-    @Thunk ItemInfo mPendingAddInfo = new ItemInfo();
+    @Thunk final ItemInfo mPendingAddInfo = new ItemInfo();
     private LauncherAppWidgetProviderInfo mPendingAddWidgetInfo;
     private int mPendingAddWidgetId = -1;
 
@@ -295,8 +293,6 @@
     private ArrayList<Runnable> mBindOnResumeCallbacks = new ArrayList<Runnable>();
     private ArrayList<Runnable> mOnResumeCallbacks = new ArrayList<Runnable>();
 
-    private Bundle mSavedInstanceState;
-
     private LauncherModel mModel;
     private IconCache mIconCache;
     @Thunk boolean mUserPresent = true;
@@ -840,24 +836,22 @@
             return;
         }
 
-        // The pattern used here is that a user PICKs a specific application,
-        // which, depending on the target, might need to CREATE the actual target.
-
-        // For example, the user would PICK_SHORTCUT for "Music playlist", and we
-        // launch over to the Music app to actually CREATE_SHORTCUT.
-        if (resultCode == RESULT_OK && mPendingAddInfo.container != ItemInfo.NO_ID) {
-            final PendingAddArguments args = preparePendingAddArgs(requestCode, data, -1,
-                    mPendingAddInfo);
-            if (isWorkspaceLocked()) {
-                sPendingAddItem = args;
-            } else {
-                completeAdd(args);
+        if (requestCode == REQUEST_CREATE_SHORTCUT) {
+            // Handle custom shortcuts created using ACTION_CREATE_SHORTCUT.
+            if (resultCode == RESULT_OK && mPendingAddInfo.container != ItemInfo.NO_ID) {
+                final PendingAddArguments args = preparePendingAddArgs(requestCode, data, -1,
+                        mPendingAddInfo);
+                if (isWorkspaceLocked()) {
+                    sPendingAddItem = args;
+                } else {
+                    completeAdd(args);
+                    mWorkspace.removeExtraEmptyScreenDelayed(true, exitSpringLoaded,
+                            ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
+                }
+            } else if (resultCode == RESULT_CANCELED) {
                 mWorkspace.removeExtraEmptyScreenDelayed(true, exitSpringLoaded,
                         ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
             }
-        } else if (resultCode == RESULT_CANCELED) {
-            mWorkspace.removeExtraEmptyScreenDelayed(true, exitSpringLoaded,
-                    ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
         }
         mDragLayer.clearAnimatedView();
 
@@ -1505,7 +1499,6 @@
     private void completeAddShortcut(Intent data, long container, long screenId, int cellX,
             int cellY) {
         int[] cellXY = mTmpAddItemCellCoordinates;
-        int[] touchXY = mPendingAddInfo.dropPos;
         CellLayout layout = getCellLayout(container, screenId);
 
         ShortcutInfo info = InstallShortcutReceiver.fromShortcutIntent(this, data);
@@ -1532,10 +1525,6 @@
                     true)) {
                 return;
             }
-        } else if (touchXY != null) {
-            // when dragging and dropping, just find the closest free spot
-            int[] result = layout.findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, cellXY);
-            foundCellSpan = (result != null);
         } else {
             foundCellSpan = layout.findCellForSpan(cellXY, 1, 1);
         }
@@ -2219,7 +2208,6 @@
         mPendingAddInfo.cellX = mPendingAddInfo.cellY = -1;
         mPendingAddInfo.spanX = mPendingAddInfo.spanY = -1;
         mPendingAddInfo.minSpanX = mPendingAddInfo.minSpanY = -1;
-        mPendingAddInfo.dropPos = null;
     }
 
     void addAppWidgetImpl(final int appWidgetId, final ItemInfo info, final
@@ -2291,7 +2279,6 @@
         resetAddInfo();
         mPendingAddInfo.container = container;
         mPendingAddInfo.screenId = screenId;
-        mPendingAddInfo.dropPos = null;
 
         if (cell != null) {
             mPendingAddInfo.cellX = cell[0];
@@ -2315,7 +2302,6 @@
         resetAddInfo();
         mPendingAddInfo.container = info.container = container;
         mPendingAddInfo.screenId = info.screenId = screenId;
-        mPendingAddInfo.dropPos = null;
         mPendingAddInfo.minSpanX = info.minSpanX;
         mPendingAddInfo.minSpanY = info.minSpanY;
 
@@ -2475,8 +2461,10 @@
 
         if (v instanceof CellLayout) {
             if (mWorkspace.isInOverviewMode()) {
-                showWorkspace(mWorkspace.indexOfChild(v), true);
+                mWorkspace.snapToPageFromOverView(mWorkspace.indexOfChild(v));
+                showWorkspace(true);
             }
+            return;
         }
 
         Object tag = v.getTag();
@@ -3274,26 +3262,17 @@
     }
 
     public void showWorkspace(boolean animated) {
-        showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated, null);
+        showWorkspace(animated, null);
     }
 
     public void showWorkspace(boolean animated, Runnable onCompleteRunnable) {
-        showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated,
-                onCompleteRunnable);
-    }
-
-    protected void showWorkspace(int snapToPage, boolean animated) {
-        showWorkspace(snapToPage, animated, null);
-    }
-
-    void showWorkspace(int snapToPage, boolean animated, Runnable onCompleteRunnable) {
         boolean changed = mState != State.WORKSPACE ||
                 mWorkspace.getState() != Workspace.State.NORMAL;
         if (changed) {
             boolean wasInSpringLoadedMode = (mState != State.WORKSPACE);
             mWorkspace.setVisibility(View.VISIBLE);
             mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.NORMAL,
-                    snapToPage, animated, onCompleteRunnable);
+                    animated, onCompleteRunnable);
 
             // Show the search bar (only animate if we were showing the drop target bar in spring
             // loaded mode)
@@ -3324,8 +3303,7 @@
     void showOverviewMode(boolean animated) {
         mWorkspace.setVisibility(View.VISIBLE);
         mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.OVERVIEW,
-                WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated,
-                null /* onCompleteRunnable */);
+                animated, null /* onCompleteRunnable */);
         mState = State.WORKSPACE;
     }
 
@@ -3401,11 +3379,11 @@
      * Updates the workspace and interaction state on state change, and return the animation to this
      * new state.
      */
-    public Animator startWorkspaceStateChangeAnimation(Workspace.State toState, int toPage,
+    public Animator startWorkspaceStateChangeAnimation(Workspace.State toState,
             boolean animated, boolean hasOverlaySearchBar, HashMap<View, Integer> layerViews) {
         Workspace.State fromState = mWorkspace.getState();
-        Animator anim = mWorkspace.setStateWithAnimation(toState, toPage, animated,
-                hasOverlaySearchBar, layerViews);
+        Animator anim = mWorkspace.setStateWithAnimation(
+                toState, animated, hasOverlaySearchBar, layerViews);
         updateInteraction(fromState, toState);
         return anim;
     }
@@ -3418,8 +3396,7 @@
         }
 
         mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.SPRING_LOADED,
-                WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, true /* animated */,
-                null /* onCompleteRunnable */);
+                true /* animated */, null /* onCompleteRunnable */);
         mState = isAppsViewVisible() ? State.APPS_SPRING_LOADED : State.WIDGETS_SPRING_LOADED;
     }
 
@@ -3638,7 +3615,7 @@
         if (mWorkspace != null) {
             return mWorkspace.getCurrentPage();
         } else {
-            return SCREEN_COUNT / 2;
+            return 0;
         }
     }
 
@@ -4608,7 +4585,6 @@
         Log.d(TAG, "mWorkspaceLoading=" + mWorkspaceLoading);
         Log.d(TAG, "mRestoring=" + mRestoring);
         Log.d(TAG, "mWaitingForResult=" + mWaitingForResult);
-        Log.d(TAG, "mSavedInstanceState=" + mSavedInstanceState);
         Log.d(TAG, "sFolders.size=" + sFolders.size());
         mModel.dumpState();
         // TODO(hyunyoungs): add mWidgetsView.dumpState(); or mWidgetsModel.dumpState();
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 0b67310..1fbb06e 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -660,12 +660,7 @@
                         modelShortcut.cellX == shortcut.cellX &&
                         modelShortcut.cellY == shortcut.cellY &&
                         modelShortcut.spanX == shortcut.spanX &&
-                        modelShortcut.spanY == shortcut.spanY &&
-                        ((modelShortcut.dropPos == null && shortcut.dropPos == null) ||
-                        (modelShortcut.dropPos != null &&
-                                shortcut.dropPos != null &&
-                                modelShortcut.dropPos[0] == shortcut.dropPos[0] &&
-                        modelShortcut.dropPos[1] == shortcut.dropPos[1]))) {
+                        modelShortcut.spanY == shortcut.spanY) {
                     // For all intents and purposes, this is the same object
                     return;
                 }
@@ -2446,19 +2441,36 @@
         private void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {
             final LauncherAppState app = LauncherAppState.getInstance();
             final InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
-            // XXX: review this
+            final int screenCols = profile.numColumns;
+            final int screenCellCount = profile.numColumns * profile.numRows;
             Collections.sort(workspaceItems, new Comparator<ItemInfo>() {
                 @Override
                 public int compare(ItemInfo lhs, ItemInfo rhs) {
-                    int cellCountX = (int) profile.numColumns;
-                    int cellCountY = (int) profile.numRows;
-                    int screenOffset = cellCountX * cellCountY;
-                    int containerOffset = screenOffset * (Launcher.SCREEN_COUNT + 1); // +1 hotseat
-                    long lr = (lhs.container * containerOffset + lhs.screenId * screenOffset +
-                            lhs.cellY * cellCountX + lhs.cellX);
-                    long rr = (rhs.container * containerOffset + rhs.screenId * screenOffset +
-                            rhs.cellY * cellCountX + rhs.cellX);
-                    return (int) (lr - rr);
+                    if (lhs.container == rhs.container) {
+                        // Within containers, order by their spatial position in that container
+                        switch ((int) lhs.container) {
+                            case LauncherSettings.Favorites.CONTAINER_DESKTOP: {
+                                long lr = (lhs.screenId * screenCellCount +
+                                        lhs.cellY * screenCols + lhs.cellX);
+                                long rr = (rhs.screenId * screenCellCount +
+                                        rhs.cellY * screenCols + rhs.cellX);
+                                return (int) (lr - rr);
+                            }
+                            case LauncherSettings.Favorites.CONTAINER_HOTSEAT: {
+                                // We currently use the screen id as the rank
+                                return (int) (lhs.screenId - rhs.screenId);
+                            }
+                            default:
+                                if (LauncherAppState.isDogfoodBuild()) {
+                                    throw new RuntimeException("Unexpected container type when " +
+                                            "sorting workspace items.");
+                                }
+                                return 0;
+                        }
+                    } else {
+                        // Between containers, order by hotseat, desktop
+                        return (int) (lhs.container - rhs.container);
+                    }
                 }
             });
         }
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index d69b743..38ccfa7 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -170,7 +170,6 @@
     public void startAnimationToWidgets(final boolean animated) {
         final WidgetsContainerView toView = mLauncher.getWidgetsView();
         final View buttonView = mLauncher.getWidgetsButton();
-
         PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
             @Override
             public float getMaterialRevealViewFinalAlpha(View revealView) {
@@ -186,7 +185,7 @@
      * Starts and animation to the workspace from the current overlay view.
      */
     public void startAnimationToWorkspace(final Launcher.State fromState,
-              final Workspace.State toWorkspaceState, final int toWorkspacePage,
+              final Workspace.State toWorkspaceState,
               final boolean animated, final Runnable onCompleteRunnable) {
         if (toWorkspaceState != Workspace.State.NORMAL &&
                 toWorkspaceState != Workspace.State.SPRING_LOADED &&
@@ -195,11 +194,9 @@
         }
 
         if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED) {
-            startAnimationToWorkspaceFromAllApps(toWorkspaceState, toWorkspacePage,
-                    animated, onCompleteRunnable);
+            startAnimationToWorkspaceFromAllApps(toWorkspaceState, animated, onCompleteRunnable);
         } else {
-            startAnimationToWorkspaceFromWidgets(toWorkspaceState, toWorkspacePage,
-                    animated, onCompleteRunnable);
+            startAnimationToWorkspaceFromWidgets(toWorkspaceState, animated, onCompleteRunnable);
         }
     }
 
@@ -229,7 +226,7 @@
 
         // Create the workspace animation.
         // NOTE: this call apparently also sets the state for the workspace if !animated
-        Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState, -1,
+        Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState,
                 animated, overlaySearchBarView != null /* hasOverlaySearchBar */, layerViews);
 
         if (animated && initialized) {
@@ -415,7 +412,7 @@
      * Starts and animation to the workspace from the apps view.
      */
     private void startAnimationToWorkspaceFromAllApps(final Workspace.State toWorkspaceState,
-            final int toWorkspacePage, final boolean animated, final Runnable onCompleteRunnable) {
+            final boolean animated, final Runnable onCompleteRunnable) {
         AllAppsContainerView appsView = mLauncher.getAppsView();
         PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
             int[] mAllAppsToPanelDelta;
@@ -451,17 +448,16 @@
             }
         };
         // Only animate the search bar if animating to spring loaded mode from all apps
-        startAnimationToWorkspaceFromOverlay(toWorkspaceState, toWorkspacePage,
-                mLauncher.getAllAppsButton(), appsView, appsView.getContentView(),
-                appsView.getRevealView(), appsView.getSearchBarView(), animated,
-                onCompleteRunnable, cb);
+        startAnimationToWorkspaceFromOverlay(toWorkspaceState, mLauncher.getAllAppsButton(),
+                appsView, appsView.getContentView(), appsView.getRevealView(),
+                appsView.getSearchBarView(), animated, onCompleteRunnable, cb);
     }
 
     /**
      * Starts and animation to the workspace from the widgets view.
      */
     private void startAnimationToWorkspaceFromWidgets(final Workspace.State toWorkspaceState,
-              final int toWorkspacePage, final boolean animated, final Runnable onCompleteRunnable) {
+              final boolean animated, final Runnable onCompleteRunnable) {
         final WidgetsContainerView widgetsView = mLauncher.getWidgetsView();
         PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
             @Override
@@ -479,19 +475,18 @@
                 };
             }
         };
-        startAnimationToWorkspaceFromOverlay(toWorkspaceState, toWorkspacePage,
-                mLauncher.getWidgetsButton(), widgetsView, widgetsView.getContentView(),
-                widgetsView.getRevealView(), null, animated, onCompleteRunnable, cb);
-    }
+        startAnimationToWorkspaceFromOverlay(toWorkspaceState, mLauncher.getWidgetsButton(),
+                widgetsView, widgetsView.getContentView(), widgetsView.getRevealView(), null,
+                animated, onCompleteRunnable, cb);
+        }
 
     /**
      * Creates and starts a new animation to the workspace.
      */
     private void startAnimationToWorkspaceFromOverlay(final Workspace.State toWorkspaceState,
-              final int toWorkspacePage, final View buttonView, final View fromView,
-              final View contentView, final View revealView, final View overlaySearchBarView,
-              final boolean animated, final Runnable onCompleteRunnable,
-              final PrivateTransitionCallbacks pCb) {
+              final View buttonView, final View fromView, final View contentView,
+              final View revealView, final View overlaySearchBarView, final boolean animated,
+              final Runnable onCompleteRunnable, final PrivateTransitionCallbacks pCb) {
         final Resources res = mLauncher.getResources();
         final boolean material = Utilities.isLmpOrAbove();
         final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
@@ -511,7 +506,7 @@
         // Create the workspace animation.
         // NOTE: this call apparently also sets the state for the workspace if !animated
         Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState,
-                toWorkspacePage, animated, overlaySearchBarView != null /* hasOverlaySearchBar */,
+                animated, overlaySearchBarView != null /* hasOverlaySearchBar */,
                 layerViews);
 
         if (animated && initialized) {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 218c1a3..c9bbe0a 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -22,6 +22,7 @@
 import android.animation.LayoutTransition;
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
+import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -47,10 +48,8 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.Interpolator;
-
 import com.android.launcher3.util.LauncherEdgeEffect;
 import com.android.launcher3.util.Thunk;
-
 import java.util.ArrayList;
 
 /**
@@ -67,7 +66,6 @@
 
     protected static final int PAGE_SNAP_ANIMATION_DURATION = 750;
     protected static final int SLOW_PAGE_SNAP_ANIMATION_DURATION = 950;
-    protected static final float NANOTIME_DIV = 1000000000.0f;
 
     private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
     // The page is moved more than halfway, automatically move to the next page on touch up.
@@ -87,25 +85,19 @@
     private int mFreeScrollMinScrollX = -1;
     private int mFreeScrollMaxScrollX = -1;
 
-    static final int AUTOMATIC_PAGE_SPACING = -1;
-
     protected int mFlingThresholdVelocity;
     protected int mMinFlingVelocity;
     protected int mMinSnapVelocity;
 
-    protected float mDensity;
-    protected float mSmoothingTime;
-    protected float mTouchX;
-
     protected boolean mFirstLayout = true;
     private int mNormalChildHeight;
 
     protected int mCurrentPage;
     protected int mRestorePage = INVALID_RESTORE_PAGE;
-    protected int mChildCountOnLastLayout;
+    private int mChildCountOnLastLayout;
 
     protected int mNextPage = INVALID_PAGE;
-    protected int mMaxScrollX;
+    private int mMaxScrollX;
     protected LauncherScroller mScroller;
     private Interpolator mDefaultInterpolator;
     private VelocityTracker mVelocityTracker;
@@ -117,10 +109,10 @@
     private float mDownMotionY;
     private float mDownScrollX;
     private float mDragViewBaselineLeft;
-    protected float mLastMotionX;
-    protected float mLastMotionXRemainder;
-    protected float mLastMotionY;
-    protected float mTotalMotionX;
+    private float mLastMotionX;
+    private float mLastMotionXRemainder;
+    private float mLastMotionY;
+    private float mTotalMotionX;
     private int mLastScreenCenter = -1;
 
     private boolean mCancelTap;
@@ -133,23 +125,17 @@
     protected final static int TOUCH_STATE_NEXT_PAGE = 3;
     protected final static int TOUCH_STATE_REORDERING = 4;
 
-    protected final static float ALPHA_QUANTIZE_LEVEL = 0.0001f;
-
     protected int mTouchState = TOUCH_STATE_REST;
-    protected boolean mForceScreenScrolled = false;
+    private boolean mForceScreenScrolled = false;
 
     protected OnLongClickListener mLongClickListener;
 
     protected int mTouchSlop;
     private int mMaximumVelocity;
-    protected int mPageLayoutWidthGap;
-    protected int mPageLayoutHeightGap;
     protected int mCellCountX = 0;
     protected int mCellCountY = 0;
-    protected boolean mCenterPagesVertically;
     protected boolean mAllowOverScroll = true;
     protected int[] mTempVisiblePagesRange = new int[2];
-    protected boolean mForceDrawAllChildrenNextFrame;
 
     protected static final int INVALID_POINTER = -1;
 
@@ -180,7 +166,7 @@
 
     private float mMinScale = 1f;
     private boolean mUseMinScale = false;
-    protected View mDragView;
+    @Thunk View mDragView;
     private Runnable mSidePageHoverRunnable;
     @Thunk int mSidePageHoverIndex = -1;
     // This variable's scope is only for the duration of startReordering() and endReordering()
@@ -189,12 +175,12 @@
     // animation after endReordering()
     private boolean mIsReordering;
     // The runnable that settles the page after snapToPage and animateDragViewToOriginalPosition
-    private int NUM_ANIMATIONS_RUNNING_BEFORE_ZOOM_OUT = 2;
+    private static final int NUM_ANIMATIONS_RUNNING_BEFORE_ZOOM_OUT = 2;
     private int mPostReorderingPreZoomInRemainingAnimationCount;
     private Runnable mPostReorderingPreZoomInRunnable;
 
     // Convenience/caching
-    private static final Matrix sTmpInvMatrix = new Matrix();
+    protected static final Matrix sTmpInvMatrix = new Matrix();
     private static final float[] sTmpPoint = new float[2];
     private static final int[] sTmpIntPoint = new int[2];
     private static final Rect sTmpRect = new Rect();
@@ -223,11 +209,6 @@
 
         TypedArray a = context.obtainStyledAttributes(attrs,
                 R.styleable.PagedView, defStyle, 0);
-
-        mPageLayoutWidthGap = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutWidthGap, 0);
-        mPageLayoutHeightGap = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutHeightGap, 0);
         mPageIndicatorViewId = a.getResourceId(R.styleable.PagedView_pageIndicator, -1);
         a.recycle();
 
@@ -243,16 +224,15 @@
         mScroller = new LauncherScroller(getContext());
         setDefaultInterpolator(new ScrollInterpolator());
         mCurrentPage = 0;
-        mCenterPagesVertically = true;
 
         final ViewConfiguration configuration = ViewConfiguration.get(getContext());
         mTouchSlop = configuration.getScaledPagingTouchSlop();
         mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
-        mDensity = getResources().getDisplayMetrics().density;
 
-        mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
-        mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * mDensity);
-        mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * mDensity);
+        float density = getResources().getDisplayMetrics().density;
+        mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * density);
+        mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * density);
+        mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * density);
         setOnHierarchyChangeListener(this);
         setWillNotDraw(false);
     }
@@ -606,9 +586,6 @@
             super.scrollTo(x, y);
         }
 
-        mTouchX = x;
-        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
-
         // Update the last motion events when scrolling
         if (isReordering(true)) {
             float[] p = mapPointFromParentToView(this, mParentDownMotionX, mParentDownMotionY);
@@ -836,6 +813,7 @@
         setMeasuredDimension(scaledWidthSize, scaledHeightSize);
     }
 
+    @SuppressLint("DrawAllocation")
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         if (getChildCount() == 0) {
@@ -874,9 +852,7 @@
                     childTop = offsetY;
                 } else {
                     childTop = offsetY + getPaddingTop() + mInsets.top;
-                    if (mCenterPagesVertically) {
-                        childTop += (getViewportHeight() - mInsets.top - mInsets.bottom - verticalPadding - child.getMeasuredHeight()) / 2;
-                    }
+                    childTop += (getViewportHeight() - mInsets.top - mInsets.bottom - verticalPadding - child.getMeasuredHeight()) / 2;
                 }
 
                 final int childWidth = child.getMeasuredWidth();
@@ -1136,8 +1112,7 @@
                 for (int i = pageCount - 1; i >= 0; i--) {
                     final View v = getPageAt(i);
                     if (v == mDragView) continue;
-                    if (mForceDrawAllChildrenNextFrame ||
-                               (leftScreen <= i && i <= rightScreen && shouldDrawChild(v))) {
+                    if (leftScreen <= i && i <= rightScreen && shouldDrawChild(v)) {
                         drawChild(canvas, v, drawingTime);
                     }
                 }
@@ -1146,7 +1121,6 @@
                     drawChild(canvas, mDragView, drawingTime);
                 }
 
-                mForceDrawAllChildrenNextFrame = false;
                 canvas.restore();
             }
         }
@@ -1450,8 +1424,6 @@
             mTotalMotionX += Math.abs(mLastMotionX - x);
             mLastMotionX = x;
             mLastMotionXRemainder = 0;
-            mTouchX = getViewportOffsetX() + getScrollX();
-            mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
             onScrollInteractionBegin();
             pageBeginMoving();
         }
@@ -1650,8 +1622,6 @@
                 // keep the remainder because we are actually testing if we've moved from the last
                 // scrolled position (which is discrete).
                 if (Math.abs(deltaX) >= 1.0f) {
-                    mTouchX += deltaX;
-                    mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
                     scrollBy((int) deltaX, 0);
                     mLastMotionX = x;
                     mLastMotionXRemainder = deltaX - (int) deltaX;
@@ -2276,6 +2246,7 @@
     private static final int ANIM_TAG_KEY = 100;
 
     /* Accessibility */
+    @SuppressWarnings("deprecation")
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java
index 4cdf1ca..7c8f441 100644
--- a/src/com/android/launcher3/SearchDropTargetBar.java
+++ b/src/com/android/launcher3/SearchDropTargetBar.java
@@ -196,7 +196,7 @@
      * DragController.DragListener implementation
      */
     @Override
-    public void onDragStart(DragSource source, Object info, int dragAction) {
+    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
         showDeleteTarget();
     }
 
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 56c0b9d..fe76634 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -29,7 +29,6 @@
 import com.android.launcher3.compat.UserManagerCompat;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 
 /**
  * Represents a launchable icon on the workspaces and in folders.
@@ -241,7 +240,7 @@
         return "ShortcutInfo(title=" + title + "intent=" + intent + "id=" + this.id
                 + " type=" + this.itemType + " container=" + this.container + " screen=" + screenId
                 + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX + " spanY=" + spanY
-                + " dropPos=" + Arrays.toString(dropPos) + " user=" + user + ")";
+                + " user=" + user + ")";
     }
 
     public static void dumpShortcutInfoList(String tag, String label,
diff --git a/src/com/android/launcher3/UninstallDropTarget.java b/src/com/android/launcher3/UninstallDropTarget.java
index 0819f8c..7c548a5 100644
--- a/src/com/android/launcher3/UninstallDropTarget.java
+++ b/src/com/android/launcher3/UninstallDropTarget.java
@@ -8,7 +8,7 @@
 import android.os.UserManager;
 import android.util.AttributeSet;
 import android.util.Pair;
-import com.android.launcher3.R;
+
 import com.android.launcher3.compat.UserHandleCompat;
 import com.android.launcher3.util.Thunk;
 
@@ -32,7 +32,7 @@
     }
 
     @Override
-    protected boolean supportsDrop(DragSource source, Object info) {
+    protected boolean supportsDrop(DragSource source, ItemInfo info) {
         return supportsDrop(getContext(), info);
     }
 
@@ -81,7 +81,7 @@
     @Override
     void completeDrop(final DragObject d) {
         final Pair<ComponentName, Integer> componentInfo = getAppInfoFlags(d.dragInfo);
-        final UserHandleCompat user = ((ItemInfo) d.dragInfo).user;
+        final UserHandleCompat user = d.dragInfo.user;
         if (startUninstallActivity(mLauncher, d.dragInfo)) {
 
             final Runnable checkIfUninstallWasSuccess = new Runnable() {
@@ -99,9 +99,9 @@
         }
     }
 
-    public static boolean startUninstallActivity(Launcher launcher, Object info) {
+    public static boolean startUninstallActivity(Launcher launcher, ItemInfo info) {
         final Pair<ComponentName, Integer> componentInfo = getAppInfoFlags(info);
-        final UserHandleCompat user = ((ItemInfo) info).user;
+        final UserHandleCompat user = info.user;
         return launcher.startApplicationUninstallActivity(
                 componentInfo.first, componentInfo.second, user);
     }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 4a6b90a..edf8a32 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -92,13 +92,17 @@
 
     private static boolean ENFORCE_DRAG_EVENT_ORDER = false;
 
-    protected static final int SNAP_OFF_EMPTY_SCREEN_DURATION = 400;
-    protected static final int FADE_EMPTY_SCREEN_DURATION = 150;
+    private static final int SNAP_OFF_EMPTY_SCREEN_DURATION = 400;
+    private static final int FADE_EMPTY_SCREEN_DURATION = 150;
 
     private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
 
-    static final boolean MAP_NO_RECURSE = false;
-    static final boolean MAP_RECURSE = true;
+    private static final boolean MAP_NO_RECURSE = false;
+    private static final boolean MAP_RECURSE = true;
+
+    // The screen id used for the empty screen always present to the right.
+    public final static long EXTRA_EMPTY_SCREEN_ID = -201;
+    private final static long CUSTOM_CONTENT_SCREEN_ID = -301;
 
     private static final long CUSTOM_CONTENT_GESTURE_DELAY = 200;
     private long mTouchDownTime = -1;
@@ -113,10 +117,6 @@
 
     private ShortcutAndWidgetContainer mDragSourceInternal;
 
-    // The screen id used for the empty screen always present to the right.
-    final static long EXTRA_EMPTY_SCREEN_ID = -201;
-    private final static long CUSTOM_CONTENT_SCREEN_ID = -301;
-
     @Thunk LongArrayMap<CellLayout> mWorkspaceScreens = new LongArrayMap<>();
     @Thunk ArrayList<Long> mScreenOrder = new ArrayList<Long>();
 
@@ -136,8 +136,8 @@
     private int mDragOverX = -1;
     private int mDragOverY = -1;
 
-    static Rect mLandscapeCellLayoutMetrics = null;
-    static Rect mPortraitCellLayoutMetrics = null;
+    private static Rect mLandscapeCellLayoutMetrics = null;
+    private static Rect mPortraitCellLayoutMetrics = null;
 
     CustomContentCallbacks mCustomContentCallbacks;
     boolean mCustomContentShowing;
@@ -164,12 +164,11 @@
 
     // These are temporary variables to prevent having to allocate a new object just to
     // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
-    private int[] mTempCell = new int[2];
-    private int[] mTempPt = new int[2];
-    private int[] mTempEstimate = new int[2];
+    private static final Rect sTempRect = new Rect();
+    private final int[] mTempXY = new int[2];
     @Thunk float[] mDragViewVisualCenter = new float[2];
     private float[] mTempCellLayoutCenterCoordinates = new float[2];
-    private Matrix mTempInverseMatrix = new Matrix();
+    private int[] mTempVisiblePagesRange = new int[2];
 
     private SpringLoadedDragController mSpringLoadedDragController;
     private float mSpringLoadedShrinkFactor;
@@ -183,7 +182,6 @@
     private boolean mIsSwitchingState = false;
 
     boolean mAnimatingViewIntoPlace = false;
-    boolean mIsDragOccuring = false;
     boolean mChildrenLayersEnabled = true;
 
     private boolean mStripScreensOnPageStopMoving = false;
@@ -193,9 +191,6 @@
 
     private HolographicOutlineHelper mOutlineHelper;
     @Thunk Bitmap mDragOutline = null;
-    private static final Rect sTempRect = new Rect();
-    private final int[] mTempXY = new int[2];
-    private int[] mTempVisiblePagesRange = new int[2];
     public static final int DRAG_BITMAP_PADDING = 2;
     private boolean mWorkspaceFadeInAdjacentScreens;
 
@@ -206,7 +201,6 @@
 
     @Thunk Runnable mDelayedResizeRunnable;
     private Runnable mDelayedSnapToPageRunnable;
-    private Point mDisplaySize = new Point();
 
     // Variables relating to the creation of user folders by hovering shortcuts over shortcuts
     private static final int FOLDER_CREATION_TIMEOUT = 0;
@@ -363,12 +357,11 @@
     }
 
     @Override
-    public void onDragStart(final DragSource source, Object info, int dragAction) {
+    public void onDragStart(final DragSource source, ItemInfo info, int dragAction) {
         if (ENFORCE_DRAG_EVENT_ORDER) {
             enfoceDragParity("onDragStart", 0, 0);
         }
 
-        mIsDragOccuring = true;
         updateChildrenLayersEnabled(false);
         mLauncher.lockScreenOrientation();
         mLauncher.onInteractionBegin();
@@ -399,7 +392,6 @@
             removeExtraEmptyScreen(true, mDragSourceInternal != null);
         }
 
-        mIsDragOccuring = false;
         updateChildrenLayersEnabled(false);
         mLauncher.unlockScreenOrientation(false);
 
@@ -427,8 +419,6 @@
         setupLayoutTransition();
 
         mWallpaperOffset = new WallpaperOffsetInterpolator();
-        Display display = mLauncher.getWindowManager().getDefaultDisplay();
-        display.getSize(mDisplaySize);
 
         mMaxDistanceForFolderCreation = (0.55f * grid.iconSizePx);
 
@@ -1830,8 +1820,18 @@
         updateChildrenLayersEnabled(false);
     }
 
+    @Override
+    protected void getVisiblePages(int[] range) {
+        super.getVisiblePages(range);
+        if (mState == State.OVERVIEW || mState == State.SPRING_LOADED) {
+            // In overview mode, make sure that the two side pages are visible.
+            range[0] = Math.min(range[0], Math.max(getCurrentPage() - 1, numCustomPages()));
+            range[1] = Math.max(range[0], Math.min(getCurrentPage() + 1, getPageCount() - 1));
+        }
+    }
+
     protected void onWallpaperTap(MotionEvent ev) {
-        final int[] position = mTempCell;
+        final int[] position = mTempXY;
         getLocationOnScreen(position);
 
         int pointerIndex = ev.getActionIndex();
@@ -1950,6 +1950,10 @@
         return mState == State.OVERVIEW;
     }
 
+    public void snapToPageFromOverView(int whichPage) {
+        mStateTransitionAnimation.snapToPageFromOverView(whichPage);
+    }
+
     int getOverviewModeTranslationY() {
         DeviceProfile grid = mLauncher.getDeviceProfile();
         Rect overviewBar = grid.getOverviewModeButtonBarRect();
@@ -1967,15 +1971,19 @@
      * Sets the current workspace {@link State}, returning an animation transitioning the workspace
      * to that new state.
      */
-    public Animator setStateWithAnimation(State toState, int toPage, boolean animated,
+    public Animator setStateWithAnimation(State toState, boolean animated,
             boolean hasOverlaySearchBar, HashMap<View, Integer> layerViews) {
         // Create the animation to the new state
         Animator workspaceAnim =  mStateTransitionAnimation.getAnimationToState(mState,
-                toState, toPage, animated, hasOverlaySearchBar, layerViews);
+                toState, animated, hasOverlaySearchBar, layerViews);
 
         // Update the current state
         mState = toState;
         updateAccessibilityFlags();
+        if (mState == State.OVERVIEW || mState == State.SPRING_LOADED) {
+            // Redraw pages, as we might want to draw pages which were not visible.
+            invalidate();
+        }
 
         return workspaceAnim;
     }
@@ -2273,6 +2281,8 @@
             dragRect = new Rect(left, top, right, bottom);
         } else if (child instanceof FolderIcon) {
             int previewSize = grid.folderIconSizePx;
+            dragVisualizeOffset = new Point(-padding.get() / 2,
+                    padding.get() / 2 - child.getPaddingTop());
             dragRect = new Rect(0, child.getPaddingTop(), child.getWidth(), previewSize);
         }
 
@@ -2282,15 +2292,17 @@
             icon.clearPressedBackground();
         }
 
-        if (child.getTag() == null || !(child.getTag() instanceof ItemInfo)) {
+        Object dragObject = child.getTag();
+        if (!(dragObject instanceof ItemInfo)) {
             String msg = "Drag started with a view that has no tag set. This "
                     + "will cause a crash (issue 11627249) down the line. "
                     + "View: " + child + "  tag: " + child.getTag();
             throw new IllegalStateException(msg);
         }
 
-        DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
-                DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale, accessible);
+        DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source,
+                (ItemInfo) dragObject, DragController.DRAG_ACTION_MOVE, dragVisualizeOffset,
+                dragRect, scale, accessible);
         dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor());
 
         if (child.getParent() instanceof ShortcutAndWidgetContainer) {
@@ -2330,7 +2342,8 @@
         Point dragVisualizeOffset = new Point(-padding.get() / 2, padding.get() / 2);
         Rect dragRect = new Rect(0, 0, iconSize, iconSize);
 
-        if (child.getTag() == null || !(child.getTag() instanceof ItemInfo)) {
+        Object dragObject = child.getTag();
+        if (!(dragObject instanceof ItemInfo)) {
             String msg = "Drag started with a view that has no tag set. This "
                     + "will cause a crash (issue 11627249) down the line. "
                     + "View: " + child + "  tag: " + child.getTag();
@@ -2338,8 +2351,9 @@
         }
 
         // Start the drag
-        DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
-                DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale, false);
+        DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source,
+                (ItemInfo) dragObject, DragController.DRAG_ACTION_MOVE, dragVisualizeOffset,
+                dragRect, scale, false);
         dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor());
 
         // Recycle temporary bitmaps
@@ -2380,9 +2394,8 @@
                 spanX = dragCellInfo.spanX;
                 spanY = dragCellInfo.spanY;
             } else {
-                final ItemInfo dragInfo = (ItemInfo) d.dragInfo;
-                spanX = dragInfo.spanX;
-                spanY = dragInfo.spanY;
+                spanX = d.dragInfo.spanX;
+                spanY = d.dragInfo.spanY;
             }
 
             int minSpanX = spanX;
@@ -2397,12 +2410,12 @@
                     mTargetCell);
             float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0],
                     mDragViewVisualCenter[1], mTargetCell);
-            if (mCreateUserFolderOnDrop && willCreateUserFolder((ItemInfo) d.dragInfo,
+            if (mCreateUserFolderOnDrop && willCreateUserFolder(d.dragInfo,
                     dropTargetLayout, mTargetCell, distance, true)) {
                 return true;
             }
 
-            if (mAddToExistingFolderOnDrop && willAddToExistingUserFolder((ItemInfo) d.dragInfo,
+            if (mAddToExistingFolderOnDrop && willAddToExistingUserFolder(d.dragInfo,
                     dropTargetLayout, mTargetCell, distance)) {
                 return true;
             }
@@ -2468,7 +2481,7 @@
         return (aboveShortcut && willBecomeShortcut);
     }
 
-    boolean willAddToExistingUserFolder(Object dragInfo, CellLayout target, int[] targetCell,
+    boolean willAddToExistingUserFolder(ItemInfo dragInfo, CellLayout target, int[] targetCell,
             float distance) {
         if (distance > mMaxDistanceForFolderCreation) return false;
         View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
@@ -2581,7 +2594,7 @@
             }
         }
 
-        int snapScreen = WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE;
+        int snapScreen = -1;
         boolean resizeOnDrop = false;
         if (d.dragSource != this) {
             final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
@@ -2624,7 +2637,7 @@
 
                 // Aside from the special case where we're dropping a shortcut onto a shortcut,
                 // we need to find the nearest cell location that is vacant
-                ItemInfo item = (ItemInfo) d.dragInfo;
+                ItemInfo item = d.dragInfo;
                 int minSpanX = item.spanX;
                 int minSpanY = item.spanY;
                 if (item.minSpanX > 0 && item.minSpanY > 0) {
@@ -2742,9 +2755,7 @@
                     animateWidgetDrop(info, parent, d.dragView,
                             onCompleteRunnable, animationType, cell, false);
                 } else {
-                    int duration = snapScreen < 0 ?
-                            WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE :
-                                    ADJACENT_SCREEN_DROP_DURATION;
+                    int duration = snapScreen < 0 ? -1 : ADJACENT_SCREEN_DROP_DURATION;
                     mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
                             onCompleteRunnable, this);
                 }
@@ -2998,30 +3009,21 @@
        xy[1] = xy[1] - v.getTop();
    }
 
-   boolean isPointInSelfOverHotseat(int x, int y, Rect r) {
-       if (r == null) {
-           r = new Rect();
-       }
-       mTempPt[0] = x;
-       mTempPt[1] = y;
-       mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempPt, true);
-
-       DeviceProfile grid = mLauncher.getDeviceProfile();
-       r = grid.getHotseatRect();
-       if (r.contains(mTempPt[0], mTempPt[1])) {
-           return true;
-       }
-       return false;
+   boolean isPointInSelfOverHotseat(int x, int y) {
+       mTempXY[0] = x;
+       mTempXY[1] = y;
+       mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempXY, true);
+       return mLauncher.getDeviceProfile().isInHotseatRect(mTempXY[0], mTempXY[1]);
    }
 
    void mapPointFromSelfToHotseatLayout(Hotseat hotseat, float[] xy) {
-       mTempPt[0] = (int) xy[0];
-       mTempPt[1] = (int) xy[1];
-       mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempPt, true);
-       mLauncher.getDragLayer().mapCoordInSelfToDescendent(hotseat.getLayout(), mTempPt);
+       mTempXY[0] = (int) xy[0];
+       mTempXY[1] = (int) xy[1];
+       mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempXY, true);
+       mLauncher.getDragLayer().mapCoordInSelfToDescendent(hotseat.getLayout(), mTempXY);
 
-       xy[0] = mTempPt[0];
-       xy[1] = mTempPt[1];
+       xy[0] = mTempXY[0];
+       xy[1] = mTempXY[1];
    }
 
    /*
@@ -3069,8 +3071,8 @@
             final float[] touchXy = {originX, originY};
             // Transform the touch coordinates to the CellLayout's local coordinates
             // If the touch point is within the bounds of the cell layout, we can return immediately
-            cl.getMatrix().invert(mTempInverseMatrix);
-            mapPointFromSelfToChild(cl, touchXy, mTempInverseMatrix);
+            cl.getMatrix().invert(sTmpInvMatrix);
+            mapPointFromSelfToChild(cl, touchXy, sTmpInvMatrix);
 
             if (touchXy[0] >= 0 && touchXy[0] <= cl.getWidth() &&
                     touchXy[1] >= 0 && touchXy[1] <= cl.getHeight()) {
@@ -3112,9 +3114,8 @@
         // Skip drag over events while we are dragging over side pages
         if (mInScrollArea || !transitionStateShouldAllowDrop()) return;
 
-        Rect r = new Rect();
         CellLayout layout = null;
-        ItemInfo item = (ItemInfo) d.dragInfo;
+        ItemInfo item = d.dragInfo;
         if (item == null) {
             if (LauncherAppState.isDogfoodBuild()) {
                 throw new NullPointerException("DragObject has null info");
@@ -3130,7 +3131,7 @@
         // Identify whether we have dragged over a side page
         if (workspaceInModalState()) {
             if (mLauncher.getHotseat() != null && !isExternalDragWidget(d)) {
-                if (isPointInSelfOverHotseat(d.x, d.y, r)) {
+                if (isPointInSelfOverHotseat(d.x, d.y)) {
                     layout = mLauncher.getHotseat().getLayout();
                 }
             }
@@ -3153,7 +3154,7 @@
         } else {
             // Test to see if we are over the hotseat otherwise just use the current page
             if (mLauncher.getHotseat() != null && !isDragWidget(d)) {
-                if (isPointInSelfOverHotseat(d.x, d.y, r)) {
+                if (isPointInSelfOverHotseat(d.x, d.y)) {
                     layout = mLauncher.getHotseat().getLayout();
                 }
             }
@@ -3175,7 +3176,7 @@
                 mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
             }
 
-            ItemInfo info = (ItemInfo) d.dragInfo;
+            ItemInfo info = d.dragInfo;
 
             int minSpanX = item.spanX;
             int minSpanY = item.spanY;
@@ -3355,24 +3356,6 @@
     }
 
     /**
-     * Add the item specified by dragInfo to the given layout.
-     * @return true if successful
-     */
-    public boolean addExternalItemToScreen(ItemInfo dragInfo, CellLayout layout) {
-        if (layout.findCellForSpan(mTempEstimate, dragInfo.spanX, dragInfo.spanY)) {
-            onDropExternal(dragInfo.dropPos, (ItemInfo) dragInfo, (CellLayout) layout, false);
-            return true;
-        }
-        mLauncher.showOutOfSpaceMessage(mLauncher.isHotseatLayout(layout));
-        return false;
-    }
-
-    private void onDropExternal(int[] touchXY, Object dragInfo,
-            CellLayout cellLayout, boolean insertAtFirst) {
-        onDropExternal(touchXY, dragInfo, cellLayout, insertAtFirst, null);
-    }
-
-    /**
      * Drop an item that didn't originate on one of the workspace screens.
      * It may have come from Launcher (e.g. from all apps or customize), or it may have
      * come from another app altogether.
@@ -3380,7 +3363,7 @@
      * NOTE: This can also be called when we are outside of a drag event, when we want
      * to add an item to one of the workspace screens.
      */
-    private void onDropExternal(final int[] touchXY, final Object dragInfo,
+    private void onDropExternal(final int[] touchXY, final ItemInfo dragInfo,
             final CellLayout cellLayout, boolean insertAtFirst, DragObject d) {
         final Runnable exitSpringLoadedRunnable = new Runnable() {
             @Override
@@ -3390,7 +3373,7 @@
             }
         };
 
-        ItemInfo info = (ItemInfo) dragInfo;
+        ItemInfo info = dragInfo;
         int spanX = info.spanX;
         int spanY = info.spanY;
         if (mDragInfo != null) {
@@ -3417,14 +3400,14 @@
                         cellLayout, mTargetCell);
                 float distance = cellLayout.getDistanceFromCell(mDragViewVisualCenter[0],
                         mDragViewVisualCenter[1], mTargetCell);
-                if (willCreateUserFolder((ItemInfo) d.dragInfo, cellLayout, mTargetCell,
-                        distance, true) || willAddToExistingUserFolder((ItemInfo) d.dragInfo,
-                                cellLayout, mTargetCell, distance)) {
+                if (willCreateUserFolder(d.dragInfo, cellLayout, mTargetCell, distance, true)
+                        || willAddToExistingUserFolder(
+                                d.dragInfo, cellLayout, mTargetCell, distance)) {
                     findNearestVacantCell = false;
                 }
             }
 
-            final ItemInfo item = (ItemInfo) d.dragInfo;
+            final ItemInfo item = d.dragInfo;
             boolean updateWidgetSize = false;
             if (findNearestVacantCell) {
                 int minSpanX = item.spanX;
@@ -3785,29 +3768,6 @@
         }
     }
 
-    void updateItemLocationsInDatabase(CellLayout cl) {
-        int count = cl.getShortcutsAndWidgets().getChildCount();
-
-        long screenId = getIdForScreen(cl);
-        int container = Favorites.CONTAINER_DESKTOP;
-
-        if (mLauncher.isHotseatLayout(cl)) {
-            screenId = -1;
-            container = Favorites.CONTAINER_HOTSEAT;
-        }
-
-        for (int i = 0; i < count; i++) {
-            View v = cl.getShortcutsAndWidgets().getChildAt(i);
-            ItemInfo info = (ItemInfo) v.getTag();
-            // Null check required as the AllApps button doesn't have an item info
-            if (info != null && info.requiresDbUpdate) {
-                info.requiresDbUpdate = false;
-                LauncherModel.modifyItemInDatabase(mLauncher, info, container, screenId, info.cellX,
-                        info.cellY, info.spanX, info.spanY);
-            }
-        }
-    }
-
     void saveWorkspaceToDb() {
         saveWorkspaceScreenToDb((CellLayout) mLauncher.getHotseat().getLayout());
         int count = getChildCount();
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index b8916a7..5d16cd5 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -174,7 +174,6 @@
 
     public static final String TAG = "WorkspaceStateTransitionAnimation";
 
-    public static final int SCROLL_TO_CURRENT_PAGE = -1;
     @Thunk static final int BACKGROUND_FADE_OUT_DURATION = 350;
 
     final @Thunk Launcher mLauncher;
@@ -216,16 +215,18 @@
         mWorkspaceFadeInAdjacentScreens = grid.shouldFadeAdjacentWorkspaceScreens();
     }
 
+    public void snapToPageFromOverView(int whichPage) {
+        mWorkspace.snapToPage(whichPage, mOverviewTransitionTime, mZoomInInterpolator);
+    }
+
     public AnimatorSet getAnimationToState(Workspace.State fromState, Workspace.State toState,
-            int toPage, boolean animated, boolean hasOverlaySearchBar,
-            HashMap<View, Integer> layerViews) {
+            boolean animated, boolean hasOverlaySearchBar, HashMap<View, Integer> layerViews) {
         AccessibilityManager am = (AccessibilityManager)
                 mLauncher.getSystemService(Context.ACCESSIBILITY_SERVICE);
         final boolean accessibilityEnabled = am.isEnabled();
         TransitionStates states = new TransitionStates(fromState, toState);
         int duration = getAnimationDuration(states);
-        animateWorkspace(states, toPage, animated, duration, layerViews,
-                accessibilityEnabled);
+        animateWorkspace(states, animated, duration, layerViews, accessibilityEnabled);
         animateSearchBar(states, animated, duration, hasOverlaySearchBar, layerViews,
                 accessibilityEnabled);
         animateBackgroundGradient(states, animated, BACKGROUND_FADE_OUT_DURATION);
@@ -265,7 +266,7 @@
     /**
      * Starts a transition animation for the workspace.
      */
-    private void animateWorkspace(final TransitionStates states, int toPage, final boolean animated,
+    private void animateWorkspace(final TransitionStates states, final boolean animated,
                                   final int duration, final HashMap<View, Integer> layerViews,
                                   final boolean accessibilityEnabled) {
         // Reinitialize animation arrays for the current workspace state
@@ -305,11 +306,7 @@
             }
         }
 
-        if (toPage == SCROLL_TO_CURRENT_PAGE) {
-            toPage = mWorkspace.getPageNearestToCenterOfScreen();
-        }
-        mWorkspace.snapToPage(toPage, duration, mZoomInInterpolator);
-
+        int toPage = mWorkspace.getPageNearestToCenterOfScreen();
         for (int i = 0; i < childCount; i++) {
             final CellLayout cl = (CellLayout) mWorkspace.getChildAt(i);
             boolean isCurrentPage = (i == toPage);
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index fe7b25e..c11aab9 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -375,7 +375,7 @@
 
 
     @Override
-    public void onDragStart(DragSource source, Object info, int dragAction) {
+    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
         // No-op
     }
 
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 67d5728..32c9012 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -526,7 +526,7 @@
                 int currentScreen = mLauncher.getCurrentWorkspaceScreen();
                 Workspace workspace = (Workspace) target;
                 CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen);
-                ItemInfo itemInfo = (ItemInfo) d.dragInfo;
+                ItemInfo itemInfo = d.dragInfo;
                 if (layout != null) {
                     layout.calculateSpans(itemInfo);
                     showOutOfSpaceMessage =
diff --git a/src/com/android/launcher3/model/PackageItemInfo.java b/src/com/android/launcher3/model/PackageItemInfo.java
index 30f228c..ddc9cbf 100644
--- a/src/com/android/launcher3/model/PackageItemInfo.java
+++ b/src/com/android/launcher3/model/PackageItemInfo.java
@@ -20,8 +20,6 @@
 
 import com.android.launcher3.ItemInfo;
 
-import java.util.Arrays;
-
 /**
  * Represents a {@link Package} in the widget tray section.
  */
@@ -59,7 +57,6 @@
         return "PackageItemInfo(title=" + title + " id=" + this.id
                 + " type=" + this.itemType + " container=" + this.container
                 + " screen=" + screenId + " cellX=" + cellX + " cellY=" + cellY
-                + " spanX=" + spanX + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos)
-                + " user=" + user + ")";
+                + " spanX=" + spanX + " spanY=" + spanY + " user=" + user + ")";
     }
 }
diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
index 30b3d58..bdd117c 100644
--- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java
+++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
@@ -13,6 +13,7 @@
 import com.android.launcher3.DragController.DragListener;
 import com.android.launcher3.DragLayer;
 import com.android.launcher3.DragSource;
+import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.compat.AppWidgetManagerCompat;
@@ -43,7 +44,7 @@
     }
 
     @Override
-    public void onDragStart(DragSource source, Object info, int dragAction) { }
+    public void onDragStart(DragSource source, ItemInfo info, int dragAction) { }
 
     @Override
     public void onDragEnd() {
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index 5afd7c4..0f43a34 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -317,7 +317,7 @@
                 int currentScreen = mLauncher.getCurrentWorkspaceScreen();
                 Workspace workspace = (Workspace) target;
                 CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen);
-                ItemInfo itemInfo = (ItemInfo) d.dragInfo;
+                ItemInfo itemInfo = d.dragInfo;
                 if (layout != null) {
                     layout.calculateSpans(itemInfo);
                     showOutOfSpaceMessage =