Fix home activity and user switch interactions.

- Make sure Home activity goes in the correct task and on the correct
stack.
- Do not allow different users to be in the same task.
- Do not set stacks aside for each user.

Fixes bug 9775492.

Change-Id: I0e7954e917aac8482a1015a36923e02914e2b692
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 8d1a665..925fb3f 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -185,9 +185,6 @@
      * is being brought in front of us. */
     boolean mUserLeaving = false;
 
-    /** Stacks belonging to users other than mCurrentUser. Indexed by userId. */
-    final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
-
     /** Set when we have taken too long waiting to go to sleep. */
     boolean mSleepTimeout = false;
 
@@ -206,6 +203,12 @@
      */
     final PowerManager.WakeLock mGoingToSleep;
 
+    /**
+     * The name of the current home activity for each user.
+     * TODO: Remove entries when user is deleted.
+     */
+    final SparseArray<String> mHomePackageNames = new SparseArray<String>();
+
     public ActivityStackSupervisor(ActivityManagerService service, Context context,
             Looper looper) {
         mService = service;
@@ -263,8 +266,7 @@
     }
 
     boolean isFrontStack(ActivityStack stack) {
-        return (stack.mCurrentUser == mCurrentUser) &&
-                !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
+        return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
     }
 
     void moveHomeStack(boolean toFront) {
@@ -354,7 +356,7 @@
             final int stackId = stack.mStackId;
             final int nextStackId = mWindowManager.removeStack(stackId);
             // TODO: Perhaps we need to let the ActivityManager determine the next focus...
-            if (getFocusedStack().mStackId == stackId) {
+            if (mFocusedStack == null || mFocusedStack.mStackId == stackId) {
                 // If this is the last app stack, set mFocusedStack to null.
                 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
             }
@@ -467,6 +469,8 @@
         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
             final ActivityStack stack = mStacks.get(stackNdx);
             if (!isFrontStack(stack) && stack.mResumedActivity != null) {
+                if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
+                        " mResumedActivity=" + stack.mResumedActivity);
                 stack.startPausingLocked(userLeaving, false);
                 someActivityPaused = true;
             }
@@ -475,16 +479,22 @@
     }
 
     boolean allPausedActivitiesComplete() {
+        boolean pausing = true;
         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
             final ActivityStack stack = mStacks.get(stackNdx);
             final ActivityRecord r = stack.mPausingActivity;
             if (r != null && r.state != ActivityState.PAUSED
                     && r.state != ActivityState.STOPPED
                     && r.state != ActivityState.STOPPING) {
-                return false;
+                if (DEBUG_STATES) {
+                    Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
+                    pausing = false;
+                } else {
+                    return false;
+                }
             }
         }
-        return true;
+        return pausing;
     }
 
     void reportActivityVisibleLocked(ActivityRecord r) {
@@ -524,8 +534,7 @@
 
         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
             final ActivityStack stack = mStacks.get(stackNdx);
-            if (stack.mCurrentUser == mCurrentUser && stack != focusedStack &&
-                    isFrontStack(stack)) {
+            if (stack != focusedStack && isFrontStack(stack)) {
                 r = stack.topRunningActivityLocked(null);
                 if (r != null) {
                     return r;
@@ -895,7 +904,7 @@
                         r.userId, System.identityHashCode(r),
                         r.task.taskId, r.shortComponentName);
             }
-            if (r.isHomeActivity()) {
+            if (r.isHomeActivity() && r.isNotResolverActivity()) {
                 mService.mHomeProcess = app;
             }
             mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
@@ -1216,28 +1225,43 @@
         return err;
     }
 
-    ActivityStack getCorrectStack(ActivityRecord r) {
+    ActivityStack adjustStackFocus(ActivityRecord r) {
         final TaskRecord task = r.task;
         if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
-            int stackNdx;
-            for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
-                if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
-                    break;
+            if (task != null) {
+                if (mFocusedStack != task.stack) {
+                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
+                            "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
+                    mFocusedStack = task.stack;
+                } else {
+                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
+                        "adjustStackFocus: Focused stack already=" + mFocusedStack);
+                }
+                return mFocusedStack;
+            }
+
+            if (mFocusedStack != null) {
+                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
+                        "adjustStackFocus: Have a focused stack=" + mFocusedStack);
+                return mFocusedStack;
+            }
+
+            for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
+                ActivityStack stack = mStacks.get(stackNdx);
+                if (!stack.isHomeStack()) {
+                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
+                            "adjustStackFocus: Setting focused stack=" + stack);
+                    mFocusedStack = stack;
+                    return mFocusedStack;
                 }
             }
-            if (stackNdx == 0) {
-                // Time to create the first app stack for this user.
-                int stackId = mService.createStack(-1, HOME_STACK_ID,
-                        StackBox.TASK_STACK_GOES_OVER, 1.0f);
-                if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: New stack r=" + r + " stackId="
-                        + stackId);
-                mFocusedStack = getStack(stackId);
-            }
-            if (task != null) {
-                if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: Setting focused stack to r=" +
-                        r + " task=" + task);
-                mFocusedStack = task.stack;
-            }
+
+            // Time to create the first app stack for this user.
+            int stackId = mService.createStack(-1, HOME_STACK_ID,
+                StackBox.TASK_STACK_GOES_OVER, 1.0f);
+            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
+                    " stackId=" + stackId);
+            mFocusedStack = getStack(stackId);
             return mFocusedStack;
         }
         return mHomeStack;
@@ -1256,8 +1280,9 @@
                 mStackState = STACK_STATE_HOME_TO_FRONT;
             }
         } else {
-            if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: Setting focused stack to r=" +
-                    r + " task=" + r.task + " Callers=" + Debug.getCallers(3));
+            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
+                    "setFocusedStack: Setting focused stack to r=" + r + " task=" + r.task +
+                    " Callers=" + Debug.getCallers(3));
             mFocusedStack = r.task.stack;
             if (mStackState != STACK_STATE_HOME_IN_BACK) {
                 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
@@ -1366,7 +1391,7 @@
                 // instance of it in the history, and it is always in its own
                 // unique task, so we do a special search.
                 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
-                        ? findTaskLocked(intent, r.info)
+                        ? findTaskLocked(r)
                         : findActivityLocked(intent, r.info);
                 if (intentActivity != null) {
                     if (r.task == null) {
@@ -1592,7 +1617,7 @@
         // Should this be considered a new task?
         if (r.resultTo == null && !addingToTask
                 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
-            targetStack = getCorrectStack(r);
+            targetStack = adjustStackFocus(r);
             moveHomeStack(targetStack.isHomeStack());
             if (reuseTask == null) {
                 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
@@ -1671,7 +1696,7 @@
             // This not being started from an existing activity, and not part
             // of a new task...  just put it in the top task, though these days
             // this case should never happen.
-            targetStack = getCorrectStack(r);
+            targetStack = adjustStackFocus(r);
             moveHomeStack(targetStack.isHomeStack());
             ActivityRecord prev = targetStack.topActivity();
             r.setTask(prev != null ? prev.task
@@ -2009,9 +2034,13 @@
         resumeTopActivitiesLocked();
     }
 
-    ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
+    ActivityRecord findTaskLocked(ActivityRecord r) {
         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
+            final ActivityStack stack = mStacks.get(stackNdx);
+            if (!r.isApplicationActivity() && !stack.isHomeStack()) {
+                continue;
+            }
+            final ActivityRecord ar = stack.findTaskLocked(r);
             if (ar != null) {
                 return ar;
             }
@@ -2193,21 +2222,18 @@
     }
 
     boolean switchUserLocked(int userId, UserStartedState uss) {
-        mUserStates.put(mCurrentUser, new UserState());
         mCurrentUser = userId;
-        UserState userState = mUserStates.get(userId);
-        if (userState != null) {
-            userState.restore();
-            mUserStates.delete(userId);
-        } else {
-            mFocusedStack = null;
-            if (DEBUG_STACK) Slog.d(TAG, "switchUserLocked: mStackState=" +
-                    stackStateToString(STACK_STATE_HOME_IN_FRONT));
-            mStackState = STACK_STATE_HOME_IN_FRONT;
+
+        final String homePackageName = mService.getHomePackageName();
+        if (homePackageName != null) {
+            setHomePackageName(mCurrentUser, homePackageName);
         }
 
         mStartingUsers.add(uss);
-        boolean haveActivities = mHomeStack.switchUserLocked(userId);
+        boolean haveActivities = false;
+        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+            haveActivities |= mStacks.get(stackNdx).switchUserLocked(userId);
+        }
 
         resumeTopActivitiesLocked();
 
@@ -2304,6 +2330,12 @@
         pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
         pw.print(prefix); pw.println("mSleepTimeout: " + mSleepTimeout);
         pw.print(prefix); pw.println("mCurTaskId: " + mCurTaskId);
+        pw.print(prefix); pw.print("mHomePackageNames:");
+                for (int i = 0; i < mHomePackageNames.size(); ++i) {
+                    pw.print(" ("); pw.print(mHomePackageNames.keyAt(i)); pw.print(",");
+                    pw.print(mHomePackageNames.valueAt(i)); pw.print(")");
+                }
+                pw.println();
     }
 
     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
@@ -2558,22 +2590,13 @@
         }
     }
 
-    private final class UserState {
-        final ActivityStack mSavedFocusedStack;
-        final int mSavedStackState;
+    String getHomePackageName() {
+        return mHomePackageNames.get(mCurrentUser);
+    }
 
-        public UserState() {
-            ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
-            mSavedFocusedStack = supervisor.mFocusedStack;
-            mSavedStackState = supervisor.mStackState;
-        }
-
-        void restore() {
-            ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
-            supervisor.mFocusedStack = mSavedFocusedStack;
-            if (DEBUG_STACK) Slog.d(TAG, "UserState.restore: mStackState old=" +
-                    stackStateToString(mSavedStackState));
-            supervisor.mStackState = mSavedStackState;
-        }
+    void setHomePackageName(int userId, String homePackageName) {
+        if (DEBUG_SWITCH) Slog.d(TAG, "setHomePackageName: user=" + userId + " package="
+                + homePackageName);
+        mHomePackageNames.put(userId, homePackageName);
     }
 }