Some drag and drop code refactor:
am: 94b510cc68

Change-Id: I2e6e8eaf8c972a6261ec54c322753a1c76f8bc95
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 0f6073e..2dde7ca 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -43,6 +43,7 @@
 
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.util.Thunk;
 
@@ -199,8 +200,8 @@
     }
 
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
-        mActive = supportsDrop(source, info);
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+        mActive = supportsDrop(dragObject.dragSource, dragObject.dragInfo);
         mDrawable.setColorFilter(null);
         if (mCurrentColorAnim != null) {
             mCurrentColorAnim.cancel();
@@ -209,6 +210,9 @@
         setTextColor(mOriginalTextColor);
         (mHideParentOnDisable ? ((ViewGroup) getParent()) : this)
                 .setVisibility(mActive ? View.VISIBLE : View.GONE);
+
+        mAccessibleDrag = options.isAccessibleDrag;
+        setOnClickListener(mAccessibleDrag ? this : null);
     }
 
     @Override
@@ -227,6 +231,7 @@
     @Override
     public void onDragEnd() {
         mActive = false;
+        setOnClickListener(null);
     }
 
     /**
@@ -308,11 +313,6 @@
         return to;
     }
 
-    public void enableAccessibleDrag(boolean enable) {
-        mAccessibleDrag = enable;
-        setOnClickListener(enable ? this : null);
-    }
-
     @Override
     public void onClick(View v) {
         mLauncher.getAccessibilityDelegate().handleAccessibleDrop(this, null, null);
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index f24e00b..705f841 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -25,6 +25,7 @@
 import android.view.animation.AnimationUtils;
 
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.util.FlingAnimation;
 import com.android.launcher3.util.Thunk;
@@ -49,9 +50,9 @@
     }
 
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
-        super.onDragStart(source, info, dragAction);
-        setTextBasedOnDragSource(source);
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+        super.onDragStart(dragObject, options);
+        setTextBasedOnDragSource(dragObject.dragSource);
     }
 
     /** @return true for items that should have a "Remove" action in accessibility. */
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 5966af5..42bab47 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -27,6 +27,7 @@
 import android.widget.LinearLayout;
 
 import com.android.launcher3.dragndrop.DragController;
+import com.android.launcher3.dragndrop.DragOptions;
 
 /*
  * The top bar containing various drop targets: Delete/App Info/Uninstall.
@@ -120,17 +121,11 @@
         }
     }
 
-    public void enableAccessibleDrag(boolean enable) {
-        mDeleteDropTarget.enableAccessibleDrag(enable);
-        mAppInfoDropTarget.enableAccessibleDrag(enable);
-        mUninstallDropTarget.enableAccessibleDrag(enable);
-    }
-
     /*
      * DragController.DragListener implementation
      */
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
         animateToVisibility(true);
     }
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index c919db8..7bcd631 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -102,6 +102,7 @@
 import com.android.launcher3.config.ProviderConfig;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.dynamicui.ExtractedColors;
 import com.android.launcher3.folder.Folder;
@@ -3222,7 +3223,7 @@
                                         longClickCellInfo.cellX, longClickCellInfo.cellY));
                 if (!(itemUnderLongClick instanceof Folder || isAllAppsButton)) {
                     // User long pressed on an item
-                    mWorkspace.startDrag(longClickCellInfo);
+                    mWorkspace.startDrag(longClickCellInfo, new DragOptions());
                 }
             }
         }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 66745ab..947aa50 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -59,7 +59,7 @@
 import com.android.launcher3.Launcher.CustomContentCallbacks;
 import com.android.launcher3.Launcher.LauncherOverlay;
 import com.android.launcher3.UninstallDropTarget.DropTargetSource;
-import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource;
+import com.android.launcher3.accessibility.AccessibileDragListenerAdapter;
 import com.android.launcher3.accessibility.OverviewAccessibilityDelegate;
 import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
 import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
@@ -69,6 +69,7 @@
 import com.android.launcher3.config.ProviderConfig;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.dragndrop.DragScroller;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.dragndrop.SpringLoadedDragController;
@@ -100,7 +101,7 @@
 public class Workspace extends PagedView
         implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
         DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener,
-        Insettable, DropTargetSource, AccessibilityDragSource {
+        Insettable, DropTargetSource {
     private static final String TAG = "Launcher.Workspace";
 
     private static boolean ENFORCE_DRAG_EVENT_ORDER = false;
@@ -134,7 +135,6 @@
 
     @Thunk Runnable mRemoveEmptyScreenRunnable;
     @Thunk boolean mDeferRemoveExtraEmptyScreen = false;
-    @Thunk boolean mAddNewPageOnDrag = true;
 
     /**
      * CellInfo for the cell that is currently being dragged
@@ -409,7 +409,7 @@
     }
 
     @Override
-    public void onDragStart(final DragSource source, ItemInfo info, int dragAction) {
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
         if (ENFORCE_DRAG_EVENT_ORDER) {
             enfoceDragParity("onDragStart", 0, 0);
         }
@@ -426,11 +426,19 @@
         // Prevent any Un/InstallShortcutReceivers from updating the db while we are dragging
         InstallShortcutReceiver.enableInstallQueue();
 
-        if (mAddNewPageOnDrag) {
+        // Do not add a new page if it is a accessible drag which was not started by the workspace.
+        // We do not support accessibility drag from other sources and instead provide a direct
+        // action for move/add to homescreen.
+        // When a accessible drag is started by the folder, we only allow rearranging withing the
+        // folder.
+        boolean addNewPage = !(options.isAccessibleDrag && dragObject.dragSource != this);
+
+        if (addNewPage) {
             mDeferRemoveExtraEmptyScreen = false;
             addExtraEmptyScreenOnDrag();
 
-            if (source != this && info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
+            if (dragObject.dragInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+                    && dragObject.dragSource != this) {
                 // When dragging a widget from different source, move to a page which has
                 // enough space to place this widget (after rearranging/resizing). We special case
                 // widgets as they cannot be placed inside a folder.
@@ -439,7 +447,7 @@
                 int currentPage = getPageNearestToCenterOfScreen();
                 for (int pageIndex = currentPage; pageIndex < getPageCount(); pageIndex++) {
                     CellLayout page = (CellLayout) getPageAt(pageIndex);
-                    if (page.hasReorderSolution(info)) {
+                    if (page.hasReorderSolution(dragObject.dragInfo)) {
                         setCurrentPage(pageIndex);
                         break;
                     }
@@ -453,10 +461,6 @@
         }
     }
 
-    public void setAddNewPageOnDrag(boolean addPage) {
-        mAddNewPageOnDrag = addPage;
-    }
-
     public void deferRemoveExtraEmptyScreen() {
         mDeferRemoveExtraEmptyScreen = true;
     }
@@ -1722,26 +1726,6 @@
         }
     }
 
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    @Override
-    public void enableAccessibleDrag(boolean enable) {
-        for (int i = 0; i < getChildCount(); i++) {
-            CellLayout child = (CellLayout) getChildAt(i);
-            child.enableAccessibleDrag(enable, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
-        }
-
-        if (enable) {
-            // We need to allow our individual children to become click handlers in this case
-            setOnClickListener(null);
-        } else {
-            // Reset our click listener
-            setOnClickListener(mLauncher);
-        }
-        mLauncher.getDropTargetBar().enableAccessibleDrag(enable);
-        mLauncher.getHotseat().getLayout()
-            .enableAccessibleDrag(enable, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
-    }
-
     public boolean hasCustomContent() {
         return (mScreenOrder.size() > 0 && mScreenOrder.get(0) == CUSTOM_CONTENT_SCREEN_ID);
     }
@@ -2280,12 +2264,7 @@
         return null;
     }
 
-    public void startDrag(CellLayout.CellInfo cellInfo) {
-        startDrag(cellInfo, false);
-    }
-
-    @Override
-    public void startDrag(CellLayout.CellInfo cellInfo, boolean accessible) {
+    public void startDrag(CellLayout.CellInfo cellInfo, DragOptions options) {
         View child = cellInfo.cell;
 
         // Make sure the drag was started by a long press as opposed to a long click.
@@ -2298,10 +2277,25 @@
         CellLayout layout = (CellLayout) child.getParent().getParent();
         layout.prepareChildForDrag(child);
 
-        beginDragShared(child, this, accessible);
+        if (options.isAccessibleDrag) {
+            mDragController.addDragListener(new AccessibileDragListenerAdapter(
+                    this, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG) {
+                @Override
+                protected void enableAccessibleDrag(boolean enable) {
+                    super.enableAccessibleDrag(enable);
+                    setEnableForLayout(mLauncher.getHotseat().getLayout(),enable);
+
+                    // We need to allow our individual children to become click handlers in this
+                    // case, so temporarily unset the click handlers.
+                    setOnClickListener(enable ? null : mLauncher);
+                }
+            });
+        }
+
+        beginDragShared(child, this, options);
     }
 
-    public void beginDragShared(View child, DragSource source, boolean accessible) {
+    public void beginDragShared(View child, DragSource source, DragOptions options) {
         Object dragObject = child.getTag();
         if (!(dragObject instanceof ItemInfo)) {
             String msg = "Drag started with a view that has no tag set. This "
@@ -2309,13 +2303,13 @@
                     + "View: " + child + "  tag: " + child.getTag();
             throw new IllegalStateException(msg);
         }
-        beginDragShared(child, source, accessible, (ItemInfo) dragObject,
-                new DragPreviewProvider(child));
+        beginDragShared(child, source, (ItemInfo) dragObject,
+                new DragPreviewProvider(child), options);
     }
 
 
-    public DragView beginDragShared(View child, DragSource source, boolean accessible,
-            ItemInfo dragObject, DragPreviewProvider previewProvider) {
+    public DragView beginDragShared(View child, DragSource source, ItemInfo dragObject,
+            DragPreviewProvider previewProvider, DragOptions dragOptions) {
         child.clearFocus();
         child.setPressed(false);
         mOutlineProvider = previewProvider;
@@ -2359,8 +2353,7 @@
         }
 
         DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source,
-                dragObject, DragController.DRAG_ACTION_MOVE, dragVisualizeOffset,
-                dragRect, scale, accessible);
+                dragObject, dragVisualizeOffset, dragRect, scale, dragOptions);
         dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor());
         b.recycle();
         return dv;
diff --git a/src/com/android/launcher3/accessibility/AccessibileDragListenerAdapter.java b/src/com/android/launcher3/accessibility/AccessibileDragListenerAdapter.java
new file mode 100644
index 0000000..62a9a6d
--- /dev/null
+++ b/src/com/android/launcher3/accessibility/AccessibileDragListenerAdapter.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.accessibility;
+
+import android.view.ViewGroup;
+
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.dragndrop.DragController.DragListener;
+import com.android.launcher3.dragndrop.DragOptions;
+
+/**
+ * Utility listener to enable/disable accessibility drag flags for a ViewGroup
+ * containing CellLayouts
+ */
+public class AccessibileDragListenerAdapter implements DragListener {
+
+    private final ViewGroup mViewGroup;
+    private final int mDragType;
+
+    /**
+     * @param parent
+     * @param dragType either {@link CellLayout#WORKSPACE_ACCESSIBILITY_DRAG} or
+     *                 {@link CellLayout#FOLDER_ACCESSIBILITY_DRAG}
+     */
+    public AccessibileDragListenerAdapter(ViewGroup parent, int dragType) {
+        mViewGroup = parent;
+        mDragType = dragType;
+    }
+
+    @Override
+    public void onDragStart(DragObject dragObject, DragOptions options) {
+        enableAccessibleDrag(true);
+    }
+
+    @Override
+    public void onDragEnd() {
+        enableAccessibleDrag(false);
+        Launcher.getLauncher(mViewGroup.getContext()).getDragController().removeDragListener(this);
+    }
+
+    protected void enableAccessibleDrag(boolean enable) {
+        for (int i = 0; i < mViewGroup.getChildCount(); i++) {
+            setEnableForLayout((CellLayout) mViewGroup.getChildAt(i), enable);
+        }
+    }
+
+    protected final void setEnableForLayout(CellLayout layout, boolean enable) {
+        layout.enableAccessibleDrag(enable, mDragType);
+    }
+}
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 0562cf5..173aad0 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -22,6 +22,8 @@
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.DeleteDropTarget;
 import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.FolderInfo;
 import com.android.launcher3.InfoDropTarget;
@@ -73,7 +75,6 @@
     @Thunk final Launcher mLauncher;
 
     private DragInfo mDragInfo = null;
-    private AccessibilityDragSource mDragSource = null;
 
     public LauncherAccessibilityDelegate(Launcher launcher) {
         mLauncher = launcher;
@@ -372,26 +373,25 @@
 
         Folder folder = workspace.getOpenFolder();
         if (folder != null) {
-            if (folder.getItemsInReadingOrder().contains(item)) {
-                mDragSource = folder;
-            } else {
+            if (!folder.getItemsInReadingOrder().contains(item)) {
                 mLauncher.closeFolder();
+                folder = null;
             }
         }
-        if (mDragSource == null) {
-            mDragSource = workspace;
-        }
-        mDragSource.enableAccessibleDrag(true);
-        mDragSource.startDrag(cellInfo, true);
 
-        if (mLauncher.getDragController().isDragging()) {
-            mLauncher.getDragController().addDragListener(this);
+        mLauncher.getDragController().addDragListener(this);
+
+        DragOptions options = new DragOptions();
+        options.isAccessibleDrag = true;
+        if (folder != null) {
+            folder.startDrag(cellInfo.cell, options);
+        } else {
+            workspace.startDrag(cellInfo, options);
         }
     }
 
-
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
+    public void onDragStart(DragObject dragObject, DragOptions options) {
         // No-op
     }
 
@@ -399,16 +399,6 @@
     public void onDragEnd() {
         mLauncher.getDragController().removeDragListener(this);
         mDragInfo = null;
-        if (mDragSource != null) {
-            mDragSource.enableAccessibleDrag(false);
-            mDragSource = null;
-        }
-    }
-
-    public static interface AccessibilityDragSource {
-        void startDrag(CellLayout.CellInfo cellInfo, boolean accessible);
-
-        void enableAccessibleDrag(boolean enable);
     }
 
     /**
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index a8e2140..a3786fa 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -48,6 +48,7 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.graphics.TintedDrawableSpan;
 import com.android.launcher3.keyboard.FocusedItemDecorator;
@@ -539,7 +540,7 @@
         if (!mLauncher.isDraggingEnabled()) return false;
 
         // Start the drag
-        mLauncher.getWorkspace().beginDragShared(v, this, false);
+        mLauncher.getWorkspace().beginDragShared(v, this, new DragOptions());
         // Enter spring loaded mode
         mLauncher.enterSpringLoadedDragMode();
 
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index b57f5bf..b67d3b8 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -57,12 +57,6 @@
 public class DragController implements DragDriver.EventListener, TouchController {
     private static final String TAG = "Launcher.DragController";
 
-    /** Indicates the drag is a move.  */
-    public static int DRAG_ACTION_MOVE = 0;
-
-    /** Indicates the drag is a copy.  */
-    public static int DRAG_ACTION_COPY = 1;
-
     public static final int SCROLL_DELAY = 500;
     public static final int RESCROLL_DELAY = PagedView.PAGE_SNAP_ANIMATION_DURATION + 150;
 
@@ -91,8 +85,8 @@
      */
     private DragDriver mDragDriver = null;
 
-    /** Whether or not an accessible drag operation is in progress. */
-    private boolean mIsAccessibleDrag;
+    /** Options controlling the drag behavior. */
+    private DragOptions mOptions;
 
     /** X coordinate of the down event. */
     private int mMotionDownX;
@@ -145,12 +139,10 @@
         /**
          * A drag has begun
          *
-         * @param source An object representing where the drag originated
-         * @param info The data associated with the object that is being dragged
-         * @param dragAction The drag action: either {@link DragController#DRAG_ACTION_MOVE}
-         *        or {@link DragController#DRAG_ACTION_COPY}
+         * @param dragObject The object being dragged
+         * @param options Options used to start the drag
          */
-        void onDragStart(DragSource source, ItemInfo info, int dragAction);
+        void onDragStart(DropTarget.DragObject dragObject, DragOptions options);
 
         /**
          * The drag has ended
@@ -160,8 +152,6 @@
 
     /**
      * Used to create a new DragLayer from XML.
-     *
-     * @param context The application's context.
      */
     public DragController(Launcher launcher) {
         Resources r = launcher.getResources();
@@ -183,11 +173,9 @@
      * @param source An object representing where the drag originated
      * @param dragInfo The data associated with the object that is being dragged
      * @param viewImageBounds the position of the image inside the view
-     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
-     *        {@link #DRAG_ACTION_COPY}
      */
     public void startDrag(View v, Bitmap bmp, DragSource source, ItemInfo dragInfo,
-            Rect viewImageBounds, int dragAction, float initialDragViewScale) {
+            Rect viewImageBounds, float initialDragViewScale, DragOptions options) {
         int[] loc = mCoordinatesTemp;
         mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
         int dragLayerX = loc[0] + viewImageBounds.left
@@ -195,12 +183,8 @@
         int dragLayerY = loc[1] + viewImageBounds.top
                 + (int) ((initialDragViewScale * bmp.getHeight() - bmp.getHeight()) / 2);
 
-        startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, null,
-                null, initialDragViewScale, false);
-
-        if (dragAction == DRAG_ACTION_MOVE) {
-            v.setVisibility(View.GONE);
-        }
+        startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, null,
+                null, initialDragViewScale, options);
     }
 
     /**
@@ -212,15 +196,12 @@
      * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
      * @param source An object representing where the drag originated
      * @param dragInfo The data associated with the object that is being dragged
-     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
-     *        {@link #DRAG_ACTION_COPY}
      * @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
-     * @param accessible whether this drag should occur in accessibility mode
      */
     public DragView startDrag(Bitmap b, int dragLayerX, int dragLayerY,
-            DragSource source, ItemInfo dragInfo, int dragAction, Point dragOffset, Rect dragRegion,
-            float initialDragViewScale, boolean accessible) {
+            DragSource source, ItemInfo dragInfo, Point dragOffset, Rect dragRegion,
+            float initialDragViewScale, DragOptions options) {
         if (PROFILE_DRAWING_DURING_DRAG) {
             android.os.Debug.startMethodTracing("Launcher");
         }
@@ -232,19 +213,15 @@
         }
         mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0);
 
-        for (DragListener listener : mListeners) {
-            listener.onDragStart(source, dragInfo, dragAction);
-        }
-
         final int registrationX = mMotionDownX - dragLayerX;
         final int registrationY = mMotionDownY - dragLayerY;
 
         final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
         final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
 
-        mIsAccessibleDrag = accessible;
         mLastDropTarget = null;
 
+        mOptions = options;
         mDragObject = new DropTarget.DragObject();
 
         final Resources res = mLauncher.getResources();
@@ -254,7 +231,7 @@
                 registrationY, initialDragViewScale, scaleDps);
 
         mDragObject.dragComplete = false;
-        if (mIsAccessibleDrag) {
+        if (mOptions.isAccessibleDrag) {
             // For an accessible drag, we assume the view is being dragged from the center.
             mDragObject.xOffset = b.getWidth() / 2;
             mDragObject.yOffset = b.getHeight() / 2;
@@ -282,6 +259,11 @@
         mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
         dragView.show(mMotionDownX, mMotionDownY);
         mDistanceSinceScroll = 0;
+
+        for (DragListener listener : mListeners) {
+            listener.onDragStart(mDragObject, mOptions);
+        }
+
         mLastTouch[0] = mMotionDownX;
         mLastTouch[1] = mMotionDownY;
         handleMoveEvent(mMotionDownX, mMotionDownY);
@@ -308,7 +290,7 @@
     }
 
     public boolean isDragging() {
-        return mDragDriver != null || mIsAccessibleDrag;
+        return mDragDriver != null || (mOptions != null && mOptions.isAccessibleDrag);
     }
 
     /**
@@ -343,7 +325,7 @@
     private void endDrag() {
         if (isDragging()) {
             mDragDriver = null;
-            mIsAccessibleDrag = false;
+            mOptions = null;
             clearScrollRunnable();
             boolean isDeferred = false;
             if (mDragObject.dragView != null) {
@@ -422,10 +404,6 @@
 
     @Override
     public void onDriverDragEnd(float x, float y, DropTarget dropTargetOverride) {
-        final int[] dragLayerPos = getClampedDragLayerPos(x, y);
-        final int dragLayerX = dragLayerPos[0];
-        final int dragLayerY = dragLayerPos[1];
-
         DropTarget dropTarget;
         PointF vec = null;
 
@@ -454,14 +432,7 @@
      * Call this from a drag source view.
      */
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        @SuppressWarnings("all") // suppress dead code warning
-        final boolean debug = false;
-        if (debug) {
-            Log.d(Launcher.TAG, "DragController.onInterceptTouchEvent " + ev + " Dragging="
-                    + (mDragDriver != null));
-        }
-
-        if (mIsAccessibleDrag) {
+        if (mOptions != null && mOptions.isAccessibleDrag) {
             return false;
         }
 
@@ -604,7 +575,7 @@
      * Call this from a drag source view.
      */
     public boolean onTouchEvent(MotionEvent ev) {
-        if (mDragDriver == null || mIsAccessibleDrag) {
+        if (mDragDriver == null || mOptions == null || mOptions.isAccessibleDrag) {
             return false;
         }
 
diff --git a/src/com/android/launcher3/dragndrop/DragOptions.java b/src/com/android/launcher3/dragndrop/DragOptions.java
new file mode 100644
index 0000000..a7f2872
--- /dev/null
+++ b/src/com/android/launcher3/dragndrop/DragOptions.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.dragndrop;
+
+/**
+ * Set of options to control the drag and drop behavior.
+ */
+public class DragOptions {
+
+    /** Whether or not an accessible drag operation is in progress. */
+    public boolean isAccessibleDrag = false;
+}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 5450423..1e87202 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -71,11 +71,12 @@
 import com.android.launcher3.UninstallDropTarget.DropTargetSource;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace.ItemOperator;
-import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource;
+import com.android.launcher3.accessibility.AccessibileDragListenerAdapter;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragController.DragListener;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.logging.UserEventDispatcher.LaunchSourceProvider;
 import com.android.launcher3.pageindicators.PageIndicatorDots;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -92,7 +93,7 @@
  */
 public class Folder extends LinearLayout implements DragSource, View.OnClickListener,
         View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
-        View.OnFocusChangeListener, DragListener, DropTargetSource, AccessibilityDragSource {
+        View.OnFocusChangeListener, DragListener, DropTargetSource {
     private static final String TAG = "Launcher.Folder";
 
     /**
@@ -282,10 +283,10 @@
     public boolean onLongClick(View v) {
         // Return if global dragging is not enabled
         if (!mLauncher.isDraggingEnabled()) return true;
-        return beginDrag(v, false);
+        return startDrag(v, new DragOptions());
     }
 
-    private boolean beginDrag(View v, boolean accessible) {
+    public boolean startDrag(View v, DragOptions options) {
         Object tag = v.getTag();
         if (tag instanceof ShortcutInfo) {
             ShortcutInfo item = (ShortcutInfo) tag;
@@ -293,35 +294,48 @@
                 return false;
             }
 
-            mLauncher.getWorkspace().beginDragShared(v, this, accessible);
-
             mCurrentDragInfo = item;
             mEmptyCellRank = item.rank;
             mCurrentDragView = v;
 
-            mContent.removeItem(mCurrentDragView);
-            mInfo.remove(mCurrentDragInfo, true);
-            mDragInProgress = true;
-            mItemAddedBackToSelfViaIcon = false;
+            mDragController.addDragListener(this);
+            if (options.isAccessibleDrag) {
+                mDragController.addDragListener(new AccessibileDragListenerAdapter(
+                        mContent, CellLayout.FOLDER_ACCESSIBILITY_DRAG) {
+
+                    @Override
+                    protected void enableAccessibleDrag(boolean enable) {
+                        super.enableAccessibleDrag(enable);
+                        mFooter.setImportantForAccessibility(enable
+                                ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+                                : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+                    }
+                });
+            }
+
+            mLauncher.getWorkspace().beginDragShared(v, this, options);
         }
         return true;
     }
 
     @Override
-    public void startDrag(CellInfo cellInfo, boolean accessible) {
-        beginDrag(cellInfo.cell, accessible);
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+        if (dragObject.dragSource != this) {
+            return;
+        }
+
+        mContent.removeItem(mCurrentDragView);
+        mInfo.remove(mCurrentDragInfo, true);
+        mDragInProgress = true;
+        mItemAddedBackToSelfViaIcon = false;
     }
 
     @Override
-    public void enableAccessibleDrag(boolean enable) {
-        mLauncher.getDropTargetBar().enableAccessibleDrag(enable);
-        for (int i = 0; i < mContent.getChildCount(); i++) {
-            mContent.getPageAt(i).enableAccessibleDrag(enable, CellLayout.FOLDER_ACCESSIBILITY_DRAG);
+    public void onDragEnd() {
+        if (mIsExternalDrag && mDragInProgress) {
+            completeDragExit();
         }
-
-        mFooter.setImportantForAccessibility(enable ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS :
-                IMPORTANT_FOR_ACCESSIBILITY_AUTO);
-        mLauncher.getWorkspace().setAddNewPageOnDrag(!enable);
+        mDragController.removeDragListener(this);
     }
 
     public boolean isEditingName() {
@@ -661,17 +675,6 @@
         mDragController.addDragListener(this);
     }
 
-    @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) { }
-
-    @Override
-    public void onDragEnd() {
-        if (mIsExternalDrag && mDragInProgress) {
-            completeDragExit();
-        }
-        mDragController.removeDragListener(this);
-    }
-
     @Thunk void sendCustomAccessibilityEvent(int type, String text) {
         AccessibilityManager accessibilityManager = (AccessibilityManager)
                 getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
index 0ff13a7..4100795 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
@@ -62,6 +62,7 @@
 import com.android.launcher3.compat.UserHandleCompat;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.graphics.TriangleShape;
 import com.android.launcher3.logging.UserEventDispatcher;
@@ -515,8 +516,8 @@
         mIconShift.y = mIconLastTouchPos.y - mLauncher.getDeviceProfile().iconSizePx;
 
         DragView dv = mLauncher.getWorkspace().beginDragShared(
-                sv.getBubbleText(), this, false, sv.getFinalInfo(),
-                new ShortcutDragPreviewProvider(sv.getIconView(), mIconShift));
+                sv.getBubbleText(), this, sv.getFinalInfo(),
+                new ShortcutDragPreviewProvider(sv.getIconView(), mIconShift), new DragOptions());
         dv.animateShift(-mIconShift.x, -mIconShift.y);
 
         // TODO: support dragging from within folder without having to close it
@@ -560,7 +561,7 @@
     }
 
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
         // Either the original icon or one of the shortcuts was dragged.
         // Hide the container, but don't remove it yet because that interferes with touch events.
         animateClose();
diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
index 297505b..049871f 100644
--- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java
+++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
@@ -11,6 +11,7 @@
 
 import com.android.launcher3.AppWidgetResizeFrame;
 import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
@@ -18,6 +19,7 @@
 import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.util.Thunk;
 
 public class WidgetHostViewLoader implements DragController.DragListener {
@@ -47,7 +49,7 @@
     }
 
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) { }
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) { }
 
     @Override
     public void onDragEnd() {
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index 4b2be18..70b2945 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -33,6 +33,7 @@
 import com.android.launcher3.DeleteDropTarget;
 import com.android.launcher3.DragSource;
 import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.IconCache;
 import com.android.launcher3.ItemInfo;
@@ -251,7 +252,7 @@
 
         // Start the drag
         mDragController.startDrag(image, preview, this, createItemInfo,
-                bounds, DragController.DRAG_ACTION_COPY, scale);
+                bounds, scale, new DragOptions());
         return true;
     }