Merge "Extend stack management to other displays." into klp-modular-dev
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 7adf5ec..89e15d2 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -109,7 +109,7 @@
                 "       am to-intent-uri [INTENT]\n" +
                 "       am switch-user <USER_ID>\n" +
                 "       am stop-user <USER_ID>\n" +
-                "       am stack create <TASK_ID> <DISPLAY_ID>\n" +
+                "       am stack start <DISPLAY_ID> <INTENT>\n" +
                 "       am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
                 "       am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
                 "       am stack list\n" +
@@ -207,7 +207,7 @@
                 "am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
                 "  code until a later explicit switch to it.\n" +
                 "\n" +
-                "am stack create: create a new stack containing <TASK_ID> which must exist\n" +
+                "am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" +
                 "\n" +
                 "am stack movetask: move <TASK_ID> from its current stack to the top (true) or" +
                 "   bottom (false) of <STACK_ID>.\n" +
@@ -1541,8 +1541,8 @@
 
     private void runStack() throws Exception {
         String op = nextArgRequired();
-        if (op.equals("create")) {
-            runStackCreate();
+        if (op.equals("start")) {
+            runStackStart();
         } else if (op.equals("movetask")) {
             runStackMoveTask();
         } else if (op.equals("resize")) {
@@ -1557,19 +1557,16 @@
         }
     }
 
-    private void runStackCreate() throws Exception {
-        String taskIdStr = nextArgRequired();
-        int taskId = Integer.valueOf(taskIdStr);
+    private void runStackStart() throws Exception {
         String displayIdStr = nextArgRequired();
         int displayId = Integer.valueOf(displayIdStr);
+        Intent intent = makeIntent(UserHandle.USER_CURRENT);
 
         try {
             IBinder homeActivityToken = mAm.getHomeActivityToken();
             IActivityContainer container = mAm.createActivityContainer(homeActivityToken, null);
-            final int stackId = container.getStackId();
-            System.out.println("createStack returned new stackId=" + stackId + "\n");
             container.attachToDisplay(displayId);
-            mAm.moveTaskToStack(taskId, stackId, true);
+            container.startActivity(intent);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 0f38095..3bc2ee6 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2031,6 +2031,15 @@
             return true;
         }
 
+        case GET_ACTIVITY_CONTAINER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder activityToken = data.readStrongBinder();
+            IActivityContainer activityContainer = getEnclosingActivityContainer(activityToken);
+            reply.writeNoException();
+            reply.writeStrongBinder(activityContainer.asBinder());
+            return true;
+        }
+
         case GET_HOME_ACTIVITY_TOKEN_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder homeActivityToken = getHomeActivityToken();
@@ -4668,6 +4677,21 @@
         return res;
     }
 
+    public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(activityToken);
+        mRemote.transact(GET_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        IActivityContainer res =
+                IActivityContainer.Stub.asInterface(reply.readStrongBinder());
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     public IBinder getHomeActivityToken() throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 97baf9a..9ae2543 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2219,15 +2219,26 @@
         ContextImpl appContext = new ContextImpl();
         appContext.init(r.packageInfo, r.token, this);
         appContext.setOuterContext(activity);
+        Context baseContext = appContext;
+
+        final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
+        try {
+            IActivityContainer container =
+                    ActivityManagerNative.getDefault().getEnclosingActivityContainer(r.token);
+            final int displayId = container.getDisplayId();
+            if (displayId > Display.DEFAULT_DISPLAY) {
+                Display display = dm.getRealDisplay(displayId, r.token);
+                baseContext = appContext.createDisplayContext(display);
+            }
+        } catch (RemoteException e) {
+        }
 
         // For debugging purposes, if the activity's package name contains the value of
         // the "debug.use-second-display" system property as a substring, then show
         // its content on a secondary display if there is one.
-        Context baseContext = appContext;
         String pkgName = SystemProperties.get("debug.second-display.pkg");
         if (pkgName != null && !pkgName.isEmpty()
                 && r.packageInfo.mPackageName.contains(pkgName)) {
-            DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
             for (int displayId : dm.getDisplayIds()) {
                 if (displayId != Display.DEFAULT_DISPLAY) {
                     Display display = dm.getRealDisplay(displayId, r.token);
diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl
index 2883d25..2d8d18f 100644
--- a/core/java/android/app/IActivityContainer.aidl
+++ b/core/java/android/app/IActivityContainer.aidl
@@ -23,7 +23,7 @@
 /** @hide */
 interface IActivityContainer {
     void attachToDisplay(int displayId);
-    int getStackId();
+    int getDisplayId();
     void detachFromDisplay();
-    void startActivity(in Intent intent);
+    int startActivity(in Intent intent);
 }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 4be1945..3ed3f7b 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -410,6 +410,9 @@
     public IActivityContainer createActivityContainer(IBinder parentActivityToken,
             IActivityContainerCallback callback) throws RemoteException;
 
+    public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
+            throws RemoteException;
+
     public IBinder getHomeActivityToken() throws RemoteException;
 
     /*
@@ -699,4 +702,5 @@
     int GET_PERSISTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+181;
     int APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+182;
     int GET_HOME_ACTIVITY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+183;
+    int GET_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184;
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3906745..53f0640 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2948,7 +2948,7 @@
                     intent.setComponent(new ComponentName(
                             ri.activityInfo.packageName, ri.activityInfo.name));
                     mStackSupervisor.startActivityLocked(null, intent, null, ri.activityInfo,
-                            null, null, 0, 0, 0, null, 0, null, false, null);
+                            null, null, 0, 0, 0, null, 0, null, false, null, null);
                 }
             }
         }
@@ -3106,7 +3106,7 @@
         // TODO: Switch to user app stacks here.
         return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
-                null, null, options, userId);
+                null, null, options, userId, null);
     }
 
     @Override
@@ -3121,7 +3121,7 @@
         // TODO: Switch to user app stacks here.
         mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
-                res, null, options, UserHandle.getCallingUserId());
+                res, null, options, UserHandle.getCallingUserId(), null);
         return res;
     }
 
@@ -3136,7 +3136,7 @@
         // TODO: Switch to user app stacks here.
         int ret = mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                 resolvedType, resultTo, resultWho, requestCode, startFlags,
-                null, null, null, config, options, userId);
+                null, null, null, config, options, userId, null);
         return ret;
     }
 
@@ -3267,7 +3267,7 @@
             int res = mStackSupervisor.startActivityLocked(r.app.thread, intent,
                     r.resolvedType, aInfo, resultTo != null ? resultTo.appToken : null,
                     resultWho, requestCode, -1, r.launchedFromUid, r.launchedFromPackage, 0,
-                    options, false, null);
+                    options, false, null, null);
             Binder.restoreCallingIdentity(origId);
 
             r.finishing = wasFinishing;
@@ -3288,7 +3288,7 @@
         // TODO: Switch to user app stacks here.
         int ret = mStackSupervisor.startActivityMayWait(null, uid, callingPackage, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags,
-                null, null, null, null, options, userId);
+                null, null, null, null, options, userId, null);
         return ret;
     }
 
@@ -7126,6 +7126,18 @@
     }
 
     @Override
+    public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
+            throws RemoteException {
+        synchronized (this) {
+            ActivityStack stack = ActivityRecord.getStackLocked(activityToken);
+            if (stack != null) {
+                return stack.mActivityContainer;
+            }
+            return null;
+        }
+    }
+
+    @Override
     public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
         enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
                 "moveTaskToStack()");
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 38b01df..b78f24c 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -145,6 +145,7 @@
 
     private boolean inHistory;  // are we in the history stack?
     final ActivityStackSupervisor mStackSupervisor;
+    ActivityContainer mInitialActivityContainer;
 
     void dump(PrintWriter pw, String prefix) {
         final long now = SystemClock.uptimeMillis();
@@ -349,7 +350,8 @@
             int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
             ActivityInfo aInfo, Configuration _configuration,
             ActivityRecord _resultTo, String _resultWho, int _reqCode,
-            boolean _componentSpecified, ActivityStackSupervisor supervisor) {
+            boolean _componentSpecified, ActivityStackSupervisor supervisor,
+            ActivityContainer container) {
         service = _service;
         appToken = new Token(this);
         info = aInfo;
@@ -380,6 +382,7 @@
         idle = false;
         hasBeenLaunched = false;
         mStackSupervisor = supervisor;
+        mInitialActivityContainer = container;
 
         // This starts out true, since the initial state of an activity
         // is that we have everything, and we shouldn't never consider it
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 8faee556..adba14d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -227,8 +227,11 @@
     int mCurrentUser;
 
     final int mStackId;
-
     final ActivityContainer mActivityContainer;
+    /** The other stacks, in order, on the attached display. Updated at attach/detach time. */
+    ArrayList<ActivityStack> mStacks;
+    /** The attached Display's unique identifier, or -1 if detached */
+    int mDisplayId;
 
     /** Run all ActivityStacks through this */
     final ActivityStackSupervisor mStackSupervisor;
@@ -446,11 +449,23 @@
         return mStackId == HOME_STACK_ID;
     }
 
-    ArrayList<ActivityStack> getStacksLocked() {
-        if (mActivityContainer.isAttached()) {
-            return mActivityContainer.mActivityDisplayInfo.stacks;
+    final boolean isOnHomeDisplay() {
+        return isAttached() &&
+                mActivityContainer.mActivityDisplay.mDisplayId == Display.DEFAULT_DISPLAY;
+    }
+
+    final void moveToFront() {
+        if (isAttached()) {
+            mStacks.remove(this);
+            mStacks.add(this);
+            if (isOnHomeDisplay()) {
+                mStackSupervisor.moveHomeStack(isHomeStack());
+            }
         }
-        return null;
+    }
+
+    final boolean isAttached() {
+        return mStacks != null;
     }
 
     /**
@@ -1252,7 +1267,8 @@
             ActivityOptions.abort(options);
             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
-            return mStackSupervisor.resumeHomeActivity(prev);
+            // Only resume home if on home display
+            return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev);
         }
 
         next.delayedResume = false;
@@ -1282,8 +1298,10 @@
                 final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
                 mTaskHistory.get(taskNdx).mOnTopOfHome = true;
             } else {
-                if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Launching home next");
-                return mStackSupervisor.resumeHomeActivity(prev);
+                if (DEBUG_STATES && isOnHomeDisplay()) Slog.d(TAG,
+                        "resumeTopActivityLocked: Launching home next");
+                // Only resume home if on home display
+                return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev);
             }
         }
 
@@ -1645,10 +1663,14 @@
     private void insertTaskAtTop(TaskRecord task) {
         // If this is being moved to the top by another activity or being launched from the home
         // activity, set mOnTopOfHome accordingly.
-        ActivityStack lastStack = mStackSupervisor.getLastStack();
-        final boolean fromHome = lastStack == null ? true : lastStack.isHomeStack();
-        if (!isHomeStack() && (fromHome || topTask() != task)) {
-            task.mOnTopOfHome = fromHome;
+        if (isOnHomeDisplay()) {
+            ActivityStack lastStack = mStackSupervisor.getLastStack();
+            final boolean fromHome = lastStack.isHomeStack();
+            if (!isHomeStack() && (fromHome || topTask() != task)) {
+                task.mOnTopOfHome = fromHome;
+            }
+        } else {
+            task.mOnTopOfHome = false;
         }
 
         mTaskHistory.remove(task);
@@ -2574,7 +2596,7 @@
                     int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent,
                             null, aInfo, parent.appToken, null,
                             0, -1, parent.launchedFromUid, parent.launchedFromPackage,
-                            0, null, true, null);
+                            0, null, true, null, null);
                     foundParentInTask = res == ActivityManager.START_SUCCESS;
                 } catch (RemoteException e) {
                     foundParentInTask = false;
@@ -3026,7 +3048,7 @@
             return;
         }
 
-        mStackSupervisor.moveHomeStack(isHomeStack());
+        moveToFront();
 
         // Shift all activities with this task up to the top
         // of the stack, keeping them in the same internal order.
@@ -3135,7 +3157,7 @@
         }
 
         final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
-        if (task == tr && task.mOnTopOfHome || numTasks <= 1) {
+        if (task == tr && tr.mOnTopOfHome || numTasks <= 1 && isOnHomeDisplay()) {
             tr.mOnTopOfHome = false;
             return mStackSupervisor.resumeHomeActivity(null);
         }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f1ac7fe..f5acbfd 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -145,17 +145,16 @@
     /** The current user */
     private int mCurrentUser;
 
-    /** The stack containing the launcher app */
+    /** The stack containing the launcher app. Assumed to always be attached to
+     * Display.DEFAULT_DISPLAY. */
     private ActivityStack mHomeStack;
 
-    /** The non-home stack currently receiving input or launching the next activity. If home is
-     * in front then mHomeStack overrides mFocusedStack.
-     * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
+    /** The stack currently receiving input or launching the next activity. */
     private ActivityStack mFocusedStack;
 
     /** If this is the same as mFocusedStack then the activity on the top of the focused stack has
      * been resumed. If stacks are changing position this will hold the old stack until the new
-     * stack becomes resumed after which it will be set to the new stack. */
+     * stack becomes resumed after which it will be set to mFocusedStack. */
     private ActivityStack mLastFocusedStack;
 
     /** List of activities that are waiting for a new activity to become visible before completing
@@ -217,7 +216,7 @@
     SparseArray<ActivityContainer> mActivityContainers = new SparseArray<ActivityContainer>();
 
     /** Mapping from displayId to display current state */
-    SparseArray<ActivityDisplayInfo> mDisplayInfos = new SparseArray<ActivityDisplayInfo>();
+    SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>();
 
     public ActivityStackSupervisor(ActivityManagerService service) {
         mService = service;
@@ -243,8 +242,8 @@
             Display[] displays = mDisplayManager.getDisplays();
             for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {
                 final int displayId = displays[displayNdx].getDisplayId();
-                ActivityDisplayInfo info = new ActivityDisplayInfo(displayId);
-                mDisplayInfos.put(displayId, info);
+                ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
+                mActivityDisplays.put(displayId, activityDisplay);
             }
 
             createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY);
@@ -271,7 +270,7 @@
     // TODO: Split into two methods isFrontStack for any visible stack and isFrontmostStack for the
     // top of all visible stacks.
     boolean isFrontStack(ActivityStack stack) {
-        ArrayList<ActivityStack> stacks = stack.getStacksLocked();
+        ArrayList<ActivityStack> stacks = stack.mStacks;
         if (stacks != null && !stacks.isEmpty()) {
             return stack == stacks.get(stacks.size() - 1);
         }
@@ -279,7 +278,7 @@
     }
 
     void moveHomeStack(boolean toFront) {
-        ArrayList<ActivityStack> stacks = mHomeStack.getStacksLocked();
+        ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
         int topNdx = stacks.size() - 1;
         if (topNdx <= 0) {
             return;
@@ -320,9 +319,9 @@
     }
 
     TaskRecord anyTaskForIdLocked(int id) {
-        int numDisplays = mDisplayInfos.size();
+        int numDisplays = mActivityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 ActivityStack stack = stacks.get(stackNdx);
                 TaskRecord task = stack.taskForIdLocked(id);
@@ -335,9 +334,9 @@
     }
 
     ActivityRecord isInAnyStackLocked(IBinder token) {
-        int numDisplays = mDisplayInfos.size();
+        int numDisplays = mActivityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityRecord r = stacks.get(stackNdx).isInStackLocked(token);
                 if (r != null) {
@@ -371,7 +370,9 @@
             final int stackId = stack.mStackId;
             final int nextStackId = mWindowManager.removeStack(stackId);
             // TODO: Perhaps we need to let the ActivityManager determine the next focus...
-            mFocusedStack = getStack(nextStackId);
+            if (stack.isOnHomeDisplay()) {
+                mFocusedStack = getStack(nextStackId);
+            }
         }
     }
 
@@ -393,8 +394,8 @@
     boolean attachApplicationLocked(ProcessRecord app) throws Exception {
         final String processName = app.processName;
         boolean didSomething = false;
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (!isFrontStack(stack)) {
@@ -424,8 +425,8 @@
     }
 
     boolean allResumedActivitiesIdle() {
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (!isFrontStack(stack)) {
@@ -441,8 +442,8 @@
     }
 
     boolean allResumedActivitiesComplete() {
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (isFrontStack(stack)) {
@@ -462,8 +463,8 @@
     }
 
     boolean allResumedActivitiesVisible() {
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 final ActivityRecord r = stack.mResumedActivity;
@@ -482,8 +483,8 @@
      */
     boolean pauseBackStacks(boolean userLeaving) {
         boolean someActivityPaused = false;
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
@@ -499,8 +500,8 @@
 
     boolean allPausedActivitiesComplete() {
         boolean pausing = true;
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 final ActivityRecord r = stack.mPausingActivity;
@@ -555,7 +556,7 @@
         }
 
         // Return to the home stack.
-        final ArrayList<ActivityStack> stacks = mHomeStack.getStacksLocked();
+        final ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
         for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
             final ActivityStack stack = stacks.get(stackNdx);
             if (stack != focusedStack && isFrontStack(stack)) {
@@ -575,9 +576,9 @@
         // Gather all of the running tasks for each stack into runningTaskLists.
         ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists =
                 new ArrayList<ArrayList<RunningTaskInfo>>();
-        final int numDisplays = mDisplayInfos.size();
+        final int numDisplays = mActivityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
@@ -666,14 +667,14 @@
     void startHomeActivity(Intent intent, ActivityInfo aInfo) {
         moveHomeToTop();
         startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
-                null, false, null);
+                null, false, null, null);
     }
 
     final int startActivityMayWait(IApplicationThread caller, int callingUid,
             String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, int startFlags, String profileFile,
             ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
-            Bundle options, int userId) {
+            Bundle options, int userId, IActivityContainer iContainer) {
         // Refuse possible leaked file descriptors
         if (intent != null && intent.hasFileDescriptors()) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -687,6 +688,7 @@
         ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                 profileFile, profileFd, userId);
 
+        ActivityContainer container = (ActivityContainer)iContainer;
         synchronized (mService) {
             int callingPid;
             if (callingUid >= 0) {
@@ -698,7 +700,12 @@
                 callingPid = callingUid = -1;
             }
 
-            final ActivityStack stack = getFocusedStack();
+            final ActivityStack stack;
+            if (container == null || container.mStack.isOnHomeDisplay()) {
+                stack = getFocusedStack();
+            } else {
+                stack = container.mStack;
+            }
             stack.mConfigWillChange = config != null
                     && mService.mConfiguration.diff(config) != 0;
             if (DEBUG_CONFIGURATION) Slog.v(TAG,
@@ -774,9 +781,9 @@
                 }
             }
 
-            int res = startActivityLocked(caller, intent, resolvedType,
-                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
-                    callingPackage, startFlags, options, componentSpecified, null);
+            int res = startActivityLocked(caller, intent, resolvedType, aInfo, resultTo, resultWho,
+                    requestCode, callingPid, callingUid, callingPackage, startFlags, options,
+                    componentSpecified, null, container);
 
             if (stack.mConfigWillChange) {
                 // If the caller also wants to switch to a new configuration,
@@ -891,7 +898,7 @@
                     }
                     int res = startActivityLocked(caller, intent, resolvedTypes[i],
                             aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
-                            0, theseOptions, componentSpecified, outActivity);
+                            0, theseOptions, componentSpecified, outActivity, null);
                     if (res < 0) {
                         return res;
                     }
@@ -1115,7 +1122,7 @@
             Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
             String resultWho, int requestCode,
             int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
-            boolean componentSpecified, ActivityRecord[] outActivity) {
+            boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container) {
         int err = ActivityManager.START_SUCCESS;
 
         ProcessRecord callerApp = null;
@@ -1250,8 +1257,8 @@
         }
 
         ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
-                intent, resolvedType, aInfo, mService.mConfiguration,
-                resultRecord, resultWho, requestCode, componentSpecified, this);
+                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
+                requestCode, componentSpecified, this, container);
         if (outActivity != null) {
             outActivity[0] = r;
         }
@@ -1299,34 +1306,40 @@
         if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
             if (task != null) {
                 final ActivityStack taskStack = task.stack;
-                if (mFocusedStack != taskStack) {
-                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
-                            "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
-                    mFocusedStack = taskStack;
-                } else {
-                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
-                        "adjustStackFocus: Focused stack already=" + mFocusedStack);
+                if (taskStack.isOnHomeDisplay()) {
+                    if (mFocusedStack != taskStack) {
+                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: Setting " +
+                                "focused stack to r=" + r + " task=" + task);
+                        mFocusedStack = taskStack;
+                    } else {
+                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
+                            "adjustStackFocus: Focused stack already=" + mFocusedStack);
+                    }
                 }
                 return taskStack;
             }
 
+            final ActivityContainer container = r.mInitialActivityContainer;
+            if (container != null) {
+                // The first time put it on the desired stack, after this put on task stack.
+                r.mInitialActivityContainer = null;
+                return container.mStack;
+            }
+
             if (mFocusedStack != mHomeStack) {
                 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                         "adjustStackFocus: Have a focused stack=" + mFocusedStack);
                 return mFocusedStack;
             }
 
-            int numDisplays = mDisplayInfos.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
-                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
-                    ActivityStack stack = stacks.get(stackNdx);
-                    if (!stack.isHomeStack()) {
-                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
-                                "adjustStackFocus: Setting focused stack=" + stack);
-                        mFocusedStack = stack;
-                        return mFocusedStack;
-                    }
+            final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
+            for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = homeDisplayStacks.get(stackNdx);
+                if (!stack.isHomeStack()) {
+                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
+                            "adjustStackFocus: Setting focused stack=" + stack);
+                    mFocusedStack = stack;
+                    return mFocusedStack;
                 }
             }
 
@@ -1471,7 +1484,7 @@
                     targetStack.mLastPausedActivity = null;
                     if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack
                             + " from " + intentActivity);
-                    moveHomeStack(targetStack.isHomeStack());
+                    targetStack.moveToFront();
                     if (intentActivity.task.intent == null) {
                         // This task was started because of movement of
                         // the activity based on affinity...  now that we
@@ -1690,7 +1703,7 @@
         if (r.resultTo == null && !addingToTask
                 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
             targetStack = adjustStackFocus(r);
-            moveHomeStack(targetStack.isHomeStack());
+            targetStack.moveToFront();
             if (reuseTask == null) {
                 r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                         newTaskInfo != null ? newTaskInfo : r.info,
@@ -1708,13 +1721,13 @@
                         == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
                     // Caller wants to appear on home activity, so before starting
                     // their own activity we will bring home to the front.
-                    r.task.mOnTopOfHome = true;
+                    r.task.mOnTopOfHome = r.task.stack.isOnHomeDisplay();
                 }
             }
         } else if (sourceRecord != null) {
             TaskRecord sourceTask = sourceRecord.task;
             targetStack = sourceTask.stack;
-            moveHomeStack(targetStack.isHomeStack());
+            targetStack.moveToFront();
             if (!addingToTask &&
                     (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
                 // In this case, we are adding the activity to an existing
@@ -1768,7 +1781,7 @@
             // of a new task...  just put it in the top task, though these days
             // this case should never happen.
             targetStack = adjustStackFocus(r);
-            moveHomeStack(targetStack.isHomeStack());
+            targetStack.moveToFront();
             ActivityRecord prev = targetStack.topActivity();
             r.setTask(prev != null ? prev.task
                     : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
@@ -1960,8 +1973,8 @@
 
     boolean handleAppDiedLocked(ProcessRecord app) {
         boolean hasVisibleActivities = false;
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 hasVisibleActivities |= stacks.get(stackNdx).handleAppDiedLocked(app);
             }
@@ -1970,8 +1983,8 @@
     }
 
     void closeSystemDialogsLocked() {
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 stacks.get(stackNdx).closeSystemDialogsLocked();
             }
@@ -1987,8 +2000,8 @@
      */
     boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
         boolean didSomething = false;
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             final int numStacks = stacks.size();
             for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
@@ -2009,8 +2022,8 @@
         // we don't blow away the previous app if this activity is being
         // hosted by the process that is actually still the foreground.
         ProcessRecord fgApp = null;
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (isFrontStack(stack)) {
@@ -2044,8 +2057,8 @@
             targetStack = getFocusedStack();
         }
         boolean result = false;
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (isFrontStack(stack)) {
@@ -2061,8 +2074,8 @@
     }
 
     void finishTopRunningActivityLocked(ProcessRecord app) {
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             final int numStacks = stacks.size();
             for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
@@ -2072,8 +2085,8 @@
     }
 
     void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 if (stacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
                     if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
@@ -2094,8 +2107,8 @@
 
     ArrayList<ActivityStack> getStacks() {
         ArrayList<ActivityStack> allStacks = new ArrayList<ActivityStack>();
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            allStacks.addAll(mDisplayInfos.valueAt(displayNdx).stacks);
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            allStacks.addAll(mActivityDisplays.valueAt(displayNdx).mStacks);
         }
         return allStacks;
     }
@@ -2134,14 +2147,14 @@
     }
 
     private int createStackOnDisplay(ActivityRecord parentActivity, int stackId, int displayId) {
-        ActivityDisplayInfo displayInfo = mDisplayInfos.get(displayId);
-        if (displayInfo == null) {
+        ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+        if (activityDisplay == null) {
             return -1;
         }
 
         ActivityContainer activityContainer =
                 createActivityContainer(parentActivity, stackId, null);
-        activityContainer.attachToDisplayLocked(displayInfo);
+        activityContainer.attachToDisplayLocked(activityDisplay);
         return stackId;
     }
 
@@ -2175,8 +2188,8 @@
 
     ActivityRecord findTaskLocked(ActivityRecord r) {
         if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + r);
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (!r.isApplicationActivity() && !stack.isHomeStack()) {
@@ -2194,8 +2207,8 @@
     }
 
     ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityRecord ar = stacks.get(stackNdx).findActivityLocked(intent, info);
                 if (ar != null) {
@@ -2228,8 +2241,8 @@
         final long endTime = System.currentTimeMillis() + timeout;
         while (true) {
             boolean cantShutdown = false;
-            for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-                final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+                final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
                 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                     cantShutdown |= stacks.get(stackNdx).checkReadyForSleepLocked();
                 }
@@ -2263,8 +2276,8 @@
         if (mGoingToSleep.isHeld()) {
             mGoingToSleep.release();
         }
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 stack.awakeFromSleepingLocked();
@@ -2289,8 +2302,8 @@
 
         if (!mSleepTimeout) {
             boolean dontSleep = false;
-            for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-                final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+                final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
                 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                     dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked();
                 }
@@ -2316,8 +2329,8 @@
             }
         }
 
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 stacks.get(stackNdx).goToSleep();
             }
@@ -2347,8 +2360,8 @@
     }
 
     void handleAppCrashLocked(ProcessRecord app) {
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             final int numStacks = stacks.size();
             for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
@@ -2360,8 +2373,8 @@
     void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
         // First the front stacks. In case any are not fullscreen and are in front of home.
         boolean showHomeBehindStack = false;
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             final int topStackNdx = stacks.size() - 1;
             for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
@@ -2379,8 +2392,8 @@
     }
 
     void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             final int numStacks = stacks.size();
             for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
@@ -2395,10 +2408,12 @@
         mCurrentUser = userId;
 
         mStartingUsers.add(uss);
-        for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
-                stacks.get(stackNdx).switchUserLocked(userId);
+                final ActivityStack stack = stacks.get(stackNdx);
+                stack.switchUserLocked(userId);
+                mWindowManager.moveTaskToTop(stack.topTask().taskId);
             }
         }
 
@@ -2407,8 +2422,13 @@
             stack = mHomeStack;
         }
         final boolean homeInFront = stack.isHomeStack();
-        moveHomeStack(homeInFront);
-        mWindowManager.moveTaskToTop(stack.topTask().taskId);
+        if (stack.isOnHomeDisplay()) {
+            moveHomeStack(homeInFront);
+            mWindowManager.moveTaskToTop(stack.topTask().taskId);
+        } else {
+            // Stack was moved to another display while user was swapped out.
+            resumeHomeActivity(null);
+        }
         return homeInFront;
     }
 
@@ -2521,10 +2541,10 @@
             boolean dumpClient, String dumpPackage) {
         boolean printed = false;
         boolean needSep = false;
-        for (int displayNdx = 0; displayNdx < mDisplayInfos.size(); ++displayNdx) {
-            ActivityDisplayInfo info = mDisplayInfos.valueAt(displayNdx);
-            pw.print("Display #"); pw.println(info.mDisplayId);
-            ArrayList<ActivityStack> stacks = info.stacks;
+        for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
+            ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
+            pw.print("Display #"); pw.println(activityDisplay.mDisplayId);
+            ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
             final int numStacks = stacks.size();
             for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
@@ -2709,21 +2729,21 @@
 
     public void handleDisplayAddedLocked(int displayId) {
         synchronized (mService) {
-            ActivityDisplayInfo info = new ActivityDisplayInfo(displayId);
-            mDisplayInfos.put(displayId, info);
+            ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
+            mActivityDisplays.put(displayId, activityDisplay);
         }
         mWindowManager.onDisplayAdded(displayId);
     }
 
     public void handleDisplayRemovedLocked(int displayId) {
         synchronized (mService) {
-            ActivityDisplayInfo info = mDisplayInfos.get(displayId);
-            if (info != null) {
-                ArrayList<ActivityStack> stacks = info.stacks;
+            ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+            if (activityDisplay != null) {
+                ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
                 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
-                    info.detachActivities(stacks.get(stackNdx));
+                    activityDisplay.detachActivitiesLocked(stacks.get(stackNdx));
                 }
-                mDisplayInfos.remove(displayId);
+                mActivityDisplays.remove(displayId);
             }
         }
         mWindowManager.onDisplayRemoved(displayId);
@@ -2731,8 +2751,8 @@
 
     public void handleDisplayChangedLocked(int displayId) {
         synchronized (mService) {
-            ActivityDisplayInfo info = mDisplayInfos.get(displayId);
-            if (info != null) {
+            ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+            if (activityDisplay != null) {
                 // TODO: Update the bounds.
             }
         }
@@ -2772,8 +2792,8 @@
 
     ArrayList<StackInfo> getAllStackInfosLocked() {
         ArrayList<StackInfo> list = new ArrayList<StackInfo>();
-        for (int displayNdx = 0; displayNdx < mDisplayInfos.size(); ++displayNdx) {
-            ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+        for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
+            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) {
                 list.add(getStackInfo(stacks.get(ndx)));
             }
@@ -2864,7 +2884,7 @@
         final ActivityRecord mParentActivity;
 
         /** Display this ActivityStack is currently on. Null if not attached to a Display. */
-        ActivityDisplayInfo mActivityDisplayInfo;
+        ActivityDisplay mActivityDisplay;
 
         ActivityContainer(ActivityRecord parentActivity, int stackId,
                 IActivityContainerCallback callback) {
@@ -2876,32 +2896,40 @@
             }
         }
 
-        void attachToDisplayLocked(ActivityDisplayInfo displayInfo) {
-            mActivityDisplayInfo = displayInfo;
-            displayInfo.attachActivities(mStack);
-            mWindowManager.createStack(mStackId, displayInfo.mDisplayId);
+        void attachToDisplayLocked(ActivityDisplay activityDisplay) {
+            mActivityDisplay = activityDisplay;
+            mStack.mDisplayId = activityDisplay.mDisplayId;
+            mStack.mStacks = activityDisplay.mStacks;
+
+            activityDisplay.attachActivities(mStack);
+            mWindowManager.createStack(mStackId, activityDisplay.mDisplayId);
         }
 
         @Override
         public void attachToDisplay(int displayId) throws RemoteException {
             synchronized (mService) {
-                ActivityDisplayInfo displayInfo = mDisplayInfos.get(displayId);
-                if (displayInfo == null) {
+                ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+                if (activityDisplay == null) {
                     return;
                 }
-                attachToDisplayLocked(displayInfo);
+                attachToDisplayLocked(activityDisplay);
             }
         }
 
         @Override
-        public int getStackId() throws RemoteException {
-            return mStack.mStackId;
+        public int getDisplayId() throws RemoteException {
+            if (mActivityDisplay != null) {
+                return mActivityDisplay.mDisplayId;
+            }
+            return -1;
         }
 
         void detachLocked() {
-            if (mActivityDisplayInfo != null) {
-                mActivityDisplayInfo.detachActivities(mStack);
-                mActivityDisplayInfo = null;
+            if (mActivityDisplay != null) {
+                mActivityDisplay.detachActivitiesLocked(mStack);
+                mActivityDisplay = null;
+                mStack.mDisplayId = -1;
+                mStack.mStacks = null;
             }
         }
 
@@ -2913,8 +2941,18 @@
         }
 
         @Override
-        public void startActivity(Intent intent) throws RemoteException {
-
+        public final int startActivity(Intent intent) {
+            mService.enforceNotIsolatedCaller("ActivityContainer");
+            int userId = mService.handleIncomingUser(Binder.getCallingPid(),
+                    Binder.getCallingUid(), mCurrentUser, false, true, "ActivityContainer", null);
+            // TODO: Switch to user app stacks here.
+            String mimeType = intent.getType();
+            if (mimeType == null && intent.getData() != null
+                    && "content".equals(intent.getData().getScheme())) {
+                mimeType = mService.getProviderMimeType(intent.getData(), userId);
+            }
+            return startActivityMayWait(null, -1, null, intent, mimeType, null, null, 0, 0, null,
+                    null, null, null, null, userId, this);
         }
 
         @Override
@@ -2927,12 +2965,12 @@
         }
 
         boolean isAttached() {
-            return mActivityDisplayInfo != null;
+            return mActivityDisplay != null;
         }
 
         void getBounds(Point outBounds) {
-            if (mActivityDisplayInfo != null) {
-                mActivityDisplayInfo.getBounds(outBounds);
+            if (mActivityDisplay != null) {
+                mActivityDisplay.getBounds(outBounds);
             } else {
                 outBounds.set(0, 0);
             }
@@ -2941,7 +2979,7 @@
 
     /** Exactly one of these classes per Display in the system. Capable of holding zero or more
      * attached {@link ActivityStack}s */
-    final class ActivityDisplayInfo {
+    final class ActivityDisplay {
         /** Actual Display this object tracks. */
         final int mDisplayId;
         final Display mDisplay;
@@ -2949,20 +2987,24 @@
 
         /** All of the stacks on this display. Order matters, topmost stack is in front of all other
          * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
-        final ArrayList<ActivityStack> stacks = new ArrayList<ActivityStack>();
+        final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
 
-        ActivityDisplayInfo(int displayId) {
+        ActivityDisplay(int displayId) {
             mDisplayId = displayId;
             mDisplay = mDisplayManager.getDisplay(displayId);
             mDisplay.getDisplayInfo(mDisplayInfo);
         }
 
         void attachActivities(ActivityStack stack) {
-            stacks.add(stack);
+            if (DEBUG_STACK) Slog.v(TAG, "attachActivities: attaching " + stack + " to displayId="
+                    + mDisplayId);
+            mStacks.add(stack);
         }
 
-        void detachActivities(ActivityStack stack) {
-            stacks.remove(stack);
+        void detachActivitiesLocked(ActivityStack stack) {
+            if (DEBUG_STACK) Slog.v(TAG, "attachActivities: detaching " + stack
+                    + " from displayId=" + mDisplayId);
+            mStacks.remove(stack);
         }
 
         void getBounds(Point bounds) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 9105103..9740812 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -60,7 +60,8 @@
     /** Takes on same set of values as ActivityRecord.mActivityType */
     private int mTaskType;
 
-    /** Launch the home activity when leaving this task. */
+    /** Launch the home activity when leaving this task. Will be false for tasks that are not on
+     * Display.DEFAULT_DISPLAY. */
     boolean mOnTopOfHome = false;
 
     TaskRecord(int _taskId, ActivityInfo info, Intent _intent) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4064377..0a070c1 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -191,6 +191,9 @@
     }
 
     TaskStack getHomeStack() {
+        if (mHomeStack == null) {
+            Slog.e(TAG, "getHomeStack: Returning null from this=" + this);
+        }
         return mHomeStack;
     }
 
@@ -430,4 +433,9 @@
         }
         pw.println();
     }
+
+    @Override
+    public String toString() {
+        return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 04129e2..ea56363 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4783,11 +4783,13 @@
                 final TaskStack stack = task.mStack;
                 final DisplayContent displayContent = task.getDisplayContent();
                 displayContent.moveStack(stack, true);
-                final TaskStack homeStack = displayContent.getHomeStack();
-                if (homeStack != stack) {
-                    // When a non-home stack moves to the top, the home stack moves to the
-                    // bottom.
-                    displayContent.moveStack(homeStack, false);
+                if (displayContent.isDefaultDisplay) {
+                    final TaskStack homeStack = displayContent.getHomeStack();
+                    if (homeStack != stack) {
+                        // When a non-home stack moves to the top, the home stack moves to the
+                        // bottom.
+                        displayContent.moveStack(homeStack, false);
+                    }
                 }
                 stack.moveTaskToTop(task);
             }
@@ -8985,6 +8987,10 @@
                 final int N = windows.size();
                 for (i=N-1; i>=0; i--) {
                     WindowState w = windows.get(i);
+                    final TaskStack stack = w.getStack();
+                    if (stack == null) {
+                        continue;
+                    }
 
                     final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
 
@@ -8994,7 +9000,7 @@
                         handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
                     }
 
-                    if (!w.getStack().testDimmingTag()) {
+                    if (!stack.testDimmingTag()) {
                         handleFlagDimBehind(w, innerDw, innerDh);
                     }
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e6c1e98..77a36b8 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -717,7 +717,12 @@
         if (wtoken != null) {
             Task task = mService.mTaskIdToTask.get(wtoken.groupId);
             if (task != null) {
-                return task.mStack;
+                if (task.mStack != null) {
+                    return task.mStack;
+                }
+                Slog.e(TAG, "getStack: mStack null for task=" + task);
+            } else {
+                Slog.e(TAG, "getStack: couldn't find taskId=" + wtoken.groupId);
             }
         }
         return mDisplayContent.getHomeStack();