Accessibility fixes

> Enabling top bar buttons in accessibility drag-drop
> Unifying logic to show delete/uninstall/app-info targets
> Announcing cell loction as 1-index instead of 0-index

Change-Id: Ibc7801f77e938b2646f0655462cbe9b7f781818b
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 5b39908..fb49df5 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -26,18 +26,19 @@
 import android.graphics.drawable.TransitionDrawable;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.LinearInterpolator;
 import android.widget.TextView;
 
-import com.android.launcher3.R;
 import com.android.launcher3.util.Thunk;
 
 /**
  * Implements a DropTarget.
  */
-public abstract class ButtonDropTarget extends TextView implements DropTarget, DragController.DragListener {
+public abstract class ButtonDropTarget extends TextView
+        implements DropTarget, DragController.DragListener, OnClickListener {
 
     private static int DRAG_VIEW_DROP_DURATION = 285;
 
@@ -256,4 +257,18 @@
     public void getLocationInDragLayer(int[] loc) {
         mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
     }
+
+    public void enableAccessibleDrag(boolean enable) {
+        setOnClickListener(enable ? this : null);
+    }
+
+    protected String getAccessibilityDropConfirmation() {
+        return null;
+    }
+
+    @Override
+    public void onClick(View v) {
+        LauncherAppState.getInstance().getAccessibilityDelegate()
+            .handleAccessibleDrop(this, null, getAccessibilityDropConfirmation());
+    }
 }
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index f4afb95..f08f25f 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -557,7 +557,7 @@
             Resources res = getContext().getResources();
             View child = getChildAt(x, y);
             if (child == null || child == dragInfo.item) {
-                return res.getString(R.string.move_to_empty_cell, x, y);
+                return res.getString(R.string.move_to_empty_cell, x + 1, y + 1);
             } else {
                 ItemInfo info = (ItemInfo) child.getTag();
                 if (info instanceof AppInfo || info instanceof ShortcutInfo) {
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index aa3e66c..e741b97 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -29,7 +29,6 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
 
-import com.android.launcher3.R;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.widget.WidgetsContainerView;
 
@@ -59,13 +58,15 @@
         setDrawable(R.drawable.remove_target_selector);
     }
 
-    public static boolean willAcceptDrop(DragSource source, Object info) {
-        return (info instanceof ItemInfo) && source.supportsDeleteDropTarget();
+    public static boolean supportsDrop(Object info) {
+        return (info instanceof ShortcutInfo)
+                || (info instanceof LauncherAppWidgetInfo)
+                || (info instanceof FolderInfo);
     }
 
     @Override
     protected boolean supportsDrop(DragSource source, Object info) {
-        return willAcceptDrop(source, info);
+        return source.supportsDeleteDropTarget() && supportsDrop(info);
     }
 
     @Override
@@ -304,4 +305,9 @@
         dragLayer.animateView(d.dragView, updateCb, duration, tInterpolator, onAnimationEndRunnable,
                 DragLayer.ANIMATION_END_DISAPPEAR, null);
     }
+
+    @Override
+    protected String getAccessibilityDropConfirmation() {
+        return getResources().getString(R.string.item_removed);
+    }
 }
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index b24608c..1968868 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -462,8 +462,7 @@
                 mLastTouchUpTime = System.currentTimeMillis();
                 if (mDragging) {
                     PointF vec = isFlingingToDelete(mDragObject.dragSource);
-                    if (!DeleteDropTarget.willAcceptDrop(mDragObject.dragSource,
-                            mDragObject.dragInfo)) {
+                    if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) {
                         vec = null;
                     }
                     if (vec != null) {
@@ -617,7 +616,7 @@
 
             if (mDragging) {
                 PointF vec = isFlingingToDelete(mDragObject.dragSource);
-                if (!DeleteDropTarget.willAcceptDrop(mDragObject.dragSource, mDragObject.dragInfo)) {
+                if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) {
                     vec = null;
                 }
                 if (vec != null) {
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index e48640c..f1ff48d 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -21,7 +21,6 @@
 import android.provider.Settings;
 import android.util.AttributeSet;
 
-import com.android.launcher3.R;
 import com.android.launcher3.compat.UserHandleCompat;
 
 public class InfoDropTarget extends ButtonDropTarget {
@@ -66,9 +65,13 @@
 
     @Override
     protected boolean supportsDrop(DragSource source, Object info) {
-        return source.supportsAppInfoDropTarget() &&
-                Settings.Global.getInt(getContext().getContentResolver(),
-                        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1;
+        return source.supportsAppInfoDropTarget() && supportsDrop(getContext(), info);
+    }
+
+    public static boolean supportsDrop(Context context, Object info) {
+        return (Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1) &&
+                (info instanceof AppInfo || info instanceof PendingAddItemInfo);
     }
 
     @Override
diff --git a/src/com/android/launcher3/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/LauncherAccessibilityDelegate.java
index 8ba02ea..a60e160 100644
--- a/src/com/android/launcher3/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/LauncherAccessibilityDelegate.java
@@ -1,16 +1,13 @@
 package com.android.launcher3;
 
 import android.annotation.TargetApi;
-import android.content.res.Resources;
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
-import android.support.v4.view.accessibility.AccessibilityEventCompat;
-import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.text.TextUtils;
 import android.util.SparseArray;
 import android.view.View;
 import android.view.View.AccessibilityDelegate;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
@@ -68,18 +65,21 @@
         if (!(host.getTag() instanceof ItemInfo)) return;
         ItemInfo item = (ItemInfo) host.getTag();
 
+        if (DeleteDropTarget.supportsDrop(item)) {
+            info.addAction(mActions.get(REMOVE));
+        }
+        if (UninstallDropTarget.supportsDrop(host.getContext(), item)) {
+            info.addAction(mActions.get(UNINSTALL));
+        }
+        if (InfoDropTarget.supportsDrop(host.getContext(), item)) {
+            info.addAction(mActions.get(INFO));
+        }
+
         if ((item instanceof ShortcutInfo)
                 || (item instanceof LauncherAppWidgetInfo)
                 || (item instanceof FolderInfo)) {
-            // Workspace shortcut / widget
-            info.addAction(mActions.get(REMOVE));
             info.addAction(mActions.get(MOVE));
-        } else if ((item instanceof AppInfo) || (item instanceof PendingAddItemInfo)) {
-            // App or Widget from customization tray
-            if (item instanceof AppInfo) {
-                info.addAction(mActions.get(UNINSTALL));
-            }
-            info.addAction(mActions.get(INFO));
+        } if ((item instanceof AppInfo) || (item instanceof PendingAddItemInfo)) {
             info.addAction(mActions.get(ADD_TO_WORKSPACE));
         }
     }
@@ -94,10 +94,9 @@
     }
 
     public boolean performAction(View host, ItemInfo item, int action) {
-        Resources res = mLauncher.getResources();
         if (action == REMOVE) {
             if (DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host)) {
-                announceConfirmation(R.string.item_removed_from_workspace);
+                announceConfirmation(R.string.item_removed);
                 return true;
             }
             return false;
@@ -105,9 +104,7 @@
             InfoDropTarget.startDetailsActivityForInfo(item, mLauncher);
             return true;
         } else if (action == UNINSTALL) {
-            AppInfo info = (AppInfo) item;
-            mLauncher.startApplicationUninstallActivity(info.componentName, info.flags, info.user);
-            return true;
+            return UninstallDropTarget.startUninstallActivity(mLauncher, item);
         } else if (action == MOVE) {
             beginAccessibleDrag(host, item);
         } else if (action == ADD_TO_WORKSPACE) {
@@ -158,19 +155,31 @@
         return mDragInfo;
     }
 
-    public void handleAccessibleDrop(CellLayout targetContainer, Rect dropLocation,
+    /**
+     * @param clickedTarget the actual view that was clicked
+     * @param dropLocation relative to {@param clickedTarget}. If provided, its center is used
+     * as the actual drop location otherwise the views center is used.
+     */
+    public void handleAccessibleDrop(View clickedTarget, Rect dropLocation,
             String confirmation) {
         if (!isInAccessibleDrag()) return;
 
         int[] loc = new int[2];
-        loc[0] = dropLocation.centerX();
-        loc[1] = dropLocation.centerY();
+        if (dropLocation == null) {
+            loc[0] = clickedTarget.getWidth() / 2;
+            loc[1] = clickedTarget.getHeight() / 2;
+        } else {
+            loc[0] = dropLocation.centerX();
+            loc[1] = dropLocation.centerY();
+        }
 
-        mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(targetContainer, loc);
+        mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(clickedTarget, loc);
         mLauncher.getDragController().completeAccessibleDrag(loc);
 
         endAccessibleDrag();
-        announceConfirmation(confirmation);
+        if (!TextUtils.isEmpty(confirmation)) {
+            announceConfirmation(confirmation);
+        }
     }
 
     public void beginAccessibleDrag(View item, ItemInfo info) {
diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java
index af8bc75..44a76b7 100644
--- a/src/com/android/launcher3/SearchDropTargetBar.java
+++ b/src/com/android/launcher3/SearchDropTargetBar.java
@@ -180,6 +180,9 @@
         prepareStartAnimation(mDropTargetBar);
         mShowDropTargetBarAnim.start();
         hideSearchBar(true);
+        if (mQSBSearchBar != null) {
+            mQSBSearchBar.setVisibility(View.GONE);
+        }
     }
 
     /**
@@ -190,6 +193,9 @@
         prepareStartAnimation(mDropTargetBar);
         mShowDropTargetBarAnim.reverse();
         showSearchBar(true);
+        if (mQSBSearchBar != null) {
+            mQSBSearchBar.setVisibility(View.VISIBLE);
+        }
     }
 
     /*
@@ -228,4 +234,13 @@
             return null;
         }
     }
+
+    public void enableAccessibleDrag(boolean enable) {
+        if (mQSBSearchBar != null) {
+            mQSBSearchBar.setVisibility(enable ? View.GONE : View.VISIBLE);
+        }
+        mInfoDropTarget.enableAccessibleDrag(enable);
+        mDeleteDropTarget.enableAccessibleDrag(enable);
+        mUninstallDropTarget.enableAccessibleDrag(enable);
+    }
 }
diff --git a/src/com/android/launcher3/UninstallDropTarget.java b/src/com/android/launcher3/UninstallDropTarget.java
index 4a7fffe..4c52d7e 100644
--- a/src/com/android/launcher3/UninstallDropTarget.java
+++ b/src/com/android/launcher3/UninstallDropTarget.java
@@ -33,9 +33,12 @@
 
     @Override
     protected boolean supportsDrop(DragSource source, Object info) {
+        return supportsDrop(getContext(), info);
+    }
+
+    public static boolean supportsDrop(Context context, Object info) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
-            UserManager userManager = (UserManager)
-                    getContext().getSystemService(Context.USER_SERVICE);
+            UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
             Bundle restrictions = userManager.getUserRestrictions();
             if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
                     || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false)) {
@@ -78,8 +81,7 @@
     void completeDrop(final DragObject d) {
         final Pair<ComponentName, Integer> componentInfo = getAppInfoFlags(d.dragInfo);
         final UserHandleCompat user = ((ItemInfo) d.dragInfo).user;
-        if (mLauncher.startApplicationUninstallActivity(
-                componentInfo.first, componentInfo.second, user)) {
+        if (startUninstallActivity(mLauncher, d.dragInfo)) {
 
             final Runnable checkIfUninstallWasSuccess = new Runnable() {
                 @Override
@@ -96,6 +98,13 @@
         }
     }
 
+    public static boolean startUninstallActivity(Launcher launcher, Object info) {
+        final Pair<ComponentName, Integer> componentInfo = getAppInfoFlags(info);
+        final UserHandleCompat user = ((ItemInfo) info).user;
+        return launcher.startApplicationUninstallActivity(
+                componentInfo.first, componentInfo.second, user);
+    }
+
     @Thunk void sendUninstallResult(DragSource target, boolean result) {
         if (target instanceof UninstallSource) {
             ((UninstallSource) target).onUninstallActivityReturned(result);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index abb8489..0ae4ffa 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1615,6 +1615,7 @@
             // Reset our click listener
             setOnClickListener(mLauncher);
         }
+        mLauncher.getSearchBar().enableAccessibleDrag(enable);
         mLauncher.getHotseat().getLayout().enableAccessibleDrag(enable);
     }