Merge "Disable ShortcutsLaunchTest.testAppLauncher*" into ub-launcher3-master
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index b9f95cc..cded799 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -19,7 +19,7 @@
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_MOVE;
 import static android.view.MotionEvent.ACTION_POINTER_DOWN;
-import static android.view.MotionEvent.ACTION_POINTER_UP;
+import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
 import static android.view.MotionEvent.ACTION_UP;
 
 import static com.android.systemui.shared.system.ActivityManagerWrapper
@@ -52,6 +52,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.ChoreographerCompat;
 import com.android.systemui.shared.system.NavigationBarCompat.HitTarget;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
@@ -299,7 +300,7 @@
             mActivityHelper = activityHelper;
             mActivity = activity;
             mTarget = activity.getDragLayer();
-            mTouchSlop = ViewConfiguration.get(mTarget.getContext()).getScaledTouchSlop();
+            mTouchSlop = ViewConfiguration.get(mActivity).getScaledTouchSlop();
             mStartingInActivityBounds = startingInActivityBounds;
 
             mQuickScrubController = mActivity.<RecentsView>getOverviewPanel()
@@ -324,12 +325,6 @@
                 mDownPos.set(ev.getX(), ev.getY());
             } else if (!mTrackingStarted) {
                 switch (action) {
-                    case ACTION_POINTER_UP:
-                    case ACTION_POINTER_DOWN:
-                        if (!mTrackingStarted) {
-                            mInvalidated = true;
-                        }
-                        break;
                     case ACTION_CANCEL:
                     case ACTION_UP:
                         startTouchTracking(ev, true /* updateLocationOffset */);
@@ -359,15 +354,26 @@
             }
 
             // Send down touch event
-            MotionEvent down = MotionEvent.obtain(ev);
+            MotionEvent down = MotionEvent.obtainNoHistory(ev);
             down.setAction(ACTION_DOWN);
             sendEvent(down);
-            down.recycle();
 
             mTrackingStarted = true;
+            // Send pointer down for remaining pointers.
+            int pointerCount = ev.getPointerCount();
+            for (int i = 1; i < pointerCount; i++) {
+                down.setAction(ACTION_POINTER_DOWN | (i << ACTION_POINTER_INDEX_SHIFT));
+                sendEvent(down);
+            }
+
+            down.recycle();
         }
 
         private void sendEvent(MotionEvent ev) {
+            if (!mTarget.verifyTouchDispatch(this, ev)) {
+                mInvalidated = true;
+                return;
+            }
             int flags = ev.getEdgeFlags();
             ev.setEdgeFlags(flags | TouchInteractionService.EDGE_NAV_BAR);
             ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 8ad3cee..bff3025 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -400,9 +400,6 @@
         final int y = (int) ev.getY();
         switch (ev.getAction()) {
             case MotionEvent.ACTION_UP:
-                if (mShowEmptyMessage) {
-                    onAllTasksRemoved();
-                }
                 if (mTouchDownToStartHome) {
                     startHome();
                 }
@@ -413,7 +410,8 @@
                 break;
             case MotionEvent.ACTION_MOVE:
                 // Passing the touch slop will not allow dismiss to home
-                if (mTouchDownToStartHome && Math.hypot(mDownX - x, mDownY - y) > mTouchSlop) {
+                if (mTouchDownToStartHome &&
+                        (isHandlingTouch() || Math.hypot(mDownX - x, mDownY - y) > mTouchSlop)) {
                     mTouchDownToStartHome = false;
                 }
                 break;
@@ -421,12 +419,17 @@
                 // Touch down anywhere but the deadzone around the visible clear all button and
                 // between the task views will start home on touch up
                 if (!isHandlingTouch()) {
-                    updateDeadZoneRects();
-                    final boolean clearAllButtonDeadZoneConsumed = mClearAllButton.getAlpha() == 1
-                            && mClearAllButtonDeadZoneRect.contains(x, y);
-                    if (!clearAllButtonDeadZoneConsumed
-                            && !mTaskViewDeadZoneRect.contains(x + getScrollX(), y)) {
+                    if (mShowEmptyMessage) {
                         mTouchDownToStartHome = true;
+                    } else {
+                        updateDeadZoneRects();
+                        final boolean clearAllButtonDeadZoneConsumed =
+                                mClearAllButton.getAlpha() == 1
+                                        && mClearAllButtonDeadZoneRect.contains(x, y);
+                        if (!clearAllButtonDeadZoneConsumed
+                                && !mTaskViewDeadZoneRect.contains(x + getScrollX(), y)) {
+                            mTouchDownToStartHome = true;
+                        }
                     }
                 }
                 mDownX = x;
@@ -666,10 +669,6 @@
         mHasVisibleTaskData.clear();
     }
 
-    protected void onAllTasksRemoved() {
-        startHome();
-    }
-
     protected abstract void startHome();
 
     public void reset() {
@@ -973,7 +972,7 @@
 
                if (getTaskViewCount() == 0) {
                    removeView(mClearAllButton);
-                   onAllTasksRemoved();
+                   startHome();
                } else {
                    snapToPageImmediately(pageToSnapTo);
                }
@@ -1002,7 +1001,7 @@
                 // Remove all the task views now
                 ActivityManagerWrapper.getInstance().removeAllRecentTasks();
                 removeAllViews();
-                onAllTasksRemoved();
+                startHome();
             }
             mPendingAnimation = null;
         });
diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java
index b4cbf65..244654b 100644
--- a/src/com/android/launcher3/icons/LauncherIcons.java
+++ b/src/com/android/launcher3/icons/LauncherIcons.java
@@ -30,6 +30,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Paint;
 import android.graphics.PaintFlagsDrawFilter;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -311,59 +312,49 @@
      * @param scale the scale to apply before drawing {@param icon} on the canvas
      */
     private Bitmap createIconBitmap(Drawable icon, float scale) {
-        int width = mIconBitmapSize;
-        int height = mIconBitmapSize;
-
-        if (icon instanceof PaintDrawable) {
-            PaintDrawable painter = (PaintDrawable) icon;
-            painter.setIntrinsicWidth(width);
-            painter.setIntrinsicHeight(height);
-        } else if (icon instanceof BitmapDrawable) {
-            // Ensure the bitmap has a density.
-            BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
-            Bitmap bitmap = bitmapDrawable.getBitmap();
-            if (bitmap != null && bitmap.getDensity() == Bitmap.DENSITY_NONE) {
-                bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
-            }
-        }
-
-        int sourceWidth = icon.getIntrinsicWidth();
-        int sourceHeight = icon.getIntrinsicHeight();
-        if (sourceWidth > 0 && sourceHeight > 0) {
-            // Scale the icon proportionally to the icon dimensions
-            final float ratio = (float) sourceWidth / sourceHeight;
-            if (sourceWidth > sourceHeight) {
-                height = (int) (width / ratio);
-            } else if (sourceHeight > sourceWidth) {
-                width = (int) (height * ratio);
-            }
-        }
-        // no intrinsic size --> use default size
-        int textureWidth = mIconBitmapSize;
-        int textureHeight = mIconBitmapSize;
-
-        Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
+        Bitmap bitmap = Bitmap.createBitmap(mIconBitmapSize, mIconBitmapSize,
                 Bitmap.Config.ARGB_8888);
         mCanvas.setBitmap(bitmap);
-
-        final int left = (textureWidth-width) / 2;
-        final int top = (textureHeight-height) / 2;
-
         mOldBounds.set(icon.getBounds());
+
         if (Utilities.ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
-            int offset = Math.max((int) Math.ceil(BLUR_FACTOR * textureWidth), Math.max(left, top));
-            int size = Math.max(width, height);
-            icon.setBounds(offset, offset, size - offset, size - offset);
+            int offset = Math.max((int) Math.ceil(BLUR_FACTOR * mIconBitmapSize),
+                    Math.round(mIconBitmapSize * (1 - scale) / 2 ));
+            icon.setBounds(offset, offset, mIconBitmapSize - offset, mIconBitmapSize - offset);
+            icon.draw(mCanvas);
         } else {
-            icon.setBounds(left, top, left+width, top+height);
+            if (icon instanceof BitmapDrawable) {
+                BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
+                Bitmap b = bitmapDrawable.getBitmap();
+                if (bitmap != null && b.getDensity() == Bitmap.DENSITY_NONE) {
+                    bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
+                }
+            }
+            int width = mIconBitmapSize;
+            int height = mIconBitmapSize;
+
+            int intrinsicWidth = icon.getIntrinsicWidth();
+            int intrinsicHeight = icon.getIntrinsicHeight();
+            if (intrinsicWidth > 0 && intrinsicHeight > 0) {
+                // Scale the icon proportionally to the icon dimensions
+                final float ratio = (float) intrinsicWidth / intrinsicHeight;
+                if (intrinsicWidth > intrinsicHeight) {
+                    height = (int) (width / ratio);
+                } else if (intrinsicHeight > intrinsicWidth) {
+                    width = (int) (height * ratio);
+                }
+            }
+            final int left = (mIconBitmapSize - width) / 2;
+            final int top = (mIconBitmapSize - height) / 2;
+            icon.setBounds(left, top, left + width, top + height);
+            mCanvas.save();
+            mCanvas.scale(scale, scale, mIconBitmapSize / 2, mIconBitmapSize / 2);
+            icon.draw(mCanvas);
+            mCanvas.restore();
+
         }
-        mCanvas.save();
-        mCanvas.scale(scale, scale, textureWidth / 2, textureHeight / 2);
-        icon.draw(mCanvas);
-        mCanvas.restore();
         icon.setBounds(mOldBounds);
         mCanvas.setBitmap(null);
-
         return bitmap;
     }
 
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 1faca15..5b8df13 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -16,6 +16,10 @@
 
 package com.android.launcher3.views;
 
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_UP;
+
 import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
 
 import android.content.Context;
@@ -79,6 +83,9 @@
     protected TouchController mActiveController;
     private TouchCompleteListener mTouchCompleteListener;
 
+    // Object controlling the current touch interaction
+    private Object mCurrentTouchOwner;
+
     public BaseDragLayer(Context context, AttributeSet attrs, int alphaChannelCount) {
         super(context, attrs);
         mActivity = (T) ActivityContext.lookupContext(context);
@@ -94,7 +101,7 @@
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         int action = ev.getAction();
 
-        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+        if (action == ACTION_UP || action == ACTION_CANCEL) {
             if (mTouchCompleteListener != null) {
                 mTouchCompleteListener.onTouchComplete();
             }
@@ -177,7 +184,7 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         int action = ev.getAction();
-        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+        if (action == ACTION_UP || action == ACTION_CANCEL) {
             if (mTouchCompleteListener != null) {
                 mTouchCompleteListener.onTouchComplete();
             }
@@ -192,6 +199,37 @@
         }
     }
 
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        return verifyTouchDispatch(this, ev) && super.dispatchTouchEvent(ev);
+    }
+
+    /**
+     * Returns true if the {@param caller} is allowed to dispatch {@param ev} on this view,
+     * false otherwise.
+     */
+    public boolean verifyTouchDispatch(Object caller, MotionEvent ev) {
+        int action = ev.getAction();
+        if (action == ACTION_DOWN) {
+            if (mCurrentTouchOwner != null) {
+                // Another touch in progress.
+                ev.setAction(ACTION_CANCEL);
+                super.dispatchTouchEvent(ev);
+                ev.setAction(action);
+            }
+            mCurrentTouchOwner = caller;
+            return true;
+        }
+        if (mCurrentTouchOwner != caller) {
+            // Someone else is controlling the touch
+            return false;
+        }
+        if (action == ACTION_UP || action == ACTION_CANCEL) {
+            mCurrentTouchOwner = null;
+        }
+        return true;
+    }
+
     /**
      * Determine the rect of the descendant in this DragLayer's coordinates
      *
diff --git a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
index a50a8b1..a0f4620 100644
--- a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
+++ b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
@@ -13,6 +13,7 @@
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.rule.ShellCommandRule;
 
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -27,12 +28,14 @@
     @Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
 
     @Test
+    @Ignore
     public void testDragIcon_portrait() throws Throwable {
         lockRotation(true);
         performTest();
     }
 
     @Test
+    @Ignore
     public void testDragIcon_landscape() throws Throwable {
         lockRotation(false);
         performTest();
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index aaea3d5..0635e11 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -41,6 +41,7 @@
 import com.android.launcher3.widget.WidgetCell;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -83,6 +84,7 @@
     }
 
     @Test
+    @Ignore
     public void testConfigCancelled_rotate() throws Throwable {
         runTest(true, false);
     }