Address comments on original shortcuts UI CL (ag/1061538).

- Only add shortcut touch listener to APPLICATION item types, not SHORTCUT.
- Load shortcuts on LauncherModel worker thread instead of using AsyncTask.
- Avoid a couple of unnecessary object allocations.

Change-Id: I31b911b91df71335542545602fe137e270c745d7
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutManager.java b/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
index d1f0c5c..66e98cd 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
@@ -58,8 +58,7 @@
     }
 
     public static boolean supportsShortcuts(ItemInfo info) {
-        return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
-                || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+        return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
     }
 
     public boolean wasLastCallSuccess() {
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
index 31440ff..5479453 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
@@ -7,8 +7,9 @@
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.os.AsyncTask;
 import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
@@ -21,6 +22,7 @@
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
 import com.android.launcher3.LogDecelerateInterpolator;
 import com.android.launcher3.R;
 import com.android.launcher3.ShortcutInfo;
@@ -35,7 +37,6 @@
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
 import com.android.launcher3.util.UiThreadCircularReveal;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -98,37 +99,45 @@
         deferDrag(originalIcon);
 
         // Load the shortcuts on a background thread and update the container as it animates.
+        final Looper workerLooper = LauncherModel.getWorkerLooper();
+        final Handler uiHandler = new Handler(Looper.getMainLooper());
         final ItemInfo originalInfo = (ItemInfo) originalIcon.getTag();
         final UserHandleCompat user = originalInfo.user;
         final ComponentName activity = originalInfo.getTargetComponent();
-        new AsyncTask<Void, Void, List<ShortcutInfo>>() {
-            public List<ShortcutInfo> doInBackground(Void ... args) {
-                List<ShortcutInfoCompat> shortcuts = mDeepShortcutsManager
-                        .queryForAllAppShortcuts(activity, ids, user);
-                List<ShortcutInfo> shortcutInfos = new ArrayList<>(shortcuts.size());
-                for (ShortcutInfoCompat shortcut : shortcuts) {
-                    shortcutInfos.add(ShortcutInfo.fromDeepShortcutInfo(shortcut, mLauncher));
-                }
-                return shortcutInfos;
-            }
-
-            // TODO: implement onProgressUpdate() to load shortcuts one at a time.
-
+        new Handler(workerLooper).postAtFrontOfQueue(new Runnable() {
             @Override
-            protected void onPostExecute(List<ShortcutInfo> shortcuts) {
+            public void run() {
+                final List<ShortcutInfoCompat> shortcuts = mDeepShortcutsManager
+                        .queryForAllAppShortcuts(activity, ids, user);
                 for (int i = 0; i < shortcuts.size(); i++) {
-                    DeepShortcutView iconAndText = (DeepShortcutView) getChildAt(i);
-                    ShortcutInfo launcherShortcutInfo = shortcuts.get(i);
-                    iconAndText.applyFromShortcutInfo(launcherShortcutInfo,
-                            LauncherAppState.getInstance().getIconCache());
-                    iconAndText.setOnClickListener(mLauncher);
-                    iconAndText.setOnLongClickListener(DeepShortcutsContainer.this);
-                    iconAndText.setOnTouchListener(DeepShortcutsContainer.this);
-                    int viewId = mLauncher.getViewIdForItem(originalInfo);
-                    iconAndText.setId(viewId);
+                    final ShortcutInfoCompat shortcut = shortcuts.get(i);
+                    final ShortcutInfo launcherShortcutInfo = ShortcutInfo
+                            .fromDeepShortcutInfo(shortcut, mLauncher);
+                    uiHandler.post(new UpdateShortcutChild(i, launcherShortcutInfo));
                 }
             }
-        }.execute();
+        });
+    }
+
+    /** Updates the child of this container at the given index based on the given shortcut info. */
+    private class UpdateShortcutChild implements Runnable {
+        private int mShortcutChildIndex;
+        private ShortcutInfo mShortcutChildInfo;
+
+        public UpdateShortcutChild(int shortcutChildIndex, ShortcutInfo shortcutChildInfo) {
+            mShortcutChildIndex = shortcutChildIndex;
+            mShortcutChildInfo = shortcutChildInfo;
+        }
+
+        @Override
+        public void run() {
+            DeepShortcutView shortcutView = (DeepShortcutView) getChildAt(mShortcutChildIndex);
+            shortcutView.applyFromShortcutInfo(mShortcutChildInfo,
+                    LauncherAppState.getInstance().getIconCache());
+            shortcutView.setOnClickListener(mLauncher);
+            shortcutView.setOnLongClickListener(DeepShortcutsContainer.this);
+            shortcutView.setOnTouchListener(DeepShortcutsContainer.this);
+        }
     }
 
     // TODO: update this animation
@@ -220,9 +229,9 @@
         mDragView.show(motionDownX, motionDownY);
     }
 
-    public boolean onForwardedEvent(MotionEvent ev, int activePointerId, MotionEvent touchDownEvent) {
-        mTouchDown = new Point((int) touchDownEvent.getX(), (int) touchDownEvent.getY());
+    public boolean onForwardedEvent(MotionEvent ev, int activePointerId, Point touchDown) {
         mActivePointerId = activePointerId;
+        mTouchDown = touchDown;
         return dispatchTouchEvent(ev);
     }
 
@@ -313,9 +322,9 @@
      * @param y the y touch coordinate relative to this container
      */
     private boolean shouldStartDeferredDrag(int x, int y, boolean containerContainsTouch) {
-        Point closestEdge = new Point(mTouchDown.x, mIsAboveIcon ? getMeasuredHeight() : 0);
-        double distToEdge = Math.hypot(mTouchDown.x - closestEdge.x, mTouchDown.y - closestEdge.y);
-        double newDistToEdge = Math.hypot(x - closestEdge.x, y - closestEdge.y);
+        int closestEdgeY = mIsAboveIcon ? getMeasuredHeight() : 0;
+        double distToEdge = Math.abs(mTouchDown.y - closestEdgeY);
+        double newDistToEdge = Math.hypot(x - mTouchDown.x, y - closestEdgeY);
         return  !containerContainsTouch && (newDistToEdge - distToEdge > mStartDragThreshold);
     }
 
diff --git a/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java b/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
index efb5be5..63c8363 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
@@ -1,6 +1,7 @@
 package com.android.launcher3.shortcuts;
 
 import android.content.Context;
+import android.graphics.Point;
 import android.os.SystemClock;
 import android.view.HapticFeedbackConstants;
 import android.view.LayoutInflater;
@@ -53,6 +54,8 @@
     private Launcher mLauncher;
     private DragLayer mDragLayer;
     private MotionEvent mTouchDownEvent;
+    /** The coordinates of the touch down, relative do the shortcuts container. */
+    private final Point mTouchDown;
 
     public ShortcutsContainerListener(BubbleTextView icon) {
         mSrcIcon = icon;
@@ -64,8 +67,8 @@
         icon.addOnAttachStateChangeListener(this);
 
         mLauncher = Launcher.getLauncher(mSrcIcon.getContext());
-
         mDragLayer = mLauncher.getDragLayer();
+        mTouchDown = new Point();
     }
 
     @Override
@@ -76,6 +79,9 @@
         }
 
         if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            if (mTouchDownEvent != null) {
+                mTouchDownEvent.recycle();
+            }
             mTouchDownEvent = MotionEvent.obtainNoHistory(event);
         }
 
@@ -134,6 +140,10 @@
             deepShortcutsContainer.populateAndShow(mSrcIcon, ids);
             mSrcIcon.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                     HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+
+            // Convert touch down event to the container's coordinates.
+            Utilities.translateEventCoordinates(mSrcIcon, deepShortcutsContainer, mTouchDownEvent);
+            mTouchDown.set((int) mTouchDownEvent.getX(), (int) mTouchDownEvent.getY());
             return true;
         }
         return false;
@@ -252,16 +262,10 @@
         final MotionEvent dstEvent = MotionEvent.obtainNoHistory(srcEvent);
         Utilities.translateEventCoordinates(src, dst, dstEvent);
 
-        // Convert touch down event to destination-local coordinates.
-        // TODO: only create this once, or just store the x and y.
-        final MotionEvent touchDownEvent = MotionEvent.obtainNoHistory(mTouchDownEvent);
-        Utilities.translateEventCoordinates(src, dst, touchDownEvent);
-
         // Forward converted event to destination view, then recycle it.
         // TODO: don't create objects in onForwardedEvent.
-        final boolean handled = dst.onForwardedEvent(dstEvent, mActivePointerId, touchDownEvent);
+        final boolean handled = dst.onForwardedEvent(dstEvent, mActivePointerId, mTouchDown);
         dstEvent.recycle();
-        touchDownEvent.recycle();
 
         // Always cancel forwarding when the touch stream ends.
         final int action = srcEvent.getActionMasked();