Merge "Don't play animation when docking stack with affordance"
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 0b7b6fc..303078b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -751,7 +751,8 @@
             int taskId = data.readInt();
             int createMode = data.readInt();
             boolean toTop = data.readInt() != 0;
-            moveTaskToDockedStack(taskId, createMode, toTop);
+            boolean animate = data.readInt() != 0;
+            moveTaskToDockedStack(taskId, createMode, toTop, animate);
             reply.writeNoException();
             return true;
         }
@@ -3577,7 +3578,7 @@
         reply.recycle();
     }
     @Override
-    public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop)
+    public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate)
             throws RemoteException
     {
         Parcel data = Parcel.obtain();
@@ -3586,6 +3587,7 @@
         data.writeInt(taskId);
         data.writeInt(createMode);
         data.writeInt(toTop ? 1 : 0);
+        data.writeInt(animate ? 1 : 0);
         mRemote.transact(MOVE_TASK_TO_DOCKED_STACK_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index db4f5c1..6594990 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -142,7 +142,7 @@
     public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
     public void moveTaskBackwards(int task) throws RemoteException;
     public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
-    public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop)
+    public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate)
             throws RemoteException;
     public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) throws RemoteException;
     public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode) throws RemoteException;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 618eb6f..834db10 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -35,6 +35,7 @@
 import android.view.AppTransitionAnimationSpec;
 import android.view.LayoutInflater;
 import android.view.View;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
@@ -539,7 +540,7 @@
         SystemServicesProxy ssp = Recents.getSystemServices();
         ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
         if (topTask != null && !SystemServicesProxy.isHomeStack(topTask.stackId)) {
-            ssp.startTaskInDockedMode(topTask.id,
+            ssp.moveTaskToDockedStack(topTask.id,
                     ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT);
             showRecents(false /* triggeredFromAltTab */, draggingInRecents);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 16d6929..03d5cf1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -311,6 +311,17 @@
         }
     }
 
+    /** Docks an already resumed task to the side of the screen. */
+    public void moveTaskToDockedStack(int taskId, int createMode) {
+        if (mIam == null) return;
+
+        try {
+            mIam.moveTaskToDockedStack(taskId, createMode, true /* onTop */, false /* animate */);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
     /** Returns the focused stack id. */
     public int getFocusedStack() {
         if (mIam == null) return -1;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 29173a5..03e3720 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4320,7 +4320,8 @@
                 }
                 if (task.stack.mStackId != launchStackId) {
                     mStackSupervisor.moveTaskToStackLocked(
-                            taskId, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents");
+                            taskId, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents",
+                            true /* animate */);
                 }
             }
 
@@ -9239,7 +9240,7 @@
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveActivityToStack: moving r=" + r
                         + " to stackId=" + stackId);
                 mStackSupervisor.moveTaskToStackLocked(r.task.taskId, stackId, ON_TOP, !FORCE_FOCUS,
-                        "moveActivityToStack");
+                        "moveActivityToStack", true /* animate */);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -9260,7 +9261,7 @@
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
                         + " to stackId=" + stackId + " toTop=" + toTop);
                 mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop, !FORCE_FOCUS,
-                        "moveTaskToStack");
+                        "moveTaskToStack", true /* animate */);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -9277,9 +9278,10 @@
      *                   and
      *                   {@link android.app.ActivityManager#DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT}
      * @param toTop If the task and stack should be moved to the top.
+     * @param animate Whether we should play an animation for the moving the task
      */
     @Override
-    public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop) {
+    public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate) {
         enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
                 "moveTaskToDockedStack()");
         synchronized (this) {
@@ -9289,7 +9291,8 @@
                         + " to createMode=" + createMode + " toTop=" + toTop);
                 mWindowManager.setDockedStackCreateMode(createMode);
                 mStackSupervisor.moveTaskToStackLocked(
-                        taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS, "moveTaskToDockedStack");
+                        taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS, "moveTaskToDockedStack",
+                        animate);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 124d2ef..722fc32 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3100,7 +3100,8 @@
                     final int count = tasks.size();
                     for (int i = 0; i < count; i++) {
                         moveTaskToStackLocked(tasks.get(i).taskId,
-                                FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, FORCE_FOCUS, "resizeStack");
+                                FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, FORCE_FOCUS, "resizeStack",
+                                true /* animate */);
                     }
 
                     // stack shouldn't contain anymore activities, so nothing to resume.
@@ -3336,7 +3337,7 @@
     }
 
     void moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
-            String reason) {
+            String reason, boolean animate) {
         final TaskRecord task = anyTaskForIdLocked(taskId);
         if (task == null) {
             Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
@@ -3357,7 +3358,7 @@
             // preserve the old window until the new one is drawn. This prevents having a gap
             // between the removal and addition, in which no window is visible. We also want the
             // entrance of the new window to be properly animated.
-            mWindowManager.setReplacingWindow(topActivity.appToken);
+            mWindowManager.setReplacingWindow(topActivity.appToken, animate);
         }
         final ActivityStack stack = moveTaskToStackUncheckedLocked(
                 task, stackId, toTop, forceFocus, "moveTaskToStack:" + reason);
@@ -3405,7 +3406,7 @@
             // There is only one activity in the task. So, we can just move the task over to the
             // pinned stack without re-parenting the activity in a different task.
             moveTaskToStackLocked(task.taskId, PINNED_STACK_ID, ON_TOP, FORCE_FOCUS,
-                    "moveTopActivityToPinnedStack");
+                    "moveTopActivityToPinnedStack", true /* animate */);
         } else {
             final ActivityStack pinnedStack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
             pinnedStack.moveActivityToStack(r);
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 3f4eaac..425ff9b 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -128,6 +128,8 @@
     boolean mWillReplaceWindow;
     // If true, the replaced window was already requested to be removed.
     boolean mReplacingRemoveRequested;
+    // Whether the replacement of the window should trigger app transition animation.
+    boolean mAnimateReplacingWindow;
     // If not null, the window that will be used to replace the old one. This is being set when
     // the window is added and unset when this window reports its first draw.
     WindowState mReplacingWindow;
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index f5e4e3b..804830e 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -196,7 +196,7 @@
                                     ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
                                     : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
                             mService.mActivityManager.moveTaskToDockedStack(
-                                    mTask.mTaskId, createMode, true /*toTop*/);
+                                    mTask.mTaskId, createMode, true /*toTop*/, true /* animate */);
                         }
                     } catch(RemoteException e) {}
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e741c45..ac14f60 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2079,7 +2079,7 @@
     }
 
     private void prepareWindowReplacementTransition(AppWindowToken atoken) {
-        if (atoken == null || !atoken.mWillReplaceWindow) {
+        if (atoken == null || !atoken.mWillReplaceWindow || !atoken.mAnimateReplacingWindow) {
             return;
         }
         atoken.allDrawn = false;
@@ -8569,7 +8569,8 @@
             } else if (wtoken != null) {
                 winAnimator.mAnimLayer =
                         w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
-                if (wtoken.mWillReplaceWindow && wtoken.mReplacingWindow != w) {
+                if (wtoken.mWillReplaceWindow && wtoken.mReplacingWindow != w
+                        && wtoken.mAnimateReplacingWindow) {
                     // We know that we will be animating a relaunching window in the near future,
                     // which will receive a z-order increase. We want the replaced window to
                     // immediately receive the same treatment, e.g. to be above the dock divider.
@@ -10107,7 +10108,7 @@
      * a window.
      * @param token Application token for which the activity will be relaunched.
      */
-    public void setReplacingWindow(IBinder token) {
+    public void setReplacingWindow(IBinder token, boolean animate) {
         synchronized (mWindowMap) {
             AppWindowToken appWindowToken = findAppWindowToken(token);
             if (appWindowToken == null) {
@@ -10118,13 +10119,16 @@
                     + " as replacing window.");
             appWindowToken.mWillReplaceWindow = true;
             appWindowToken.mHasReplacedWindow = false;
+            appWindowToken.mAnimateReplacingWindow = animate;
 
-            // Set-up dummy animation so we can start treating windows associated with this token
-            // like they are in transition before the new app window is ready for us to run the
-            // real transition animation.
-            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                    "setReplacingWindow() Setting dummy animation on: " + appWindowToken);
-            appWindowToken.mAppAnimator.setDummyAnimation();
+            if (animate) {
+                // Set-up dummy animation so we can start treating windows associated with this
+                // token like they are in transition before the new app window is ready for us to
+                // run the real transition animation.
+                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+                        "setReplacingWindow() Setting dummy animation on: " + appWindowToken);
+                appWindowToken.mAppAnimator.setDummyAnimation();
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c6f7f4c..d4850af 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1389,6 +1389,7 @@
                 && token.mHasReplacedWindow) {
             if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replacing window: " + this);
             token.mWillReplaceWindow = false;
+            token.mAnimateReplacingWindow = false;
             token.mReplacingRemoveRequested = false;
             token.mReplacingWindow = null;
             token.mHasReplacedWindow = false;