Decoupling some drag and drop code handling

> Removing some special checks around accessibility drag
> Unifying folder alarm code path for accessible and normal DnD
> Maintaining mDragStartTime inside the dragDriver instead of the callers
> Simplifying some accessibility callbacks

Future cl will create a Accessibility DragDriver and unify it with
other DnD flow

Change-Id: I1919ef218de0174678110f271b450bcb9aaf4a5c
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 2b0da43..34d7067 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -155,7 +155,7 @@
 
     @Override
     public final void onDragEnter(DragObject d) {
-        if (!d.accessibleDrag && !mTextVisible) {
+        if (!mAccessibleDrag && !mTextVisible) {
             // Show tooltip
             hideTooltip();
 
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index e3eb387..4742bbc 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -53,8 +53,6 @@
 
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
-import com.android.launcher3.accessibility.FolderAccessibilityHelper;
-import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PropertyListBuilder;
 import com.android.launcher3.config.FeatureFlags;
@@ -79,9 +77,6 @@
 import java.util.Stack;
 
 public class CellLayout extends ViewGroup implements Transposable {
-    public static final int WORKSPACE_ACCESSIBILITY_DRAG = 2;
-    public static final int FOLDER_ACCESSIBILITY_DRAG = 1;
-
     private static final String TAG = "CellLayout";
     private static final boolean LOGD = false;
 
@@ -182,7 +177,6 @@
     private static final Paint sPaint = new Paint();
 
     // Related to accessible drag and drop
-    private DragAndDropAccessibilityDelegate mTouchHelper;
     private boolean mUseTouchHelper = false;
     private RotationMode mRotationMode = RotationMode.NORMAL;
 
@@ -292,26 +286,20 @@
         addView(mShortcutsAndWidgets);
     }
 
-    public void enableAccessibleDrag(boolean enable, int dragType) {
-        mUseTouchHelper = enable;
-        if (!enable) {
-            ViewCompat.setAccessibilityDelegate(this, null);
-            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
-            getShortcutsAndWidgets().setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
-            setOnClickListener(null);
-        } else {
-            if (dragType == WORKSPACE_ACCESSIBILITY_DRAG &&
-                    !(mTouchHelper instanceof WorkspaceAccessibilityHelper)) {
-                mTouchHelper = new WorkspaceAccessibilityHelper(this);
-            } else if (dragType == FOLDER_ACCESSIBILITY_DRAG &&
-                    !(mTouchHelper instanceof FolderAccessibilityHelper)) {
-                mTouchHelper = new FolderAccessibilityHelper(this);
-            }
-            ViewCompat.setAccessibilityDelegate(this, mTouchHelper);
-            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
-            getShortcutsAndWidgets().setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
-            setOnClickListener(mTouchHelper);
-        }
+
+    /**
+     * Sets or clears a delegate used for accessible drag and drop
+     */
+    public void setDragAndDropAccessibilityDelegate(DragAndDropAccessibilityDelegate delegate) {
+        setOnClickListener(delegate);
+        setOnHoverListener(delegate);
+        ViewCompat.setAccessibilityDelegate(this, delegate);
+
+        mUseTouchHelper = delegate != null;
+        int accessibilityFlag = mUseTouchHelper
+                ? IMPORTANT_FOR_ACCESSIBILITY_YES : IMPORTANT_FOR_ACCESSIBILITY_NO;
+        setImportantForAccessibility(accessibilityFlag);
+        getShortcutsAndWidgets().setImportantForAccessibility(accessibilityFlag);
 
         // Invalidate the accessibility hierarchy
         if (getParent() != null) {
@@ -339,15 +327,6 @@
     }
 
     @Override
-    public boolean dispatchHoverEvent(MotionEvent event) {
-        // Always attempt to dispatch hover events to accessibility first.
-        if (mUseTouchHelper && mTouchHelper.dispatchHoverEvent(event)) {
-            return true;
-        }
-        return super.dispatchHoverEvent(event);
-    }
-
-    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (mUseTouchHelper ||
                 (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev))) {
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index a32fd12..c03011b 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -59,9 +59,6 @@
         /** Where the drag originated */
         public DragSource dragSource = null;
 
-        /** The object is part of an accessible drag operation */
-        public boolean accessibleDrag;
-
         /** Indicates that the drag operation was cancelled */
         public boolean cancelled = false;
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1413a5c..1dd2e41 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -339,6 +339,8 @@
                 }
             };
 
+    private long mLastTouchUpTime = -1;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         Object traceToken = TraceHelper.INSTANCE.beginSection(ON_CREATE_EVT,
@@ -1115,7 +1117,7 @@
 
         super.onPause();
         mDragController.cancelDrag();
-        mDragController.resetLastGestureUpTime();
+        mLastTouchUpTime = -1;
         mDropTargetBar.animateToVisibility(false);
 
         if (!mDeferOverlayCallbacks) {
@@ -1838,6 +1840,9 @@
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_UP) {
+            mLastTouchUpTime = System.currentTimeMillis();
+        }
         TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
         return super.dispatchTouchEvent(ev);
     }
@@ -2465,8 +2470,12 @@
     }
 
     private boolean canRunNewAppsAnimation() {
-        long diff = System.currentTimeMillis() - mDragController.getLastGestureUpTime();
-        return diff > (NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS * 1000);
+        if (mDragController.isDragging()) {
+            return false;
+        } else {
+            return (System.currentTimeMillis() - mLastTouchUpTime)
+                    > (NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS * 1000);
+        }
     }
 
     private ValueAnimator createNewAppBounceAnimation(View v, int i) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index ead6018..46493b7 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -192,10 +192,7 @@
     final WallpaperOffsetInterpolator mWallpaperOffset;
     private boolean mUnlockWallpaperFromDefaultPageOnLayout;
 
-    // Variables relating to the creation of user folders by hovering shortcuts over shortcuts
-    private static final int FOLDER_CREATION_TIMEOUT = 0;
     public static final int REORDER_TIMEOUT = 650;
-    private final Alarm mFolderCreationAlarm = new Alarm();
     private final Alarm mReorderAlarm = new Alarm();
     private PreviewBackground mFolderCreateBg;
     private FolderIcon mDragOverFolderIcon = null;
@@ -567,11 +564,6 @@
         addView(newScreen, insertIndex);
         mStateTransitionAnimation.applyChildState(
                 mLauncher.getStateManager().getState(), newScreen, insertIndex);
-
-        if (mLauncher.getAccessibilityDelegate().isInAccessibleDrag()) {
-            newScreen.enableAccessibleDrag(true, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
-        }
-
         return newScreen;
     }
 
@@ -818,11 +810,6 @@
                 if (indexOfChild(cl) < currentPage) {
                     pageShift++;
                 }
-
-                if (isInAccessibleDrag) {
-                    cl.enableAccessibleDrag(false, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
-                }
-
                 removeView(cl);
             } else {
                 // if this is the last screen, convert it to the empty screen
@@ -1444,14 +1431,14 @@
         child.setVisibility(INVISIBLE);
 
         if (options.isAccessibleDrag) {
-            mDragController.addDragListener(new AccessibleDragListenerAdapter(
-                    this, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG) {
-                @Override
-                protected void enableAccessibleDrag(boolean enable) {
-                    super.enableAccessibleDrag(enable);
-                    setEnableForLayout(mLauncher.getHotseat(),enable);
-                }
-            });
+            mDragController.addDragListener(
+                    new AccessibleDragListenerAdapter(this, WorkspaceAccessibilityHelper::new) {
+                        @Override
+                        protected void enableAccessibleDrag(boolean enable) {
+                            super.enableAccessibleDrag(enable);
+                            setEnableForLayout(mLauncher.getHotseat(), enable);
+                        }
+                    });
         }
 
         beginDragShared(child, this, options);
@@ -1883,12 +1870,10 @@
                         final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
                         AppWidgetProviderInfo pInfo = hostView.getAppWidgetInfo();
                         if (pInfo != null && pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE
-                                && !d.accessibleDrag) {
-                            onCompleteRunnable = new Runnable() {
-                                public void run() {
-                                    if (!isPageInTransition()) {
-                                        AppWidgetResizeFrame.showForWidget(hostView, cellLayout);
-                                    }
+                                && !options.isAccessibleDrag) {
+                            onCompleteRunnable = () -> {
+                                if (!isPageInTransition()) {
+                                    AppWidgetResizeFrame.showForWidget(hostView, cellLayout);
                                 }
                             };
                         }
@@ -2088,8 +2073,6 @@
         if (mFolderCreateBg != null) {
             mFolderCreateBg.animateToRest();
         }
-        mFolderCreationAlarm.setOnAlarmListener(null);
-        mFolderCreationAlarm.cancelAlarm();
     }
 
     private void cleanupAddToFolder() {
@@ -2196,7 +2179,7 @@
             float targetCellDistance = mDragTargetLayout.getDistanceFromCell(
                     mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell);
 
-            manageFolderFeedback(mDragTargetLayout, mTargetCell, targetCellDistance, d);
+            manageFolderFeedback(targetCellDistance, d);
 
             boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int)
                     mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX,
@@ -2294,8 +2277,7 @@
         return null;
     }
 
-    private void manageFolderFeedback(CellLayout targetLayout,
-            int[] targetCell, float distance, DragObject dragObject) {
+    private void manageFolderFeedback(float distance, DragObject dragObject) {
         if (distance > mMaxDistanceForFolderCreation) {
             if (mDragMode != DRAG_MODE_NONE) {
                 setDragMode(DRAG_MODE_NONE);
@@ -2306,18 +2288,18 @@
         final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
         ItemInfo info = dragObject.dragInfo;
         boolean userFolderPending = willCreateUserFolder(info, dragOverView, false);
-        if (mDragMode == DRAG_MODE_NONE && userFolderPending &&
-                !mFolderCreationAlarm.alarmPending()) {
+        if (mDragMode == DRAG_MODE_NONE && userFolderPending) {
 
-            FolderCreationAlarmListener listener = new
-                    FolderCreationAlarmListener(targetLayout, targetCell[0], targetCell[1]);
+            mFolderCreateBg = new PreviewBackground();
+            mFolderCreateBg.setup(mLauncher, mLauncher, null,
+                    dragOverView.getMeasuredWidth(), dragOverView.getPaddingTop());
 
-            if (!dragObject.accessibleDrag) {
-                mFolderCreationAlarm.setOnAlarmListener(listener);
-                mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
-            } else {
-                listener.onAlarm(mFolderCreationAlarm);
-            }
+            // The full preview background should appear behind the icon
+            mFolderCreateBg.isClipping = false;
+
+            mFolderCreateBg.animateToAccept(mDragTargetLayout, mTargetCell[0], mTargetCell[1]);
+            mDragTargetLayout.clearDragOutlines();
+            setDragMode(DRAG_MODE_CREATE_FOLDER);
 
             if (dragObject.stateAnnouncer != null) {
                 dragObject.stateAnnouncer.announce(WorkspaceAccessibilityHelper
@@ -2330,8 +2312,8 @@
         if (willAddToFolder && mDragMode == DRAG_MODE_NONE) {
             mDragOverFolderIcon = ((FolderIcon) dragOverView);
             mDragOverFolderIcon.onDragEnter(info);
-            if (targetLayout != null) {
-                targetLayout.clearDragOutlines();
+            if (mDragTargetLayout != null) {
+                mDragTargetLayout.clearDragOutlines();
             }
             setDragMode(DRAG_MODE_ADD_TO_FOLDER);
 
@@ -2350,33 +2332,6 @@
         }
     }
 
-    class FolderCreationAlarmListener implements OnAlarmListener {
-        final CellLayout layout;
-        final int cellX;
-        final int cellY;
-
-        final PreviewBackground bg = new PreviewBackground();
-
-        public FolderCreationAlarmListener(CellLayout layout, int cellX, int cellY) {
-            this.layout = layout;
-            this.cellX = cellX;
-            this.cellY = cellY;
-
-            BubbleTextView cell = (BubbleTextView) layout.getChildAt(cellX, cellY);
-            bg.setup(mLauncher, mLauncher, null, cell.getMeasuredWidth(), cell.getPaddingTop());
-
-            // The full preview background should appear behind the icon
-            bg.isClipping = false;
-        }
-
-        public void onAlarm(Alarm alarm) {
-            mFolderCreateBg = bg;
-            mFolderCreateBg.animateToAccept(layout, cellX, cellY);
-            layout.clearDragOutlines();
-            setDragMode(DRAG_MODE_CREATE_FOLDER);
-        }
-    }
-
     class ReorderAlarmListener implements OnAlarmListener {
         final float[] dragViewCenter;
         final int minSpanX, minSpanY, spanX, spanY;
diff --git a/src/com/android/launcher3/accessibility/AccessibleDragListenerAdapter.java b/src/com/android/launcher3/accessibility/AccessibleDragListenerAdapter.java
index f8df5d7..0d7df2b 100644
--- a/src/com/android/launcher3/accessibility/AccessibleDragListenerAdapter.java
+++ b/src/com/android/launcher3/accessibility/AccessibleDragListenerAdapter.java
@@ -16,7 +16,9 @@
 
 package com.android.launcher3.accessibility;
 
+import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewGroup.OnHierarchyChangeListener;
 
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.DropTarget.DragObject;
@@ -24,36 +26,55 @@
 import com.android.launcher3.dragndrop.DragController.DragListener;
 import com.android.launcher3.dragndrop.DragOptions;
 
+import java.util.function.Function;
+
 /**
  * Utility listener to enable/disable accessibility drag flags for a ViewGroup
  * containing CellLayouts
  */
-public class AccessibleDragListenerAdapter implements DragListener {
+public class AccessibleDragListenerAdapter implements DragListener, OnHierarchyChangeListener {
 
     private final ViewGroup mViewGroup;
-    private final int mDragType;
+    private final Function<CellLayout, DragAndDropAccessibilityDelegate> mDelegateFactory;
 
     /**
-     * @param parent
-     * @param dragType either {@link CellLayout#WORKSPACE_ACCESSIBILITY_DRAG} or
-     *                 {@link CellLayout#FOLDER_ACCESSIBILITY_DRAG}
+     * @param parent the viewgroup containing all the children
+     * @param delegateFactory function to create no delegates
      */
-    public AccessibleDragListenerAdapter(ViewGroup parent, int dragType) {
+    public AccessibleDragListenerAdapter(ViewGroup parent,
+            Function<CellLayout, DragAndDropAccessibilityDelegate> delegateFactory) {
         mViewGroup = parent;
-        mDragType = dragType;
+        mDelegateFactory = delegateFactory;
     }
 
     @Override
     public void onDragStart(DragObject dragObject, DragOptions options) {
+        mViewGroup.setOnHierarchyChangeListener(this);
         enableAccessibleDrag(true);
     }
 
     @Override
     public void onDragEnd() {
+        mViewGroup.setOnHierarchyChangeListener(null);
         enableAccessibleDrag(false);
         Launcher.getLauncher(mViewGroup.getContext()).getDragController().removeDragListener(this);
     }
 
+
+    @Override
+    public void onChildViewAdded(View parent, View child) {
+        if (parent == mViewGroup) {
+            setEnableForLayout((CellLayout) child, true);
+        }
+    }
+
+    @Override
+    public void onChildViewRemoved(View parent, View child) {
+        if (parent == mViewGroup) {
+            setEnableForLayout((CellLayout) child, false);
+        }
+    }
+
     protected void enableAccessibleDrag(boolean enable) {
         for (int i = 0; i < mViewGroup.getChildCount(); i++) {
             setEnableForLayout((CellLayout) mViewGroup.getChildAt(i), enable);
@@ -61,6 +82,6 @@
     }
 
     protected final void setEnableForLayout(CellLayout layout, boolean enable) {
-        layout.enableAccessibleDrag(enable, mDragType);
+        layout.setDragAndDropAccessibilityDelegate(enable ? mDelegateFactory.apply(layout) : null);
     }
 }
diff --git a/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java
index 117296d..ddb547f 100644
--- a/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java
@@ -19,24 +19,26 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
+import android.view.View.OnHoverListener;
 import android.view.accessibility.AccessibilityEvent;
 
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
+import androidx.customview.widget.ExploreByTouchHelper;
+
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 
 import java.util.List;
 
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
-import androidx.customview.widget.ExploreByTouchHelper;
-
 /**
  * Helper class to make drag-and-drop in a {@link CellLayout} accessible.
  */
 public abstract class DragAndDropAccessibilityDelegate extends ExploreByTouchHelper
-        implements OnClickListener {
+        implements OnClickListener, OnHoverListener {
     protected static final int INVALID_POSITION = -1;
 
     private static final int[] sTempArray = new int[2];
@@ -123,6 +125,11 @@
         node.setFocusable(true);
     }
 
+    @Override
+    public boolean onHover(View view, MotionEvent motionEvent) {
+        return dispatchHoverEvent(motionEvent);
+    }
+
     protected abstract String getLocationDescriptionForIconDrop(int id);
 
     protected abstract String getConfirmationForIconDrop(int id);
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 0b439ec..6f7f8e6 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -7,6 +7,7 @@
 import android.app.AlertDialog;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.DialogInterface;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -400,11 +401,11 @@
 
         Rect pos = new Rect();
         mLauncher.getDragLayer().getDescendantRectRelativeToSelf(item, pos);
-        mLauncher.getDragController().prepareAccessibleDrag(pos.centerX(), pos.centerY());
         mLauncher.getDragController().addDragListener(this);
 
         DragOptions options = new DragOptions();
         options.isAccessibleDrag = true;
+        options.simulatedDndStartPoint = new Point(pos.centerX(), pos.centerY());
         ItemLongClickListener.beginDrag(item, mLauncher, info, options);
     }
 
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index 75693c6..9b91a1d 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -26,7 +26,6 @@
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.SystemClock;
 import android.util.Log;
 import android.view.DragEvent;
 import android.view.View;
@@ -63,7 +62,6 @@
 
     protected Launcher mLauncher;
     private DragController mDragController;
-    private long mDragStartTime;
 
     public BaseItemDragListener(Rect previewRect, int previewBitmapWidth, int previewViewWidth) {
         mPreviewRect = previewRect;
@@ -102,7 +100,7 @@
                 return false;
             }
         }
-        return mDragController.onDragEvent(mDragStartTime, event);
+        return mDragController.onDragEvent(event);
     }
 
     protected boolean onDragStart(DragEvent event) {
@@ -118,7 +116,7 @@
 
         Point downPos = new Point((int) event.getX(), (int) event.getY());
         DragOptions options = new DragOptions();
-        options.systemDndStartPoint = downPos;
+        options.simulatedDndStartPoint = downPos;
         options.preDragCondition = preDragCondition;
 
         // We use drag event position as the screenPos for the preview image. Since mPreviewRect
@@ -128,7 +126,6 @@
         // to source window.
         createDragHelper().startDrag(new Rect(mPreviewRect),
                 mPreviewBitmapWidth, mPreviewViewWidth, downPos, this, options);
-        mDragStartTime = SystemClock.uptimeMillis();
         return true;
     }
 
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index de7bc6d..1539747 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -43,7 +43,6 @@
 import com.android.launcher3.WorkspaceItemInfo;
 import com.android.launcher3.accessibility.DragViewStateAnnouncer;
 import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.Thunk;
 import com.android.launcher3.util.TouchController;
 import com.android.launcher3.util.UiThreadHelper;
 
@@ -61,8 +60,8 @@
      */
     private static final int DEEP_PRESS_DISTANCE_FACTOR = 3;
 
-    @Thunk Launcher mLauncher;
-    private FlingToDeleteHelper mFlingToDeleteHelper;
+    private final Launcher mLauncher;
+    private final FlingToDeleteHelper mFlingToDeleteHelper;
 
     // temporaries to avoid gc thrash
     private Rect mRectTemp = new Rect();
@@ -77,11 +76,12 @@
     /** Options controlling the drag behavior. */
     private DragOptions mOptions;
 
-    /** X coordinate of the down event. */
-    private int mMotionDownX;
+    /** Coordinate for motion down event */
+    private final Point mMotionDown = new Point();
+    /** Coordinate for last touch event **/
+    private final Point mLastTouch = new Point();
 
-    /** Y coordinate of the down event. */
-    private int mMotionDownY;
+    private final Point mTmpPoint = new Point();
 
     private DropTarget.DragObject mDragObject;
 
@@ -96,12 +96,9 @@
 
     private DropTarget mLastDropTarget;
 
-    private final int[] mLastTouch = new int[2];
-    private long mLastTouchUpTime = -1;
     private int mLastTouchClassification;
     private int mDistanceSinceScroll = 0;
 
-    private int mTmpPoint[] = new int[2];
     private Rect mDragLayerRect = new Rect();
 
     private boolean mIsInPreDrag;
@@ -159,13 +156,13 @@
         AbstractFloatingView.closeOpenViews(mLauncher, false, TYPE_DISCOVERY_BOUNCE);
 
         mOptions = options;
-        if (mOptions.systemDndStartPoint != null) {
-            mLastTouch[0] = mMotionDownX = mOptions.systemDndStartPoint.x;
-            mLastTouch[1] = mMotionDownY = mOptions.systemDndStartPoint.y;
+        if (mOptions.simulatedDndStartPoint != null) {
+            mLastTouch.x = mMotionDown.x = mOptions.simulatedDndStartPoint.x;
+            mLastTouch.y = mMotionDown.y = mOptions.simulatedDndStartPoint.y;
         }
 
-        final int registrationX = mMotionDownX - dragLayerX;
-        final int registrationY = mMotionDownY - dragLayerY;
+        final int registrationX = mMotionDown.x - dragLayerX;
+        final int registrationY = mMotionDown.y - dragLayerY;
 
         final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
         final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
@@ -184,17 +181,13 @@
                 registrationY, initialDragViewScale, dragViewScaleOnDrop, scaleDps);
         dragView.setItemInfo(dragInfo);
         mDragObject.dragComplete = false;
-        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;
-            mDragObject.accessibleDrag = true;
-        } else {
-            mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
-            mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
-            mDragObject.stateAnnouncer = DragViewStateAnnouncer.createFor(dragView);
 
-            mDragDriver = DragDriver.create(mLauncher, this, mDragObject, mOptions);
+        mDragObject.xOffset = mMotionDown.x - (dragLayerX + dragRegionLeft);
+        mDragObject.yOffset = mMotionDown.y - (dragLayerY + dragRegionTop);
+
+        mDragDriver = DragDriver.create(this, mOptions, mFlingToDeleteHelper::recordMotionEvent);
+        if (!mOptions.isAccessibleDrag) {
+            mDragObject.stateAnnouncer = DragViewStateAnnouncer.createFor(dragView);
         }
 
         mDragObject.dragSource = source;
@@ -210,7 +203,7 @@
         }
 
         mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-        dragView.show(mLastTouch[0], mLastTouch[1]);
+        dragView.show(mLastTouch.x, mLastTouch.y);
         mDistanceSinceScroll = 0;
 
         if (!mIsInPreDrag) {
@@ -219,7 +212,7 @@
             mOptions.preDragCondition.onPreDragStart(mDragObject);
         }
 
-        handleMoveEvent(mLastTouch[0], mLastTouch[1]);
+        handleMoveEvent(mLastTouch.x, mLastTouch.y);
         mLauncher.getUserEventDispatcher().resetActionDurationMillis();
         return dragView;
     }
@@ -336,7 +329,7 @@
                 }
             }
         };
-        mDragObject.dragView.animateTo(mMotionDownX, mMotionDownY, onCompleteRunnable, duration);
+        mDragObject.dragView.animateTo(mMotionDown.x, mMotionDown.y, onCompleteRunnable, duration);
     }
 
     private void callOnDragEnd() {
@@ -365,30 +358,17 @@
     /**
      * Clamps the position to the drag layer bounds.
      */
-    private int[] getClampedDragLayerPos(float x, float y) {
+    private Point getClampedDragLayerPos(float x, float y) {
         mLauncher.getDragLayer().getLocalVisibleRect(mDragLayerRect);
-        mTmpPoint[0] = (int) Math.max(mDragLayerRect.left, Math.min(x, mDragLayerRect.right - 1));
-        mTmpPoint[1] = (int) Math.max(mDragLayerRect.top, Math.min(y, mDragLayerRect.bottom - 1));
+        mTmpPoint.x = (int) Math.max(mDragLayerRect.left, Math.min(x, mDragLayerRect.right - 1));
+        mTmpPoint.y = (int) Math.max(mDragLayerRect.top, Math.min(y, mDragLayerRect.bottom - 1));
         return mTmpPoint;
     }
 
-    public long getLastGestureUpTime() {
-        if (mDragDriver != null) {
-            return System.currentTimeMillis();
-        } else {
-            return mLastTouchUpTime;
-        }
-    }
-
-    public void resetLastGestureUpTime() {
-        mLastTouchUpTime = -1;
-    }
-
     @Override
     public void onDriverDragMove(float x, float y) {
-        final int[] dragLayerPos = getClampedDragLayerPos(x, y);
-
-        handleMoveEvent(dragLayerPos[0], dragLayerPos[1]);
+        Point dragLayerPos = getClampedDragLayerPos(x, y);
+        handleMoveEvent(dragLayerPos.x, dragLayerPos.y);
     }
 
     @Override
@@ -422,53 +402,38 @@
     /**
      * Call this from a drag source view.
      */
+    @Override
     public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
         if (mOptions != null && mOptions.isAccessibleDrag) {
             return false;
         }
 
-        // Update the velocity tracker
-        mFlingToDeleteHelper.recordMotionEvent(ev);
+        Point dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
+        mLastTouch.set(dragLayerPos.x,  dragLayerPos.y);
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            // Remember location of down touch
+            mMotionDown.set(dragLayerPos.x,  dragLayerPos.y);
+        }
 
-        final int action = ev.getAction();
-        final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
-        final int dragLayerX = dragLayerPos[0];
-        final int dragLayerY = dragLayerPos[1];
-        mLastTouch[0] = dragLayerX;
-        mLastTouch[1] = dragLayerY;
         if (ATLEAST_Q) {
             mLastTouchClassification = ev.getClassification();
         }
-
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                // Remember location of down touch
-                mMotionDownX = dragLayerX;
-                mMotionDownY = dragLayerY;
-                break;
-            case MotionEvent.ACTION_UP:
-                mLastTouchUpTime = System.currentTimeMillis();
-                break;
-        }
-
         return mDragDriver != null && mDragDriver.onInterceptTouchEvent(ev);
     }
 
     /**
      * Call this from a drag source view.
      */
-    public boolean onDragEvent(long dragStartTime, DragEvent event) {
-        mFlingToDeleteHelper.recordDragEvent(dragStartTime, event);
-        return mDragDriver != null && mDragDriver.onDragEvent(event);
+    @Override
+    public boolean onControllerTouchEvent(MotionEvent ev) {
+        return mDragDriver != null && mDragDriver.onTouchEvent(ev);
     }
 
     /**
-     * Call this from a drag view.
+     * Call this from a drag source view.
      */
-    public void onDragViewAnimationEnd() {
-        if (mDragDriver != null) {
-            mDragDriver.onDragViewAnimationEnd();
-        }
+    public boolean onDragEvent(DragEvent event) {
+        return mDragDriver != null && mDragDriver.onDragEvent(event);
     }
 
     /**
@@ -493,9 +458,8 @@
         checkTouchMove(dropTarget);
 
         // Check if we are hovering over the scroll areas
-        mDistanceSinceScroll += Math.hypot(mLastTouch[0] - x, mLastTouch[1] - y);
-        mLastTouch[0] = x;
-        mLastTouch[1] = y;
+        mDistanceSinceScroll += Math.hypot(mLastTouch.x - x, mLastTouch.y - y);
+        mLastTouch.set(x, y);
 
         int distanceDragged = mDistanceSinceScroll;
         if (ATLEAST_Q && mLastTouchClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS) {
@@ -513,7 +477,7 @@
 
     public void forceTouchMove() {
         int[] dummyCoordinates = mCoordinatesTemp;
-        DropTarget dropTarget = findDropTarget(mLastTouch[0], mLastTouch[1], dummyCoordinates);
+        DropTarget dropTarget = findDropTarget(mLastTouch.x, mLastTouch.y, dummyCoordinates);
         mDragObject.x = dummyCoordinates[0];
         mDragObject.y = dummyCoordinates[1];
         checkTouchMove(dropTarget);
@@ -537,44 +501,6 @@
     }
 
     /**
-     * Call this from a drag source view.
-     */
-    public boolean onControllerTouchEvent(MotionEvent ev) {
-        if (mDragDriver == null || mOptions == null || mOptions.isAccessibleDrag) {
-            return false;
-        }
-
-        // Update the velocity tracker
-        mFlingToDeleteHelper.recordMotionEvent(ev);
-
-        final int action = ev.getAction();
-        final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
-        final int dragLayerX = dragLayerPos[0];
-        final int dragLayerY = dragLayerPos[1];
-
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                // Remember where the motion event started
-                mMotionDownX = dragLayerX;
-                mMotionDownY = dragLayerY;
-                break;
-        }
-
-        return mDragDriver.onTouchEvent(ev);
-    }
-
-    /**
-     * Since accessible drag and drop won't cause the same sequence of touch events, we manually
-     * inject the appropriate state which would have been otherwise initiated via touch events.
-     */
-    public void prepareAccessibleDrag(int x, int y) {
-        mMotionDownX = x;
-        mMotionDownY = y;
-        mLastTouch[0] = x;
-        mLastTouch[1] = y;
-    }
-
-    /**
      * As above, since accessible drag and drop won't cause the same sequence of touch events,
      * we manually ensure appropriate drag and drop events get emulated for accessible drag.
      */
diff --git a/src/com/android/launcher3/dragndrop/DragDriver.java b/src/com/android/launcher3/dragndrop/DragDriver.java
index 87461d5..d4ce308 100644
--- a/src/com/android/launcher3/dragndrop/DragDriver.java
+++ b/src/com/android/launcher3/dragndrop/DragDriver.java
@@ -16,19 +16,19 @@
 
 package com.android.launcher3.dragndrop;
 
-import android.content.Context;
-import android.util.Log;
+import android.os.SystemClock;
 import android.view.DragEvent;
 import android.view.MotionEvent;
 
-import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.testing.TestProtocol;
+import java.util.function.Consumer;
 
 /**
  * Base class for driving a drag/drop operation.
  */
 public abstract class DragDriver {
+
     protected final EventListener mEventListener;
+    protected final Consumer<MotionEvent> mSecondaryEventConsumer;
 
     public interface EventListener {
         void onDriverDragMove(float x, float y);
@@ -37,131 +37,175 @@
         void onDriverDragCancel();
     }
 
-    public DragDriver(EventListener eventListener) {
+    public DragDriver(EventListener eventListener, Consumer<MotionEvent> sec) {
         mEventListener = eventListener;
+        mSecondaryEventConsumer = sec;
     }
 
     /**
-     * Handles ending of the DragView animation.
+     * Called to handle system touch event
      */
-    public void onDragViewAnimationEnd() { }
-
     public boolean onTouchEvent(MotionEvent ev) {
-        final int action = ev.getAction();
-
-        switch (action) {
-            case MotionEvent.ACTION_MOVE:
-                mEventListener.onDriverDragMove(ev.getX(), ev.getY());
-                break;
-            case MotionEvent.ACTION_UP:
-                mEventListener.onDriverDragMove(ev.getX(), ev.getY());
-                mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
-                break;
-            case MotionEvent.ACTION_CANCEL:
-                mEventListener.onDriverDragCancel();
-                break;
-        }
-
-        return true;
+        return false;
     }
 
-    public abstract boolean onDragEvent (DragEvent event);
-
-
+    /**
+     * Called to handle system touch intercept event
+     */
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        final int action = ev.getAction();
-
-        switch (action) {
-            case MotionEvent.ACTION_UP:
-                mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
-                break;
-            case MotionEvent.ACTION_CANCEL:
-                mEventListener.onDriverDragCancel();
-                break;
-        }
-
-        return true;
+        return false;
     }
 
-    public static DragDriver create(Context context, DragController dragController,
-            DragObject dragObject, DragOptions options) {
-        if (options.systemDndStartPoint != null) {
-            return new SystemDragDriver(dragController, context, dragObject);
+    /**
+     * Called to handle system drag event
+     */
+    public boolean onDragEvent(DragEvent event) {
+        return false;
+    }
+
+    /**
+     * Created a driver for handing the actual events
+     */
+    public static DragDriver create(DragController dragController, DragOptions options,
+            Consumer<MotionEvent> sec) {
+        if (options.simulatedDndStartPoint != null) {
+            if  (options.isAccessibleDrag) {
+                return null;
+            }
+            return new SystemDragDriver(dragController, sec);
         } else {
-            return new InternalDragDriver(dragController);
+            return new InternalDragDriver(dragController, sec);
+        }
+    }
+
+    /**
+     * Class for driving a system (i.e. framework) drag/drop operation.
+     */
+    static class SystemDragDriver extends DragDriver {
+
+        private final long mDragStartTime;
+        float mLastX = 0;
+        float mLastY = 0;
+
+        SystemDragDriver(DragController dragController, Consumer<MotionEvent> sec) {
+            super(dragController, sec);
+            mDragStartTime = SystemClock.uptimeMillis();
+        }
+
+        @Override
+        public boolean onInterceptTouchEvent(MotionEvent ev) {
+            return false;
+        }
+
+        /**
+         * It creates a temporary {@link MotionEvent} object for secondary consumer
+         */
+        private void simulateSecondaryMotionEvent(DragEvent event) {
+            final int motionAction;
+            switch (event.getAction()) {
+                case DragEvent.ACTION_DRAG_STARTED:
+                    motionAction = MotionEvent.ACTION_DOWN;
+                    break;
+                case DragEvent.ACTION_DRAG_LOCATION:
+                    motionAction = MotionEvent.ACTION_MOVE;
+                    break;
+                case DragEvent.ACTION_DRAG_ENDED:
+                    motionAction = MotionEvent.ACTION_UP;
+                    break;
+                default:
+                    return;
+            }
+            MotionEvent emulatedEvent = MotionEvent.obtain(mDragStartTime,
+                    SystemClock.uptimeMillis(), motionAction, event.getX(), event.getY(), 0);
+            mSecondaryEventConsumer.accept(emulatedEvent);
+            emulatedEvent.recycle();
+        }
+
+        @Override
+        public boolean onDragEvent(DragEvent event) {
+            simulateSecondaryMotionEvent(event);
+            final int action = event.getAction();
+
+            switch (action) {
+                case DragEvent.ACTION_DRAG_STARTED:
+                    mLastX = event.getX();
+                    mLastY = event.getY();
+                    return true;
+
+                case DragEvent.ACTION_DRAG_ENTERED:
+                    return true;
+
+                case DragEvent.ACTION_DRAG_LOCATION:
+                    mLastX = event.getX();
+                    mLastY = event.getY();
+                    mEventListener.onDriverDragMove(event.getX(), event.getY());
+                    return true;
+
+                case DragEvent.ACTION_DROP:
+                    mLastX = event.getX();
+                    mLastY = event.getY();
+                    mEventListener.onDriverDragMove(event.getX(), event.getY());
+                    mEventListener.onDriverDragEnd(mLastX, mLastY);
+                    return true;
+                case DragEvent.ACTION_DRAG_EXITED:
+                    mEventListener.onDriverDragExitWindow();
+                    return true;
+
+                case DragEvent.ACTION_DRAG_ENDED:
+                    mEventListener.onDriverDragCancel();
+                    return true;
+
+                default:
+                    return false;
+            }
+        }
+    }
+
+    /**
+     * Class for driving an internal (i.e. not using framework) drag/drop operation.
+     */
+    static class InternalDragDriver extends DragDriver {
+        InternalDragDriver(DragController dragController, Consumer<MotionEvent> sec) {
+            super(dragController, sec);
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent ev) {
+            mSecondaryEventConsumer.accept(ev);
+            final int action = ev.getAction();
+
+            switch (action) {
+                case MotionEvent.ACTION_MOVE:
+                    mEventListener.onDriverDragMove(ev.getX(), ev.getY());
+                    break;
+                case MotionEvent.ACTION_UP:
+                    mEventListener.onDriverDragMove(ev.getX(), ev.getY());
+                    mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
+                    break;
+                case MotionEvent.ACTION_CANCEL:
+                    mEventListener.onDriverDragCancel();
+                    break;
+            }
+
+            return true;
+        }
+
+
+        public boolean onInterceptTouchEvent(MotionEvent ev) {
+            mSecondaryEventConsumer.accept(ev);
+            final int action = ev.getAction();
+
+            switch (action) {
+                case MotionEvent.ACTION_UP:
+                    mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
+                    break;
+                case MotionEvent.ACTION_CANCEL:
+                    mEventListener.onDriverDragCancel();
+                    break;
+            }
+            return true;
         }
     }
 }
 
-/**
- * Class for driving a system (i.e. framework) drag/drop operation.
- */
-class SystemDragDriver extends DragDriver {
 
-    float mLastX = 0;
-    float mLastY = 0;
-
-    SystemDragDriver(DragController dragController, Context context, DragObject dragObject) {
-        super(dragController);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        return false;
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        return false;
-    }
-
-    @Override
-    public boolean onDragEvent (DragEvent event) {
-        final int action = event.getAction();
-
-        switch (action) {
-            case DragEvent.ACTION_DRAG_STARTED:
-                mLastX = event.getX();
-                mLastY = event.getY();
-                return true;
-
-            case DragEvent.ACTION_DRAG_ENTERED:
-                return true;
-
-            case DragEvent.ACTION_DRAG_LOCATION:
-                mLastX = event.getX();
-                mLastY = event.getY();
-                mEventListener.onDriverDragMove(event.getX(), event.getY());
-                return true;
-
-            case DragEvent.ACTION_DROP:
-                mLastX = event.getX();
-                mLastY = event.getY();
-                mEventListener.onDriverDragMove(event.getX(), event.getY());
-                mEventListener.onDriverDragEnd(mLastX, mLastY);
-                return true;
-            case DragEvent.ACTION_DRAG_EXITED:
-                mEventListener.onDriverDragExitWindow();
-                return true;
-
-            case DragEvent.ACTION_DRAG_ENDED:
-                mEventListener.onDriverDragCancel();
-                return true;
-
-            default:
-                return false;
-        }
-    }
-}
-
-/**
- * Class for driving an internal (i.e. not using framework) drag/drop operation.
- */
-class InternalDragDriver extends DragDriver {
-    InternalDragDriver(DragController dragController) {
-        super(dragController);
-    }
-
-    @Override
-    public boolean onDragEvent (DragEvent event) { return false; }
-}
diff --git a/src/com/android/launcher3/dragndrop/DragOptions.java b/src/com/android/launcher3/dragndrop/DragOptions.java
index 2d19f36..959602b 100644
--- a/src/com/android/launcher3/dragndrop/DragOptions.java
+++ b/src/com/android/launcher3/dragndrop/DragOptions.java
@@ -28,8 +28,11 @@
     /** Whether or not an accessible drag operation is in progress. */
     public boolean isAccessibleDrag = false;
 
-    /** Specifies the start location for the system DnD, null when using internal DnD */
-    public Point systemDndStartPoint = null;
+    /**
+     * Specifies the start location for a simulated DnD (like system drag or accessibility drag),
+     * null when using internal DnD
+     */
+    public Point simulatedDndStartPoint = null;
 
     /** Determines when a pre-drag should transition to a drag. By default, this is immediate. */
     public PreDragCondition preDragCondition = null;
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 145885a..7c76d34 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -19,8 +19,6 @@
 import static com.android.launcher3.Utilities.getBadge;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.FloatArrayEvaluator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -146,15 +144,6 @@
             }
         });
 
-        mAnim.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (!mAnimationCancelled) {
-                    mDragController.onDragViewAnimationEnd();
-                }
-            }
-        });
-
         mBitmap = bitmap;
         setDragRegion(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()));
 
diff --git a/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java b/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
index 06b5c40..7788f93 100644
--- a/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
+++ b/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
@@ -17,8 +17,6 @@
 package com.android.launcher3.dragndrop;
 
 import android.graphics.PointF;
-import android.os.SystemClock;
-import android.view.DragEvent;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
@@ -55,31 +53,6 @@
         mVelocityTracker.addMovement(ev);
     }
 
-    /**
-     * Same as {@link #recordMotionEvent}. It creates a temporary {@link MotionEvent} object
-     * using {@param event} for tracking velocity.
-     */
-    public void recordDragEvent(long dragStartTime, DragEvent event) {
-        final int motionAction;
-        switch (event.getAction()) {
-            case DragEvent.ACTION_DRAG_STARTED:
-                motionAction = MotionEvent.ACTION_DOWN;
-                break;
-            case DragEvent.ACTION_DRAG_LOCATION:
-                motionAction = MotionEvent.ACTION_MOVE;
-                break;
-            case DragEvent.ACTION_DRAG_ENDED:
-                motionAction = MotionEvent.ACTION_UP;
-                break;
-            default:
-                return;
-        }
-        MotionEvent emulatedEvent = MotionEvent.obtain(dragStartTime, SystemClock.uptimeMillis(),
-                motionAction, event.getX(), event.getY(), 0);
-        recordMotionEvent(emulatedEvent);
-        emulatedEvent.recycle();
-    }
-
     public void releaseVelocityTracker() {
         if (mVelocityTracker != null) {
             mVelocityTracker.recycle();
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 5f496f4..c20717a 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -85,6 +85,7 @@
 import com.android.launcher3.Workspace.ItemOperator;
 import com.android.launcher3.WorkspaceItemInfo;
 import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
+import com.android.launcher3.accessibility.FolderAccessibilityHelper;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragController.DragListener;
@@ -271,16 +272,15 @@
             mDragController.addDragListener(this);
             if (options.isAccessibleDrag) {
                 mDragController.addDragListener(new AccessibleDragListenerAdapter(
-                        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);
-                    }
-                });
+                        mContent, FolderAccessibilityHelper::new) {
+                            @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);