Merge changes Ia255a7af,I74e74e54 into ub-launcher3-master

* changes:
  Animate TaskView as you swipe down on it to launch
  Calculate task view animation instead of using dimens
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index e354193..ab6d8af 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -33,9 +33,6 @@
     <!-- Launcher app transition -->
     <dimen name="content_trans_y">25dp</dimen>
     <dimen name="workspace_trans_y">80dp</dimen>
-    <dimen name="recents_adjacent_trans_x">140dp</dimen>
-    <dimen name="recents_adjacent_trans_y">80dp</dimen>
-    <fraction name="recents_adjacent_scale">150%</fraction>
 
     <dimen name="recents_empty_message_text_size">16sp</dimen>
     <dimen name="recents_empty_message_text_padding">16dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 5a090d9..f1471a7 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -17,6 +17,7 @@
 package com.android.launcher3;
 
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
 import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber;
@@ -55,13 +56,12 @@
 import com.android.launcher3.anim.PropertyListBuilder;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.graphics.DrawableFactory;
-import com.android.launcher3.shortcuts.DeepShortcutTextView;
 import com.android.launcher3.shortcuts.DeepShortcutView;
 import com.android.quickstep.RecentsAnimationInterpolator;
 import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds;
 import com.android.quickstep.views.RecentsView;
-import com.android.systemui.shared.recents.model.Task;
 import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.ActivityCompat;
 import com.android.systemui.shared.system.ActivityOptionsCompat;
 import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
@@ -104,9 +104,6 @@
 
     private final float mContentTransY;
     private final float mWorkspaceTransY;
-    private final float mRecentsTransX;
-    private final float mRecentsTransY;
-    private final float mRecentsScale;
 
     private DeviceProfile mDeviceProfile;
     private View mFloatingView;
@@ -129,9 +126,6 @@
         Resources res = mLauncher.getResources();
         mContentTransY = res.getDimensionPixelSize(R.dimen.content_trans_y);
         mWorkspaceTransY = res.getDimensionPixelSize(R.dimen.workspace_trans_y);
-        mRecentsTransX = res.getDimensionPixelSize(R.dimen.recents_adjacent_trans_x);
-        mRecentsTransY = res.getDimensionPixelSize(R.dimen.recents_adjacent_trans_y);
-        mRecentsScale = res.getFraction(R.fraction.recents_adjacent_scale, 1, 1);
 
         mLauncher.addOnDeviceProfileChangeListener(this);
         registerRemoteAnimations();
@@ -154,14 +148,7 @@
 
                     @Override
                     public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
-                        Animator[] anims = composeRecentsLaunchAnimator(v, targetCompats);
-                        AnimatorSet anim = new AnimatorSet();
-                        if (anims != null) {
-                            anim.playTogether(anims);
-                        } else {
-                            anim.play(getLauncherAnimators(v, targetCompats));
-                            anim.play(getWindowAnimators(v, targetCompats));
-                        }
+                        AnimatorSet anim = createLaunchAnimatorForView(v, targetCompats);
                         mLauncher.getStateManager().setCurrentAnimation(anim);
                         return anim;
                     }
@@ -180,6 +167,19 @@
         return getDefaultActivityLaunchOptions(launcher, v);
     }
 
+    private AnimatorSet createLaunchAnimatorForView(View v, RemoteAnimationTargetCompat[] targets) {
+        Animator[] anims = composeRecentsLaunchAnimator(v, new AnimConfig(targets,
+                RECENTS_LAUNCH_DURATION, Interpolators.TOUCH_RESPONSE_INTERPOLATOR));
+        AnimatorSet anim = new AnimatorSet();
+        if (anims != null) {
+            anim.playTogether(anims);
+        } else {
+            anim.play(getLauncherAnimators(v, targets));
+            anim.play(getWindowAnimators(v, targets));
+        }
+        return anim;
+    }
+
     /**
      * Try to find a TaskView that corresponds with the component of the launched view.
      *
@@ -238,21 +238,32 @@
         return taskView;
     }
 
+    public AnimatorSet composeUserControlledRecentsLaunchAnimator(TaskView v, AnimConfig config) {
+        Animator[] anims = composeRecentsLaunchAnimator(v, config);
+        AnimatorSet anim = new AnimatorSet();
+        anim.playTogether(anims);
+        return anim;
+    }
+
     /**
      * Composes the animations for a launch from the recents list if possible.
      */
-    private Animator[] composeRecentsLaunchAnimator(View v,
-            RemoteAnimationTargetCompat[] targets) {
+    private Animator[] composeRecentsLaunchAnimator(View v, AnimConfig config) {
         // Ensure recents is actually visible
         if (!mLauncher.getStateManager().getState().overviewUi) {
             return null;
         }
 
         RecentsView recentsView = mLauncher.getOverviewPanel();
-        boolean launcherClosing = launcherIsATargetWithMode(targets, MODE_CLOSING);
+        boolean launcherClosing = launcherIsATargetWithMode(config.targets, MODE_CLOSING);
+        if (config.userControlled) {
+            // We don't pass any targets when creating a user-controlled animation. In this case,
+            // assume launcher is closing.
+            launcherClosing = true;
+        }
         boolean skipLauncherChanges = !launcherClosing;
 
-        TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets);
+        TaskView taskView = findTaskViewToLaunch(mLauncher, v, config.targets);
         if (taskView == null) {
             return null;
         }
@@ -261,7 +272,7 @@
         Animator launcherAnim;
         final AnimatorListenerAdapter windowAnimEndListener;
         if (launcherClosing) {
-            launcherAnim = getRecentsLauncherAnimator(recentsView, taskView);
+            launcherAnim = getRecentsLauncherAnimator(recentsView, taskView, config);
             // Make sure recents gets fixed up by resetting task alphas and scales, etc.
             windowAnimEndListener = mReapplyStateListener;
         } else {
@@ -278,8 +289,12 @@
             };
         }
 
-        Animator windowAnim = getRecentsWindowAnimator(taskView, skipLauncherChanges, targets);
-        windowAnim.addListener(windowAnimEndListener);
+        Animator windowAnim = getRecentsWindowAnimator(taskView, skipLauncherChanges, config);
+        if (!config.userControlled) {
+            // Don't reset properties if the animation is user-controlled, as we will run the
+            // "real" (not user controlled) animation from where they left off when they let go.
+            windowAnim.addListener(windowAnimEndListener);
+        }
         return new Animator[] {launcherAnim, windowAnim};
     }
 
@@ -289,23 +304,33 @@
      * If launching one of the adjacent tasks, parallax the center task and other adjacent task
      * to the right.
      */
-    private Animator getRecentsLauncherAnimator(RecentsView recentsView, TaskView v) {
+    private Animator getRecentsLauncherAnimator(RecentsView recentsView, TaskView v,
+            AnimConfig config) {
         AnimatorSet launcherAnimator = new AnimatorSet();
 
         int launchedTaskIndex = recentsView.indexOfChild(v);
         int centerTaskIndex = recentsView.getCurrentPage();
         boolean launchingCenterTask = launchedTaskIndex == centerTaskIndex;
         boolean isRtl = recentsView.isRtl();
+
+        RecentsAnimationInterpolator recentsInterpolator = getRecentsInterpolator(v);
+        TaskWindowBounds endInterpolation = recentsInterpolator.interpolate(1);
+        float toScale = endInterpolation.taskScale;
+        float toTranslationY = endInterpolation.taskY;
+        float displacementX = v.getWidth() * (toScale - v.getScaleX());
         if (launchingCenterTask) {
+
             if (launchedTaskIndex - 1 >= 0) {
                 TaskView adjacentPage1 = (TaskView) recentsView.getPageAt(launchedTaskIndex - 1);
                 ObjectAnimator adjacentTask1ScaleAndTranslate =
                         LauncherAnimUtils.ofPropertyValuesHolder(adjacentPage1,
                                 new PropertyListBuilder()
-                                        .scale(adjacentPage1.getScaleX() * mRecentsScale)
-                                        .translationY(mRecentsTransY)
-                                        .translationX(isRtl ? mRecentsTransX : -mRecentsTransX)
+                                        .scale(adjacentPage1.getScaleX() * toScale)
+                                        .translationY(toTranslationY)
+                                        .translationX(isRtl ? displacementX : -displacementX)
                                         .build());
+                adjacentTask1ScaleAndTranslate.setInterpolator(config.interpolator);
+                adjacentTask1ScaleAndTranslate.setDuration(config.duration);
                 launcherAnimator.play(adjacentTask1ScaleAndTranslate);
             }
             if (launchedTaskIndex + 1 < recentsView.getPageCount()) {
@@ -313,21 +338,24 @@
                 ObjectAnimator adjacentTask2ScaleAndTranslate =
                         LauncherAnimUtils.ofPropertyValuesHolder(adjacentTask2,
                                 new PropertyListBuilder()
-                                        .scale(adjacentTask2.getScaleX() * mRecentsScale)
-                                        .translationY(mRecentsTransY)
-                                        .translationX(isRtl ? -mRecentsTransX : mRecentsTransX)
+                                        .scale(adjacentTask2.getScaleX() * toScale)
+                                        .translationY(toTranslationY)
+                                        .translationX(isRtl ? -displacementX : displacementX)
                                         .build());
+                adjacentTask2ScaleAndTranslate.setInterpolator(config.interpolator);
+                adjacentTask2ScaleAndTranslate.setDuration(config.duration);
                 launcherAnimator.play(adjacentTask2ScaleAndTranslate);
             }
         } else {
             // We are launching an adjacent task, so parallax the center and other adjacent task.
             TaskView centerTask = (TaskView) recentsView.getPageAt(centerTaskIndex);
-            float translationX = mRecentsTransX / 2;
             ObjectAnimator centerTaskParallaxOffscreen =
                     LauncherAnimUtils.ofPropertyValuesHolder(centerTask,
                             new PropertyListBuilder()
-                                    .translationX(isRtl ? -translationX : translationX)
+                                    .translationX(isRtl ? -displacementX : displacementX)
                                     .build());
+            centerTaskParallaxOffscreen.setInterpolator(config.interpolator);
+            centerTaskParallaxOffscreen.setDuration(config.duration);
             launcherAnimator.play(centerTaskParallaxOffscreen);
             int otherAdjacentTaskIndex = centerTaskIndex + (centerTaskIndex - launchedTaskIndex);
             if (otherAdjacentTaskIndex >= 0
@@ -337,14 +365,26 @@
                 ObjectAnimator otherAdjacentTaskParallaxOffscreen =
                         LauncherAnimUtils.ofPropertyValuesHolder(otherAdjacentTask,
                                 new PropertyListBuilder()
-                                        .translationX(isRtl ? -translationX : translationX)
+                                        .translationX(isRtl ? -displacementX : displacementX)
+                                        .scale(1)
                                         .build());
+                otherAdjacentTaskParallaxOffscreen.setInterpolator(config.interpolator);
+                otherAdjacentTaskParallaxOffscreen.setDuration(config.duration);
                 launcherAnimator.play(otherAdjacentTaskParallaxOffscreen);
             }
         }
 
+        float allAppsProgressOffscreen = ALL_APPS_PROGRESS_OFF_SCREEN;
+        LauncherState state = mLauncher.getStateManager().getState();
+        if ((state.getVisibleElements(mLauncher) & ALL_APPS_HEADER_EXTRA) != 0) {
+            float maxShiftRange = mDeviceProfile.heightPx;
+            float currShiftRange = mLauncher.getAllAppsController().getShiftRange();
+            allAppsProgressOffscreen = 1f + (maxShiftRange - currShiftRange) / maxShiftRange;
+        }
         Animator allAppsSlideOut = ObjectAnimator.ofFloat(mLauncher.getAllAppsController(),
-                ALL_APPS_PROGRESS, ALL_APPS_PROGRESS_OFF_SCREEN);
+                ALL_APPS_PROGRESS, allAppsProgressOffscreen);
+        allAppsSlideOut.setInterpolator(config.interpolator);
+        allAppsSlideOut.setDuration(config.duration);
         launcherAnimator.play(allAppsSlideOut);
 
         Workspace workspace = mLauncher.getWorkspace();
@@ -355,40 +395,44 @@
                         .translationX(workspaceScaleAndTranslation[1])
                         .translationY(workspaceScaleAndTranslation[2])
                         .build());
+        recenterWorkspace.setInterpolator(config.interpolator);
+        recenterWorkspace.setDuration(config.duration);
         launcherAnimator.play(recenterWorkspace);
         CellLayout currentWorkspacePage = (CellLayout) workspace.getPageAt(
                 workspace.getCurrentPage());
 
-        launcherAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
-        launcherAnimator.setDuration(RECENTS_LAUNCH_DURATION);
         return launcherAnimator;
     }
 
+    private RecentsAnimationInterpolator getRecentsInterpolator(TaskView v) {
+        Rect taskViewBounds = new Rect();
+        mDragLayer.getDescendantRectRelativeToSelf(v, taskViewBounds);
+
+        // TODO: Use the actual target insets instead of the current thumbnail insets in case the
+        // device state has changed
+        return new RecentsAnimationInterpolator(
+                new Rect(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx),
+                v.getThumbnail().getInsets(),
+                taskViewBounds,
+                new Rect(0, v.getThumbnail().getTop(), 0, 0),
+                v.getScaleX(),
+                v.getTranslationX());
+    }
+
     /**
      * @return Animator that controls the window of the opening targets for the recents launch
      * animation.
      */
     private ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipLauncherChanges,
-            RemoteAnimationTargetCompat[] targets) {
-        Rect taskViewBounds = new Rect();
-        mDragLayer.getDescendantRectRelativeToSelf(v, taskViewBounds);
-
-        // TODO: Use the actual target insets instead of the current thumbnail insets in case the
-        // device state has changed
-        RecentsAnimationInterpolator recentsInterpolator = new RecentsAnimationInterpolator(
-                new Rect(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx),
-                v.getThumbnail().getInsets(),
-                taskViewBounds,
-                new Rect(0, v.getThumbnail().getTop(), 0, 0),
-                v.getScaleX(),
-                v.getTranslationX());
+            AnimConfig config) {
+        final RecentsAnimationInterpolator recentsInterpolator = getRecentsInterpolator(v);
 
         Rect crop = new Rect();
         Matrix matrix = new Matrix();
 
         ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
-        appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
-        appAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
+        appAnimator.setDuration(config.duration);
+        appAnimator.setInterpolator(config.interpolator);
         appAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             boolean isFirstFrame = true;
 
@@ -404,14 +448,17 @@
                 final float percent = animation.getAnimatedFraction();
                 TaskWindowBounds tw = recentsInterpolator.interpolate(percent);
 
+                float alphaDuration = 75;
                 if (!skipLauncherChanges) {
                     v.setScaleX(tw.taskScale);
                     v.setScaleY(tw.taskScale);
                     v.setTranslationX(tw.taskX);
                     v.setTranslationY(tw.taskY);
-                    // Defer fading out the view until after the app window gets faded in
-                    v.setAlpha(getValue(1f, 0f, 75, 75,
-                            appAnimator.getDuration() * percent, Interpolators.LINEAR));
+                    if (!config.userControlled) {
+                        // Defer fading out the view until after the app window gets faded in
+                        v.setAlpha(getValue(1f, 0f, alphaDuration, alphaDuration,
+                                appAnimator.getDuration() * percent, Interpolators.LINEAR));
+                    }
                 }
 
                 matrix.setScale(tw.winScale, tw.winScale);
@@ -419,12 +466,11 @@
                 crop.set(tw.winCrop);
 
                 // Fade in the app window.
-                float alphaDuration = 75;
                 float alpha = getValue(0f, 1f, 0, alphaDuration,
                         appAnimator.getDuration() * percent, Interpolators.LINEAR);
 
                 TransactionCompat t = new TransactionCompat();
-                for (RemoteAnimationTargetCompat target : targets) {
+                for (RemoteAnimationTargetCompat target : config.targets) {
                     if (target.mode == RemoteAnimationTargetCompat.MODE_OPENING) {
                         t.setAlpha(target.leash, alpha);
 
@@ -921,4 +967,24 @@
         newPercent = i.getInterpolation(newPercent);
         return end * newPercent + start * (1 - newPercent);
     }
+
+    public static class AnimConfig {
+        public RemoteAnimationTargetCompat[] targets;
+        public long duration;
+        public Interpolator interpolator;
+
+        public boolean userControlled = false;
+
+        public AnimConfig(RemoteAnimationTargetCompat[] targets, long duration,
+                Interpolator interpolator) {
+            this.targets = targets;
+            this.duration = duration;
+            this.interpolator = interpolator;
+        }
+
+        public AnimConfig(long duration, Interpolator interpolator) {
+            this(new RemoteAnimationTargetCompat[0], duration, interpolator);
+            userControlled = true;
+        }
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
index d11547d..dca0018 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
@@ -28,8 +28,11 @@
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppTransitionManagerImpl;
+import com.android.launcher3.LauncherAppTransitionManagerImpl.AnimConfig;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.touch.SwipeDetector;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
@@ -167,8 +170,10 @@
                     .wrap(mPendingAnimation.anim, maxDuration);
             mEndDisplacement = -mTaskBeingDragged.getHeight();
         } else {
-            AnimatorSet anim = new AnimatorSet();
-            // TODO: Setup a zoom animation
+            LauncherAppTransitionManagerImpl appTransitionManager =
+                    (LauncherAppTransitionManagerImpl) mLauncher.getAppTransitionManager();
+            AnimatorSet anim = appTransitionManager.composeUserControlledRecentsLaunchAnimator(
+                    mTaskBeingDragged, new AnimConfig(maxDuration, Interpolators.ZOOM_IN));
             mCurrentAnimation = AnimatorPlaybackController.wrap(anim, maxDuration);
 
             mTempCords[1] = mTaskBeingDragged.getHeight();
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationInterpolator.java b/quickstep/src/com/android/quickstep/RecentsAnimationInterpolator.java
index 1f9c728..fdeb0c1 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationInterpolator.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationInterpolator.java
@@ -79,8 +79,8 @@
         Rect finalScaledTaskInsets = new Rect(taskInsets);
         Utilities.scaleRect(finalScaledTaskInsets, mFinalTaskScale);
         mTargetTask = new Rect(mInsetWindow);
-        mTargetTask.offsetTo(window.top + insets.top - finalScaledTaskInsets.top,
-                window.left + insets.left - finalScaledTaskInsets.left);
+        mTargetTask.offsetTo(window.left + insets.left - finalScaledTaskInsets.left,
+                window.top + insets.top - finalScaledTaskInsets.top);
 
         float initialWinScale = 1f / mFinalTaskScale;
         Rect scaledWindow = new Rect(mInsetWindow);
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 55ed9a9..ad0e253 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -26,7 +26,6 @@
 import android.util.FloatProperty;
 import android.view.View;
 import android.view.ViewDebug;
-import android.widget.FrameLayout;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
@@ -92,11 +91,7 @@
         mInsets.set(insets);
         DeviceProfile dp = mActivity.getDeviceProfile();
         Rect padding = getPadding(dp, getContext());
-        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
-        lp.bottomMargin = padding.bottom;
-        setLayoutParams(lp);
-
-        setPadding(padding.left, padding.top, padding.right, 0);
+        setPadding(padding.left, padding.top, padding.right, padding.bottom);
         mPagePadding.set(padding);
         mPagePadding.top += getResources().getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
     }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 002dd1a..056404e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1684,6 +1684,10 @@
                 : mAppTransitionManager.getActivityLaunchOptions(this, v);
     }
 
+    public LauncherAppTransitionManager getAppTransitionManager() {
+        return mAppTransitionManager;
+    }
+
     @TargetApi(Build.VERSION_CODES.M)
     @Override
     protected boolean onErrorStartingShortcut(Intent intent, ItemInfo info) {
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 68e9847..6fea201 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -206,7 +206,6 @@
                 anim.setCurrentPlayTime(Math.min(playPos, anim.getDuration()));
             }
         }
-
     }
 
     private class OnAnimationEndDispatcher extends AnimationSuccessListener {