diff options
5 files changed, 175 insertions, 47 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index dd113c3..c750cad 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -3612,7 +3612,7 @@ public final class ActivityManagerService extends ActivityManagerNative "for process:"+packageName); } } - + try { // Clear application user data pm.clearApplicationUserData(packageName, observer, userId); @@ -3681,7 +3681,7 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.w(TAG, msg); throw new SecurityException(msg); } - + long callingId = Binder.clearCallingIdentity(); try { synchronized(this) { @@ -3702,7 +3702,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } } - + int N = procs.size(); for (int i=0; i<N; i++) { removeProcessLocked(procs.get(i), false, true, "kill all background"); @@ -3971,7 +3971,7 @@ public final class ActivityManagerService extends ActivityManagerNative procs.add(app); } } - + int N = procs.size(); for (int i=0; i<N; i++) { removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason); @@ -4133,7 +4133,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } if (mBooted) { - mStackSupervisor.resumeTopActivityLocked(); + mStackSupervisor.resumeTopActivitiesLocked(); mStackSupervisor.scheduleIdleLocked(); } } @@ -4983,7 +4983,8 @@ public final class ActivityManagerService extends ActivityManagerNative updateOomAdjLocked(); } } - + + @Override public void setProcessForeground(IBinder token, int pid, boolean isForeground) { enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT, "setProcessForeground()"); @@ -5007,6 +5008,7 @@ public final class ActivityManagerService extends ActivityManagerNative } if (isForeground && token != null) { ForegroundToken newToken = new ForegroundToken() { + @Override public void binderDied() { foregroundTokenDied(this); } @@ -5041,6 +5043,7 @@ public final class ActivityManagerService extends ActivityManagerNative mActivityManagerService = activityManagerService; } + @Override public boolean checkPermission(String permission, int pid, int uid) { return mActivityManagerService.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED; @@ -5048,12 +5051,14 @@ public final class ActivityManagerService extends ActivityManagerNative } class IntentFirewallInterface implements IntentFirewall.AMSInterface { + @Override public int checkComponentPermission(String permission, int pid, int uid, int owningUid, boolean exported) { return ActivityManagerService.this.checkComponentPermission(permission, pid, uid, owningUid, exported); } + @Override public Object getAMSLock() { return ActivityManagerService.this; } @@ -8281,7 +8286,7 @@ public final class ActivityManagerService extends ActivityManagerNative } finally { Binder.restoreCallingIdentity(ident); } - mStackSupervisor.resumeTopActivityLocked(); + mStackSupervisor.resumeTopActivitiesLocked(); sendUserSwitchBroadcastsLocked(-1, mCurrentUserId); } } @@ -8396,10 +8401,10 @@ public final class ActivityManagerService extends ActivityManagerNative // annoy the user repeatedly. Unless it is persistent, since those // processes run critical code. removeProcessLocked(app, false, false, "crash"); - mStackSupervisor.resumeTopActivityLocked(); + mStackSupervisor.resumeTopActivitiesLocked(); return false; } - mStackSupervisor.resumeTopActivityLocked(); + mStackSupervisor.resumeTopActivitiesLocked(); } else { mStackSupervisor.finishTopRunningActivityLocked(app); } diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 3557e90..3758bb1 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -234,7 +234,7 @@ final class ActivityStack { int mThumbnailWidth = -1; int mThumbnailHeight = -1; - private int mCurrentUser; + int mCurrentUser; final int mStackId; @@ -576,7 +576,8 @@ final class ActivityStack { } /* - * Move the activities around in the stack to bring a user to the foreground. + * Move the activities around in the stack to bring a user to the foreground. This only + * matters on the home stack. All other stacks are single user. * @return whether there are any activities for the specified user. */ final boolean switchUserLocked(int userId, UserStartedState uss) { @@ -602,9 +603,6 @@ final class ActivityStack { } } - // task is now the original topmost TaskRecord. Transition from the old top to the new top. - ActivityRecord top = task != null ? task.getTopActivity() : null; - resumeTopActivityLocked(top); return haveActivities; } @@ -1718,7 +1716,7 @@ final class ActivityStack { } if (doResume) { - mStackSupervisor.resumeTopActivityLocked(); + mStackSupervisor.resumeTopActivitiesLocked(); } } 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.SystemClock; 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 @@ public class ActivityStackSupervisor { * 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 @@ public class ActivityStackSupervisor { } boolean isFrontStack(ActivityStack stack) { + if (stack.mCurrentUser != mCurrentUser) { + return false; + } return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack()); } @@ -319,6 +326,9 @@ public class ActivityStackSupervisor { 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 @@ public class ActivityStackSupervisor { } 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 @@ public class ActivityStackSupervisor { } 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 @@ public class ActivityStackSupervisor { 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 @@ public class ActivityStackSupervisor { 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 @@ public class ActivityStackSupervisor { } 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; + } + if (getStack(mLastStackId) == null) { + break; } - mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId)); - return mLastStackId; } + mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId)); + return mLastStackId; } void moveTaskToStack(int taskId, int stackId, boolean toTop) { @@ -1938,16 +1955,22 @@ public class ActivityStackSupervisor { } 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 @@ public class ActivityStackSupervisor { } } } + + 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; + } + } } diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java index 8343986..45f018d 100644 --- a/services/java/com/android/server/wm/DisplayContent.java +++ b/services/java/com/android/server/wm/DisplayContent.java @@ -18,10 +18,12 @@ package com.android.server.wm; import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; import static com.android.server.wm.WindowManagerService.DEBUG_STACK; +import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerService.TAG; import android.graphics.Rect; import android.util.Slog; +import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; import android.view.InputChannel; @@ -104,6 +106,8 @@ class DisplayContent { /** Detect user tapping outside of current focused stack bounds .*/ StackTapDetector mTapDetector; + SparseArray<UserStacks> mUserStacks = new SparseArray<UserStacks>(); + /** * @param display May not be null. */ @@ -145,6 +149,22 @@ class DisplayContent { */ ArrayList<Task> getTasks() { mTmpTasks.clear(); + // First do the tasks belonging to other users. + final int numUserStacks = mUserStacks.size(); + for (int i = 0; i < numUserStacks; ++i) { + UserStacks userStacks = mUserStacks.valueAt(i); + ArrayList<TaskStack> stacks = userStacks.mSavedStackHistory; + final int numStacks = stacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + TaskStack stack = stacks.get(stackNdx); + if (stack != mHomeStack) { + if (WindowManagerService.DEBUG_LAYERS) Slog.i(TAG, "getTasks: mStackHistory=" + + mStackHistory); + mTmpTasks.addAll(stack.getTasks()); + } + } + } + // Now do the current user's tasks. final int numStacks = mStackHistory.size(); for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { mTmpTasks.addAll(mStackHistory.get(stackNdx).getTasks()); @@ -292,6 +312,14 @@ class DisplayContent { return bounds; } } + // Not in the visible stacks, try the saved ones. + for (int userNdx = mUserStacks.size() - 1; userNdx >= 0; --userNdx) { + UserStacks userStacks = mUserStacks.valueAt(userNdx); + Rect bounds = userStacks.mSavedStackBox.getStackBounds(stackId); + if (bounds != null) { + return bounds; + } + } return null; } @@ -300,6 +328,26 @@ class DisplayContent { return topBox.stackIdFromPoint(x, y); } + void switchUserStacks(int oldUserId, int newUserId) { + final WindowList windows = getWindowList(); + for (int i = 0; i < windows.size(); i++) { + final WindowState win = windows.get(i); + if (win.isHiddenFromUserLocked()) { + if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding " + + win + ", attrs=" + win.mAttrs.type + ", belonging to " + + win.mOwnerUid); + win.hideLw(false); + } + } + // Clear the old user's non-home StackBox + mUserStacks.put(oldUserId, new UserStacks()); + UserStacks userStacks = mUserStacks.get(newUserId); + if (userStacks != null) { + userStacks.restore(); + mUserStacks.delete(newUserId); + } + } + public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); final String subPrefix = " " + prefix; @@ -365,6 +413,49 @@ class DisplayContent { token.dump(pw, " "); } } + if (mUserStacks.size() > 0) { + pw.println(); + pw.println(" Saved user stacks:"); + for (int i = 0; i < mUserStacks.size(); ++i) { + UserStacks userStacks = mUserStacks.valueAt(i); + pw.print(" UserId="); pw.println(Integer.toHexString(mUserStacks.keyAt(i))); + pw.print(" StackHistory="); pw.println(userStacks.mSavedStackHistory); + pw.print(" StackBox="); userStacks.mSavedStackBox.dump(" ", pw); + } + } pw.println(); } + + private final class UserStacks { + final ArrayList<TaskStack> mSavedStackHistory; + StackBox mSavedStackBox; + int mBoxNdx; + + public UserStacks() { + mSavedStackHistory = new ArrayList<TaskStack>(mStackHistory); + for (int stackNdx = mStackHistory.size() - 1; stackNdx >=0; --stackNdx) { + if (mStackHistory.get(stackNdx) != mHomeStack) { + mStackHistory.remove(stackNdx); + } + } + mSavedStackBox = null; + mBoxNdx = -1; + for (int boxNdx = mStackBoxes.size() - 1; boxNdx >= 0; --boxNdx) { + StackBox box = mStackBoxes.get(boxNdx); + if (box.mStack != mHomeStack) { + mSavedStackBox = box; + mBoxNdx = boxNdx; + mStackBoxes.remove(boxNdx); + break; + } + } + } + + void restore() { + mStackHistory = mSavedStackHistory; + if (mBoxNdx >= 0) { + mStackBoxes.add(mBoxNdx, mSavedStackBox); + } + } + } } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 5a9d63a..cb4333f 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -5094,22 +5094,16 @@ public class WindowManagerService extends IWindowManager.Stub public void setCurrentUser(final int newUserId) { synchronized (mWindowMap) { + int oldUserId = mCurrentUserId; mCurrentUserId = newUserId; mPolicy.setCurrentUserLw(newUserId); // Hide windows that should not be seen by the new user. DisplayContentsIterator iterator = new DisplayContentsIterator(); while (iterator.hasNext()) { - final WindowList windows = iterator.next().getWindowList(); - for (int i = 0; i < windows.size(); i++) { - final WindowState win = windows.get(i); - if (win.isHiddenFromUserLocked()) { - Slog.w(TAG, "current user violation " + newUserId + " hiding " - + win + ", attrs=" + win.mAttrs.type + ", belonging to " - + win.mOwnerUid); - win.hideLw(false); - } - } + DisplayContent displayContent = iterator.next(); + displayContent.switchUserStacks(oldUserId, newUserId); + rebuildAppWindowListLocked(displayContent); } performLayoutAndPlaceSurfacesLocked(); } |
