Merge changes from topic "am-c2841e6a-5061-492f-abbf-dfb8b89ccc04" into ub-launcher3-master

* changes:
  [automerger] Fix some state issues with user-controlled animations am: 31fbd4c08b
  Fix some state issues with user-controlled animations
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 85ccf29..94aaf15 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -335,10 +335,14 @@
             launcherAnimator.play(dragLayerAlpha);
             launcherAnimator.play(dragLayerTransY);
             mDragLayer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+
+            // Pause page indicator animations as they lead to layer trashing.
+            mLauncher.getWorkspace().getPageIndicator().pauseAnimations();
             endListener = () -> {
                 mDragLayer.setLayerType(View.LAYER_TYPE_NONE, null);
                 mDragLayer.setAlpha(1);
                 mDragLayer.setTranslationY(0);
+                mLauncher.getWorkspace().getPageIndicator().skipAnimationsToEnd();
             };
         }
         return new Pair<>(launcherAnimator, endListener);
@@ -694,6 +698,13 @@
             workspaceAnimator.setStartDelay(LAUNCHER_RESUME_START_DELAY);
             workspaceAnimator.setDuration(333);
             workspaceAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+            currentPage.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            workspaceAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    currentPage.setLayerType(View.LAYER_TYPE_NONE, null);
+                }
+            });
 
             // Animate the shelf in two parts: slide in, and overeshoot.
             AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
@@ -715,7 +726,6 @@
             allAppsOvershoot.setDuration(153);
             allAppsOvershoot.setInterpolator(Interpolators.OVERSHOOT_0);
 
-
             anim.play(workspaceAnimator);
             anim.playSequentially(allAppsSlideIn, allAppsOvershoot);
             anim.addListener(mReapplyStateListener);
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index ab73074..168bd08 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -780,7 +780,7 @@
     }
 
     private static final class IconDB extends SQLiteCacheHelper {
-        private final static int RELEASE_VERSION = 21;
+        private final static int RELEASE_VERSION = 22;
 
         private final static String TABLE_NAME = "icons";
         private final static String COLUMN_ROWID = "rowid";
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 2c08169..af4faa8 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -318,7 +318,7 @@
             if (!internalStateHandled) {
                 // If we are not binding synchronously, show a fade in animation when
                 // the first page bind completes.
-                mDragLayer.setAlpha(0);
+                mLauncherView.setAlpha(0);
             }
         } else {
             // Pages bound synchronously.
@@ -2131,8 +2131,8 @@
 
     @Override
     public void finishFirstPageBind(final ViewOnDrawExecutor executor) {
-        if (mDragLayer.getAlpha() < 1) {
-            mDragLayer.animate().alpha(1).withEndAction(
+        if (mLauncherView.getAlpha() < 1) {
+            mLauncherView.animate().alpha(1).withEndAction(
                     executor == null ? null : executor::onLoadAnimationCompleted).start();
         } else if (executor != null) {
             executor.onLoadAnimationCompleted();
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 37405db..211d98f 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -45,6 +45,7 @@
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.uioverrides.AllAppsScrim;
 import com.android.launcher3.keyboard.FocusedItemDecorator;
@@ -122,6 +123,13 @@
     }
 
     @Override
+    protected void setDampedScrollShift(float shift) {
+        // Bound the shift amount to avoid content from drawing on top (Y-val) of the QSB.
+        float maxShift = getSearchView().getHeight() / 2f;
+        super.setDampedScrollShift(Utilities.boundToRange(shift, -maxShift, maxShift));
+    }
+
+    @Override
     public void onDeviceProfileChanged(DeviceProfile dp) {
         for (AdapterHolder holder : mAH) {
             if (holder.recyclerView != null) {
diff --git a/src/com/android/launcher3/graphics/IconNormalizer.java b/src/com/android/launcher3/graphics/IconNormalizer.java
index 81f3f90..a2a0801 100644
--- a/src/com/android/launcher3/graphics/IconNormalizer.java
+++ b/src/com/android/launcher3/graphics/IconNormalizer.java
@@ -24,6 +24,7 @@
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.PorterDuff;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -66,12 +67,10 @@
 
     private final int mMaxSize;
     private final Bitmap mBitmap;
-    private final Bitmap mBitmapARGB;
     private final Canvas mCanvas;
     private final Paint mPaintMaskShape;
     private final Paint mPaintMaskShapeOutline;
     private final byte[] mPixels;
-    private final int[] mPixelsARGB;
 
     private final Rect mAdaptiveIconBounds;
     private float mAdaptiveIconScale;
@@ -83,9 +82,6 @@
     private final Path mShapePath;
     private final Matrix mMatrix;
 
-    private final Paint mPaintIcon;
-    private final Canvas mCanvasARGB;
-
     /** package private **/
     IconNormalizer(Context context) {
         // Use twice the icon size as maximum size to avoid scaling down twice.
@@ -93,19 +89,11 @@
         mBitmap = Bitmap.createBitmap(mMaxSize, mMaxSize, Bitmap.Config.ALPHA_8);
         mCanvas = new Canvas(mBitmap);
         mPixels = new byte[mMaxSize * mMaxSize];
-        mPixelsARGB = new int[mMaxSize * mMaxSize];
         mLeftBorder = new float[mMaxSize];
         mRightBorder = new float[mMaxSize];
         mBounds = new Rect();
         mAdaptiveIconBounds = new Rect();
 
-        // Needed for isShape() method
-        mBitmapARGB = Bitmap.createBitmap(mMaxSize, mMaxSize, Bitmap.Config.ARGB_8888);
-        mCanvasARGB = new Canvas(mBitmapARGB);
-
-        mPaintIcon = new Paint();
-        mPaintIcon.setColor(Color.WHITE);
-
         mPaintMaskShape = new Paint();
         mPaintMaskShape.setColor(Color.RED);
         mPaintMaskShape.setStyle(Paint.Style.FILL);
@@ -115,7 +103,7 @@
         mPaintMaskShapeOutline.setStrokeWidth(2 * context.getResources().getDisplayMetrics().density);
         mPaintMaskShapeOutline.setStyle(Paint.Style.STROKE);
         mPaintMaskShapeOutline.setColor(Color.BLACK);
-        mPaintMaskShapeOutline.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+        mPaintMaskShapeOutline.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
 
         mShapePath = new Path();
         mMatrix = new Matrix();
@@ -141,8 +129,6 @@
         // Condition 2:
         // Actual icon (white) and the fitted shape (e.g., circle)(red) XOR operation
         // should generate transparent image, if the actual icon is equivalent to the shape.
-        mBitmapARGB.eraseColor(Color.TRANSPARENT);
-        mCanvasARGB.drawBitmap(mBitmap, 0, 0, mPaintIcon);
 
         // Fit the shape within the icon's bounding box
         mMatrix.reset();
@@ -151,31 +137,41 @@
         maskPath.transform(mMatrix, mShapePath);
 
         // XOR operation
-        mCanvasARGB.drawPath(mShapePath, mPaintMaskShape);
+        mCanvas.drawPath(mShapePath, mPaintMaskShape);
 
         // DST_OUT operation around the mask path outline
-        mCanvasARGB.drawPath(mShapePath, mPaintMaskShapeOutline);
+        mCanvas.drawPath(mShapePath, mPaintMaskShapeOutline);
 
         // Check if the result is almost transparent
-        return isTransparentBitmap(mBitmapARGB);
+        return isTransparentBitmap();
     }
 
     /**
      * Used to determine if certain the bitmap is transparent.
      */
-    private boolean isTransparentBitmap(Bitmap bitmap) {
-        int w = mBounds.width();
-        int h = mBounds.height();
-        bitmap.getPixels(mPixelsARGB, 0 /* the first index to write into the array */,
-                w /* stride */,
-                mBounds.left, mBounds.top,
-                w, h);
+    private boolean isTransparentBitmap() {
+        ByteBuffer buffer = ByteBuffer.wrap(mPixels);
+        buffer.rewind();
+        mBitmap.copyPixelsToBuffer(buffer);
+
+        int y = mBounds.top;
+        // buffer position
+        int index = y * mMaxSize;
+        // buffer shift after every row, width of buffer = mMaxSize
+        int rowSizeDiff = mMaxSize - mBounds.right;
+
         int sum = 0;
-        for (int i = w * h - 1; i >= 0; i--) {
-            if(Color.alpha(mPixelsARGB[i]) > MIN_VISIBLE_ALPHA) {
+        for (; y < mBounds.bottom; y++) {
+            index += mBounds.left;
+            for (int x = mBounds.left; x < mBounds.right; x++) {
+                if ((mPixels[index] & 0xFF) > MIN_VISIBLE_ALPHA) {
                     sum++;
+                }
+                index++;
             }
+            index += rowSizeDiff;
         }
+
         float percentageDiffPixels = ((float) sum) / (mBounds.width() * mBounds.height());
         return percentageDiffPixels < PIXEL_DIFF_PERCENTAGE_THRESHOLD;
     }
@@ -306,7 +302,7 @@
         mBounds.bottom = bottomY;
 
         if (outBounds != null) {
-            outBounds.set(((float) mBounds.left) / width, ((float) mBounds.top),
+            outBounds.set(((float) mBounds.left) / width, ((float) mBounds.top) / height,
                     1 - ((float) mBounds.right) / width,
                     1 - ((float) mBounds.bottom) / height);
         }
diff --git a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
index 3c16cde..1383f53 100644
--- a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
@@ -41,8 +41,9 @@
     private static final int LINE_ALPHA_ANIMATOR_INDEX = 0;
     private static final int NUM_PAGES_ANIMATOR_INDEX = 1;
     private static final int TOTAL_SCROLL_ANIMATOR_INDEX = 2;
+    private static final int ANIMATOR_COUNT = 3;
 
-    private ValueAnimator[] mAnimators = new ValueAnimator[3];
+    private ValueAnimator[] mAnimators = new ValueAnimator[ANIMATOR_COUNT];
 
     private final Handler mDelayedLineFadeHandler = new Handler(Looper.getMainLooper());
     private final Launcher mLauncher;
@@ -232,6 +233,28 @@
         mAnimators[animatorIndex].start();
     }
 
+    /**
+     * Pauses all currently running animations.
+     */
+    public void pauseAnimations() {
+        for (int i = 0; i < ANIMATOR_COUNT; i++) {
+            if (mAnimators[i] != null) {
+                mAnimators[i].pause();
+            }
+        }
+    }
+
+    /**
+     * Force-ends all currently running or paused animations.
+     */
+    public void skipAnimationsToEnd() {
+        for (int i = 0; i < ANIMATOR_COUNT; i++) {
+            if (mAnimators[i] != null) {
+                mAnimators[i].end();
+            }
+        }
+    }
+
     @Override
     public void setInsets(Rect insets) {
         DeviceProfile grid = mLauncher.getDeviceProfile();
diff --git a/src/com/android/launcher3/views/SpringRelativeLayout.java b/src/com/android/launcher3/views/SpringRelativeLayout.java
index a508191..598738b 100644
--- a/src/com/android/launcher3/views/SpringRelativeLayout.java
+++ b/src/com/android/launcher3/views/SpringRelativeLayout.java
@@ -97,7 +97,7 @@
         mActiveEdge = edge;
     }
 
-    private void setDampedScrollShift(float shift) {
+    protected void setDampedScrollShift(float shift) {
         if (shift != mDampedScrollShift) {
             mDampedScrollShift = shift;
             invalidate();