Fix user switching.
- Save and restore WindowManager stack states.
- Maintain ActivityManager activity states based on the stack
the activity is in.
Fixes bug 8646641.
Change-Id: I16c76c7708ab49121c3884a7e5bf219898b92d3f
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 89b0ff2..528bf6f 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -61,6 +61,7 @@
import android.os.UserHandle;
import android.util.EventLog;
import android.util.Slog;
+import android.util.SparseArray;
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
@@ -160,6 +161,9 @@
* 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>();
+
public ActivityStackSupervisor(ActivityManagerService service, Context context,
Looper looper) {
mService = service;
@@ -213,6 +217,9 @@
}
boolean isFrontStack(ActivityStack stack) {
+ if (stack.mCurrentUser != mCurrentUser) {
+ return false;
+ }
return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
}
@@ -319,6 +326,9 @@
final String processName = app.processName;
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
+ if (!isFrontStack(stack)) {
+ continue;
+ }
ActivityRecord hr = stack.topRunningActivityLocked(null);
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
@@ -412,7 +422,7 @@
}
void reportActivityVisibleLocked(ActivityRecord r) {
- for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
+ for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
WaitResult w = mWaitingActivityVisible.get(i);
w.timeout = false;
if (r != null) {
@@ -449,6 +459,9 @@
}
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
+ if (stack.mCurrentUser != mCurrentUser) {
+ continue;
+ }
if (stack != mFocusedStack && isFrontStack(stack)) {
r = stack.topRunningActivityLocked(null);
if (r != null) {
@@ -1145,8 +1158,14 @@
ActivityStack getCorrectStack(ActivityRecord r) {
if (!r.isHomeActivity) {
- if (mStacks.size() == 1) {
- // Time to create the first app stack.
+ int stackNdx;
+ for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
+ if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
+ break;
+ }
+ }
+ 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);
mFocusedStack = getStack(stackId);
@@ -1776,7 +1795,7 @@
return didSomething;
}
- void resumeTopActivityLocked() {
+ void resumeTopActivitiesLocked() {
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
if (isFrontStack(stack)) {
@@ -1816,18 +1835,16 @@
}
int createStack() {
- synchronized (this) {
- while (true) {
- if (++mLastStackId <= HOME_STACK_ID) {
- mLastStackId = HOME_STACK_ID + 1;
- }
- if (getStack(mLastStackId) == null) {
- break;
- }
+ while (true) {
+ if (++mLastStackId <= HOME_STACK_ID) {
+ mLastStackId = HOME_STACK_ID + 1;
}
- mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
- return mLastStackId;
+ if (getStack(mLastStackId) == null) {
+ break;
+ }
}
+ mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
+ return mLastStackId;
}
void moveTaskToStack(int taskId, int stackId, boolean toTop) {
@@ -1938,16 +1955,22 @@
}
boolean switchUserLocked(int userId, UserStartedState uss) {
+ mUserStates.put(mCurrentUser, new UserState());
mCurrentUser = userId;
- mStartingUsers.add(uss);
- boolean haveActivities = false;
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (isFrontStack(stack)) {
- haveActivities |= stack.switchUserLocked(userId, uss);
- }
+ UserState userState = mUserStates.get(userId);
+ if (userState != null) {
+ userState.restore();
+ mUserStates.delete(userId);
+ } else {
+ mFocusedStack = null;
+ mStackState = STACK_STATE_HOME_IN_FRONT;
}
+
+ mStartingUsers.add(uss);
+ boolean haveActivities = mHomeStack.switchUserLocked(userId, uss);
+
+ resumeTopActivitiesLocked();
+
return haveActivities;
}
@@ -2203,4 +2226,21 @@
}
}
}
+
+ private final class UserState {
+ final ActivityStack mSavedFocusedStack;
+ final int mSavedStackState;
+
+ public UserState() {
+ ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
+ mSavedFocusedStack = supervisor.mFocusedStack;
+ mSavedStackState = supervisor.mStackState;
+ }
+
+ void restore() {
+ ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
+ supervisor.mFocusedStack = mSavedFocusedStack;
+ supervisor.mStackState = mSavedStackState;
+ }
+ }
}