Merge "Added new app launch crop / positioning."
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index 8e6a5b6..99c4dba 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -56,6 +56,7 @@
 import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.SystemProperties;
 import android.util.Pair;
 import android.view.View;
 
@@ -99,6 +100,9 @@
 
     private static final String TAG = "QuickstepTransition";
 
+    private static final boolean ENABLE_SHELL_STARTING_SURFACE =
+            SystemProperties.getBoolean("persist.debug.shell_starting_surface", false);
+
     /** Duration of status bar animations. */
     public static final int STATUS_BAR_TRANSITION_DURATION = 120;
 
@@ -442,9 +446,9 @@
             RemoteAnimationTargetCompat[] appTargets,
             RemoteAnimationTargetCompat[] wallpaperTargets,
             Rect windowTargetBounds, boolean toggleVisibility) {
-        RectF bounds = new RectF();
+        RectF launcherIconBounds = new RectF();
         FloatingIconView floatingView = FloatingIconView.getFloatingIconView(mLauncher, v,
-                toggleVisibility, bounds, true /* isOpening */);
+                toggleVisibility, launcherIconBounds, true /* isOpening */);
         Rect crop = new Rect();
         Matrix matrix = new Matrix();
 
@@ -458,11 +462,17 @@
         mDragLayer.getLocationOnScreen(dragLayerBounds);
 
         AnimOpenProperties prop = new AnimOpenProperties(mLauncher.getResources(), mDeviceProfile,
-                windowTargetBounds, bounds, v, dragLayerBounds);
+                windowTargetBounds, launcherIconBounds, v, dragLayerBounds[0], dragLayerBounds[1]);
+        int left = (int) (prop.cropCenterXStart - prop.cropWidthStart / 2);
+        int top = (int) (prop.cropCenterYStart - prop.cropHeightStart / 2);
+        int right = (int) (left + prop.cropWidthStart);
+        int bottom = (int) (top + prop.cropHeightStart);
+        // Set the crop here so we can calculate the corner radius below.
+        crop.set(left, top, right, bottom);
 
         RectF targetBounds = new RectF(windowTargetBounds);
-        RectF iconBounds = new RectF();
-        RectF temp = new RectF();
+        RectF floatingIconBounds = new RectF();
+        RectF tmpRectF = new RectF();
         Point tmpPos = new Point();
 
         AnimatorSet animatorSet = new AnimatorSet();
@@ -481,68 +491,79 @@
         });
 
         final float initialWindowRadius = supportsRoundedCornersOnWindows(mLauncher.getResources())
-                ? prop.startCrop / 2f : 0f;
+                ? Math.max(crop.width(), crop.height()) / 2f
+                : 0f;
         final float finalWindowRadius = mDeviceProfile.isMultiWindowMode
                 ? 0 : getWindowCornerRadius(mLauncher.getResources());
 
         appAnimator.addUpdateListener(new MultiValueUpdateListener() {
             FloatProp mDx = new FloatProp(0, prop.dX, 0, prop.xDuration, AGGRESSIVE_EASE);
             FloatProp mDy = new FloatProp(0, prop.dY, 0, prop.yDuration, AGGRESSIVE_EASE);
-            FloatProp mScale = new FloatProp(prop.initialAppIconScale,
+
+            FloatProp mIconScaleToFitScreen = new FloatProp(prop.initialAppIconScale,
                     prop.finalAppIconScale, 0, APP_LAUNCH_DURATION, EXAGGERATED_EASE);
             FloatProp mIconAlpha = new FloatProp(prop.iconAlphaStart, 0f,
                     APP_LAUNCH_ALPHA_START_DELAY, prop.alphaDuration, LINEAR);
-            FloatProp mCroppedSize = new FloatProp(prop.startCrop, prop.endCrop, 0, CROP_DURATION,
-                    EXAGGERATED_EASE);
+
             FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius, 0,
                     RADIUS_DURATION, EXAGGERATED_EASE);
             FloatProp mShadowRadius = new FloatProp(0, mMaxShadowRadius, 0,
                     APP_LAUNCH_DURATION, EXAGGERATED_EASE);
 
+            FloatProp mCropRectCenterX = new FloatProp(prop.cropCenterXStart, prop.cropCenterXEnd,
+                    0, CROP_DURATION, EXAGGERATED_EASE);
+            FloatProp mCropRectCenterY = new FloatProp(prop.cropCenterYStart, prop.cropCenterYEnd,
+                    0, CROP_DURATION, EXAGGERATED_EASE);
+            FloatProp mCropRectWidth = new FloatProp(prop.cropWidthStart, prop.cropWidthEnd, 0,
+                    CROP_DURATION, EXAGGERATED_EASE);
+            FloatProp mCropRectHeight = new FloatProp(prop.cropHeightStart, prop.cropHeightEnd, 0,
+                    CROP_DURATION, EXAGGERATED_EASE);
+
             @Override
             public void onUpdate(float percent) {
                 // Calculate the size of the scaled icon.
-                float width = bounds.width() * mScale.value;
-                float height = bounds.height() * mScale.value;
+                float iconWidth = launcherIconBounds.width() * mIconScaleToFitScreen.value;
+                float iconHeight = launcherIconBounds.height() * mIconScaleToFitScreen.value;
 
-                // Animate the crop so that it starts off as a square.
-                final int cropWidth;
-                final int cropHeight;
-                if (mDeviceProfile.isVerticalBarLayout()) {
-                    cropWidth = (int) mCroppedSize.value;
-                    cropHeight = windowTargetBounds.height();
-                } else {
-                    cropWidth = windowTargetBounds.width();
-                    cropHeight = (int) mCroppedSize.value;
-                }
-                crop.set(0, 0, cropWidth, cropHeight);
+                int left = (int) (mCropRectCenterX.value - mCropRectWidth.value / 2);
+                int top = (int) (mCropRectCenterY.value - mCropRectHeight.value / 2);
+                int right = (int) (left + mCropRectWidth.value);
+                int bottom = (int) (top + mCropRectHeight.value);
+                crop.set(left, top, right, bottom);
+
+                final int windowCropWidth = crop.width();
+                final int windowCropHeight = crop.height();
 
                 // Scale the size of the icon to match the size of the window crop.
-                float scaleX = width / cropWidth;
-                float scaleY = height / cropHeight;
+                float scaleX = iconWidth / windowCropWidth;
+                float scaleY = iconHeight / windowCropHeight;
                 float scale = Math.min(1f, Math.max(scaleX, scaleY));
 
-                float scaledCropWidth = cropWidth * scale;
-                float scaledCropHeight = cropHeight * scale;
-                float offsetX  = (scaledCropWidth - width) / 2;
-                float offsetY = (scaledCropHeight - height) / 2;
+                float scaledCropWidth = windowCropWidth * scale;
+                float scaledCropHeight = windowCropHeight * scale;
+                float offsetX  = (scaledCropWidth - iconWidth) / 2;
+                float offsetY = (scaledCropHeight - iconHeight) / 2;
 
                 // Calculate the window position to match the icon position.
-                temp.set(bounds);
-                temp.offset(dragLayerBounds[0], dragLayerBounds[1]);
-                temp.offset(mDx.value, mDy.value);
-                Utilities.scaleRectFAboutCenter(temp, mScale.value);
-                float windowTransX0 = temp.left - offsetX;
-                float windowTransY0 = temp.top - offsetY;
+                tmpRectF.set(launcherIconBounds);
+                tmpRectF.offset(dragLayerBounds[0], dragLayerBounds[1]);
+                tmpRectF.offset(mDx.value, mDy.value);
+                Utilities.scaleRectFAboutCenter(tmpRectF, mIconScaleToFitScreen.value);
+                float windowTransX0 = tmpRectF.left - offsetX;
+                float windowTransY0 = tmpRectF.top - offsetY;
+                if (ENABLE_SHELL_STARTING_SURFACE) {
+                    windowTransX0 -= crop.left * scale;
+                    windowTransY0 -= crop.top * scale;
+                }
 
                 // Calculate the icon position.
-                iconBounds.set(bounds);
-                iconBounds.offset(mDx.value, mDy.value);
-                Utilities.scaleRectFAboutCenter(iconBounds, mScale.value);
-                iconBounds.left -= offsetX;
-                iconBounds.top -= offsetY;
-                iconBounds.right += offsetX;
-                iconBounds.bottom += offsetY;
+                floatingIconBounds.set(launcherIconBounds);
+                floatingIconBounds.offset(mDx.value, mDy.value);
+                Utilities.scaleRectFAboutCenter(floatingIconBounds, mIconScaleToFitScreen.value);
+                floatingIconBounds.left -= offsetX;
+                floatingIconBounds.top -= offsetY;
+                floatingIconBounds.right += offsetX;
+                floatingIconBounds.bottom += offsetY;
 
                 SurfaceParams[] params = new SurfaceParams[appTargets.length];
                 for (int i = appTargets.length - 1; i >= 0; i--) {
@@ -553,7 +574,7 @@
                         matrix.setScale(scale, scale);
                         matrix.postTranslate(windowTransX0, windowTransY0);
 
-                        floatingView.update(iconBounds, mIconAlpha.value, percent, 0f,
+                        floatingView.update(floatingIconBounds, mIconAlpha.value, percent, 0f,
                                 mWindowRadius.value * scale, true /* isOpening */);
                         builder.withMatrix(matrix)
                                 .withWindowCrop(crop)
@@ -932,8 +953,15 @@
      */
     static class AnimOpenProperties {
 
-        public final float startCrop;
-        public final float endCrop;
+        public final int cropCenterXStart;
+        public final int cropCenterYStart;
+        public final int cropWidthStart;
+        public final int cropHeightStart;
+
+        public final int cropCenterXEnd;
+        public final int cropCenterYEnd;
+        public final int cropWidthEnd;
+        public final int cropHeightEnd;
 
         public final float dX;
         public final float dY;
@@ -948,7 +976,7 @@
         public final float iconAlphaStart;
 
         AnimOpenProperties(Resources r, DeviceProfile dp, Rect windowTargetBounds,
-                RectF launcherIconBounds, View view, int[] dragLayerBounds) {
+                RectF launcherIconBounds, View view, int dragLayerLeft, int dragLayerTop) {
             // Scale the app icon to take up the entire screen. This simplifies the math when
             // animating the app window position / scale.
             float smallestSize = Math.min(windowTargetBounds.height(), windowTargetBounds.width());
@@ -966,8 +994,8 @@
             finalAppIconScale = Math.max(maxScaleX, maxScaleY);
 
             // Animate the app icon to the center of the window bounds in screen coordinates.
-            float centerX = windowTargetBounds.centerX() - dragLayerBounds[0];
-            float centerY = windowTargetBounds.centerY() - dragLayerBounds[1];
+            float centerX = windowTargetBounds.centerX() - dragLayerLeft;
+            float centerY = windowTargetBounds.centerY() - dragLayerTop;
 
             dX = centerX - launcherIconBounds.centerX();
             dY = centerY - launcherIconBounds.centerY();
@@ -981,15 +1009,31 @@
             alphaDuration = useUpwardAnimation ? APP_LAUNCH_ALPHA_DURATION
                     : APP_LAUNCH_ALPHA_DOWN_DURATION;
 
-            if (dp.isVerticalBarLayout()) {
-                startCrop = windowTargetBounds.height();
-                endCrop = windowTargetBounds.width();
+            if (ENABLE_SHELL_STARTING_SURFACE) {
+                iconAlphaStart = 0;
+
+                // TOOD: Share value from shell when available.
+                final float windowIconSize = Utilities.pxFromSp(108, r.getDisplayMetrics());
+
+                cropCenterXStart = windowTargetBounds.centerX();
+                cropCenterYStart = windowTargetBounds.centerY();
+
+                cropWidthStart = (int) windowIconSize;
+                cropHeightStart = (int) windowIconSize;
             } else {
-                startCrop = windowTargetBounds.width();
-                endCrop = windowTargetBounds.height();
+                iconAlphaStart = 1;
+
+                cropWidthStart = cropHeightStart =
+                        Math.min(windowTargetBounds.width(), windowTargetBounds.height());
+                cropCenterXStart = cropCenterYStart =
+                        Math.min(windowTargetBounds.centerX(), windowTargetBounds.centerY());
             }
 
-            iconAlphaStart = 1f;
+            cropWidthEnd = windowTargetBounds.width();
+            cropHeightEnd = windowTargetBounds.height();
+
+            cropCenterXEnd = windowTargetBounds.centerX();
+            cropCenterYEnd = windowTargetBounds.centerY();
         }
     }
 }