Fix wrong task bounds when docking from recents.

When docking from recents we would move the task to the docked stack,
but we wouldn't run the resizing code that forces the task to be within
the stack bounds. We need to perform both operations and we can achieve
that using a more general method of moving tasks.

This also adds the passing of creation mode in the activity options, so
the task will be docked in the right spot.

Change-Id: Ia7f94a7e3677ed60ca2f4d889e548d80a3bc3df1
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 933f98d..821621e 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -127,6 +129,12 @@
     public static final String KEY_ANIM_START_LISTENER = "android:activity.animStartListener";
 
     /**
+     * Where the docked stack should be positioned.
+     * @hide
+     */
+    private static final String KEY_DOCK_CREATE_MODE = "android:activity.dockCreateMode";
+
+    /**
      * For Activity transitions, the calling Activity's TransitionListener used to
      * notify the called Activity when the shared element and the exit transitions
      * complete.
@@ -190,6 +198,7 @@
     private int mResultCode;
     private int mExitCoordinatorIndex;
     private PendingIntent mUsageTimeReport;
+    private int mDockCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 
     /**
      * Create an ActivityOptions specifying a custom animation to run when
@@ -688,6 +697,7 @@
                 mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX);
                 break;
         }
+        mDockCreateMode = opts.getInt(KEY_DOCK_CREATE_MODE, DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT);
     }
 
     /** @hide */
@@ -806,6 +816,14 @@
         }
     }
 
+    /** @hide */
+    public int getDockCreateMode() { return mDockCreateMode; }
+
+    /** @hide */
+    public void setDockCreateMode(int dockCreateMode) {
+        mDockCreateMode = dockCreateMode;
+    }
+
     /**
      * Update the current values in this ActivityOptions from those supplied
      * in <var>otherOptions</var>.  Any values
@@ -945,6 +963,7 @@
                 b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
                 break;
         }
+        b.putInt(KEY_DOCK_CREATE_MODE, mDockCreateMode);
 
         return b;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 3a30a8f..b07d23c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -409,7 +409,7 @@
         SystemServicesProxy ssp = Recents.getSystemServices();
         ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
         if (topTask != null && !ssp.isInHomeStack(topTask.id)) {
-            ssp.moveTaskToDockedStack(topTask.id,
+            ssp.startTaskInDockedMode(topTask.id,
                     ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT);
             showRecents(false /* triggeredFromAltTab */);
         }
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 221af15..0b01538 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -284,18 +284,9 @@
         if (mIam == null) return;
 
         try {
-            mIam.startActivityFromRecents(taskId, DOCKED_STACK_ID, null);
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        }
-    }
-
-    /** 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 */);
+            final ActivityOptions options = ActivityOptions.makeBasic();
+            options.setDockCreateMode(createMode);
+            mIam.startActivityFromRecents(taskId, DOCKED_STACK_ID, options.toBundle());
         } catch (RemoteException e) {
             e.printStackTrace();
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 257f034..dbbce49 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3844,8 +3844,8 @@
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
             int startFlags, ProfilerInfo profilerInfo, Bundle options) {
         return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
-            resultWho, requestCode, startFlags, profilerInfo, options,
-            UserHandle.getCallingUserId());
+                resultWho, requestCode, startFlags, profilerInfo, options,
+                UserHandle.getCallingUserId());
     }
 
     @Override
@@ -4152,7 +4152,12 @@
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
-        return startActivityFromRecentsInner(taskId, launchStackId, options);
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            return startActivityFromRecentsInner(taskId, launchStackId, options);
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
     }
 
     final int startActivityFromRecentsInner(int taskId, int launchStackId, Bundle options) {
@@ -4174,8 +4179,12 @@
             }
 
             if (launchStackId != INVALID_STACK_ID && task.stack.mStackId != launchStackId) {
-                mStackSupervisor.moveTaskToStackUncheckedLocked(
-                        task, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents");
+                if (launchStackId == DOCKED_STACK_ID && options != null) {
+                    ActivityOptions activityOptions = new ActivityOptions(options);
+                    mWindowManager.setDockedStackCreateMode(activityOptions.getDockCreateMode());
+                }
+                mStackSupervisor.moveTaskToStackLocked(
+                        taskId, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents");
             }
 
             if (task.getRootActivity() != null) {
@@ -9029,7 +9038,8 @@
                 }
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveActivityToStack: moving r=" + r
                         + " to stackId=" + stackId);
-                mStackSupervisor.moveTaskToStackLocked(r.task.taskId, stackId, ON_TOP, !FORCE_FOCUS);
+                mStackSupervisor.moveTaskToStackLocked(r.task.taskId, stackId, ON_TOP, !FORCE_FOCUS,
+                        "moveActivityToStack");
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -9049,7 +9059,8 @@
             try {
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
                         + " to stackId=" + stackId + " toTop=" + toTop);
-                mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop, !FORCE_FOCUS);
+                mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop, !FORCE_FOCUS,
+                        "moveTaskToStack");
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -9078,7 +9089,7 @@
                         + " to createMode=" + createMode + " toTop=" + toTop);
                 mWindowManager.setDockedStackCreateMode(createMode);
                 mStackSupervisor.moveTaskToStackLocked(
-                        taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS);
+                        taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS, "moveTaskToDockedStack");
             } 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 cd2f124..3bf87d8 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3032,7 +3032,7 @@
                     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);
+                                FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, FORCE_FOCUS, "resizeStack");
                     }
 
                     // stack shouldn't contain anymore activities, so nothing to resume.
@@ -3267,13 +3267,13 @@
         return stack;
     }
 
-    void moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus) {
+    void moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
+            String reason) {
         final TaskRecord task = anyTaskForIdLocked(taskId);
         if (task == null) {
             Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
             return;
         }
-        final String reason = "moveTaskToStack";
         if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID
                 || stackId == FULLSCREEN_WORKSPACE_STACK_ID) {
             // We are about to relaunch the activity because its configuration changed due to
@@ -3286,7 +3286,8 @@
             mWindowManager.setReplacingWindow(r.appToken, true /* animate */);
         }
         final ActivityStack stack =
-                moveTaskToStackUncheckedLocked(task, stackId, toTop, forceFocus, reason);
+                moveTaskToStackUncheckedLocked(task, stackId, toTop, forceFocus,
+                        "moveTaskToStack:" + reason);
 
         // Make sure the task has the appropriate bounds/size for the stack it is in.
         if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
@@ -3332,7 +3333,8 @@
         if (task.mActivities.size() == 1) {
             // 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);
+            moveTaskToStackLocked(task.taskId, PINNED_STACK_ID, ON_TOP, FORCE_FOCUS,
+                    "moveTopActivityToPinnedStack");
         } else {
             final ActivityStack pinnedStack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
             pinnedStack.moveActivityToStack(r);