diff options
| author | 2013-07-17 13:24:59 -0700 | |
|---|---|---|
| committer | 2013-07-19 16:05:59 -0700 | |
| commit | ac6f843c917b68ea8805711965b149a9338e3a0e (patch) | |
| tree | 8dbcb9d8f1ae101e1a7b12fac3693c5270c327b2 | |
| parent | 350503fba389a753cbb92864c36864830fdd8efe (diff) | |
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
12 files changed, 216 insertions, 178 deletions
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 02894074e709..aea2799c2835 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -78,7 +78,7 @@ interface IWindowManager void addWindowToken(IBinder token, int type); void removeWindowToken(IBinder token); void addAppToken(int addPos, IApplicationToken token, int groupId, int stackId, - int requestedOrientation, boolean fullscreen, boolean showWhenLocked); + int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId); void setAppGroupId(IBinder token, int groupId); void setAppOrientation(IApplicationToken token, int requestedOrientation); int getAppOrientation(IApplicationToken token); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index b51415f5c655..ebd51abc4188 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -30,6 +30,7 @@ import android.util.ArrayMap; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsService; +import com.android.internal.app.ResolverActivity; import com.android.internal.os.BackgroundThread; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.ProcessStats; @@ -2056,7 +2057,7 @@ public final class ActivityManagerService extends ActivityManagerNative final void setFocusedActivityLocked(ActivityRecord r) { if (mFocusedActivity != r) { - if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedActivitiyLocked: r=" + r); + if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedActivityLocked: r=" + r); mFocusedActivity = r; mStackSupervisor.setFocusedStack(r); if (r != null) { @@ -2493,6 +2494,20 @@ public final class ActivityManagerService extends ActivityManagerNative } } + String getHomePackageName() { + Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null); + intent.setComponent(mTopComponent); + intent.addCategory(Intent.CATEGORY_HOME); + ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, mCurrentUserId); + if (aInfo != null) { + final String homePackageName = aInfo.applicationInfo.packageName; + if (!ResolverActivity.class.getName().equals(homePackageName)) { + return homePackageName; + } + } + return null; + } + boolean startHomeActivityLocked(int userId) { if (mHeadless) { // Added because none of the other calls to ensureBootCompleted seem to fire diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index e6849ede255d..b858755623ed 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -339,6 +339,10 @@ final class ActivityRecord { } } + boolean isNotResolverActivity() { + return !ResolverActivity.class.getName().equals(realActivity.getClassName()); + } + ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, @@ -442,21 +446,22 @@ final class ActivityRecord { // If we know the system has determined the component, then // we can consider this to be a home activity... - // Note the last check is so we don't count the resolver - // activity as being home... really, we don't care about - // doing anything special with something that comes from - // the core framework package. - if ((!_componentSpecified || _launchedFromUid == Process.myUid() + String homePackageName = supervisor.getHomePackageName(); + if (homePackageName != null && homePackageName.equals(packageName)) { + mActivityType = HOME_ACTIVITY_TYPE; + } else if ((!_componentSpecified || _launchedFromUid == Process.myUid() || _launchedFromUid == 0) && Intent.ACTION_MAIN.equals(_intent.getAction()) && _intent.hasCategory(Intent.CATEGORY_HOME) && _intent.getCategories().size() == 1 && _intent.getData() == null && _intent.getType() == null && - (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && - !ResolverActivity.class.getName().equals(realActivity.getClassName())) { + (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { // This sure looks like a home activity! mActivityType = HOME_ACTIVITY_TYPE; + if (isNotResolverActivity()) { + supervisor.setHomePackageName(userId, packageName); + } } else if (realActivity.getClassName().contains("com.android.systemui.recent")) { mActivityType = RECENTS_ACTIVITY_TYPE; } else { diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index a154b9c59d22..4c7767c40155 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -465,7 +465,9 @@ final class ActivityStack { * Returns the top activity in any existing task matching the given * Intent. Returns null if no such task is found. */ - ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) { + ActivityRecord findTaskLocked(ActivityRecord target) { + Intent intent = target.intent; + ActivityInfo info = target.info; ComponentName cls = intent.getComponent(); if (info.targetActivity != null) { cls = new ComponentName(info.packageName, info.targetActivity); @@ -474,6 +476,10 @@ final class ActivityStack { for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); + if (task.userId != userId) { + // Looking for a different task. + continue; + } final ActivityRecord r = task.getTopActivity(); if (r == null || r.finishing || r.userId != userId || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { @@ -518,7 +524,11 @@ final class ActivityStack { final int userId = UserHandle.getUserId(info.applicationInfo.uid); for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { - final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; + TaskRecord task = mTaskHistory.get(taskNdx); + if (task.userId != mCurrentUser) { + return null; + } + final ArrayList<ActivityRecord> activities = task.mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord r = activities.get(activityNdx); if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId == userId) { @@ -534,8 +544,7 @@ final class ActivityStack { } /* - * 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. + * Move the activities around in the stack to bring a user to the foreground. * @return whether there are any activities for the specified user. */ final boolean switchUserLocked(int userId) { @@ -1172,6 +1181,7 @@ final class ActivityStack { // There are no more activities! Let's just start up the // Launcher... ActivityOptions.abort(options); + if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return mStackSupervisor.resumeHomeActivity(prev); } @@ -1186,6 +1196,7 @@ final class ActivityStack { mWindowManager.executeAppTransition(); mNoAnimActivities.clear(); ActivityOptions.abort(options); + if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } @@ -1213,6 +1224,7 @@ final class ActivityStack { final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; mTaskHistory.get(taskNdx).mActivities.get(0).mLaunchHomeTaskNext = true; } else { + if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Launching home next"); return mStackSupervisor.resumeHomeActivity(prev); } } @@ -1227,6 +1239,7 @@ final class ActivityStack { mWindowManager.executeAppTransition(); mNoAnimActivities.clear(); ActivityOptions.abort(options); + if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Going to sleep and all paused"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } @@ -1255,7 +1268,8 @@ final class ActivityStack { // If we are currently pausing an activity, then don't do anything // until that is done. if (!mStackSupervisor.allPausedActivitiesComplete()) { - if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG, "Skip resume: some activity pausing"); + if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG, + "resumeTopActivityLocked: Skip resume: some activity pausing."); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } @@ -1295,9 +1309,11 @@ final class ActivityStack { if (mResumedActivity != null) { pausing = true; startPausingLocked(userLeaving, false); + if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity); } if (pausing) { - if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing"); + if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG, + "resumeTopActivityLocked: Skip resume: need to start pausing"); // At this point we want to put the upcoming activity's process // at the top of the LRU list, since we know we will be needing it // very soon and it would be a waste to let it get killed if it @@ -1459,7 +1475,7 @@ final class ActivityStack { // is still at the top and schedule another run if something // weird happened. ActivityRecord nextNext = topRunningActivityLocked(null); - if (DEBUG_SWITCH) Slog.i(TAG, + if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Activity config changed during resume: " + next + ", new next: " + nextNext); if (nextNext != next) { @@ -1505,6 +1521,7 @@ final class ActivityStack { mStackSupervisor.checkReadyForSleepLocked(); + if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Resumed " + next); } catch (Exception e) { // Whoops, need to restart this activity! if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to " @@ -1561,6 +1578,7 @@ final class ActivityStack { } if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next); } + if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Restarting " + next); mStackSupervisor.startSpecificActivityLocked(next, true, true); } @@ -1568,6 +1586,21 @@ final class ActivityStack { return true; } + private void insertTaskAtTop(TaskRecord task) { + mTaskHistory.remove(task); + // Now put task at top. + int stackNdx = mTaskHistory.size(); + if (task.userId != mCurrentUser) { + // Put non-current user tasks below current user tasks. + while (--stackNdx >= 0) { + if (mTaskHistory.get(stackNdx).userId != mCurrentUser) { + break; + } + } + ++stackNdx; + } + mTaskHistory.add(stackNdx, task); + } final void startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition, Bundle options) { @@ -1577,9 +1610,7 @@ final class ActivityStack { // Last activity in task had been removed or ActivityManagerService is reusing task. // Insert or replace. // Might not even be in. - mTaskHistory.remove(rTask); - // Now put task at top. - mTaskHistory.add(rTask); + insertTaskAtTop(rTask); mWindowManager.moveTaskToTop(taskId); } TaskRecord task = null; @@ -1599,7 +1630,8 @@ final class ActivityStack { r.putInHistory(); mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, - (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0); + (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, + r.userId); if (VALIDATE_TOKENS) { validateAppTokensLocked(); } @@ -1660,7 +1692,7 @@ final class ActivityStack { r.updateOptionsLocked(options); mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, - (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0); + (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId); boolean doShow = true; if (newTask) { // Even though this activity is starting fresh, we still need @@ -1703,7 +1735,7 @@ final class ActivityStack { // because there is nothing for it to animate on top of. mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, - (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0); + (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId); ActivityOptions.abort(options); } if (VALIDATE_TOKENS) { @@ -2897,8 +2929,7 @@ final class ActivityStack { // Shift all activities with this task up to the top // of the stack, keeping them in the same internal order. - mTaskHistory.remove(tr); - mTaskHistory.add(tr); + insertTaskAtTop(tr); if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr); if (reason != null && @@ -3380,7 +3411,7 @@ final class ActivityStack { printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities, " ", "Hist", true, !dumpAll, dumpClient, dumpPackage, needSep, header, - " Task " + taskNdx + ": id #" + task.taskId); + " Task id #" + task.taskId); if (printed) { header = null; } @@ -3448,12 +3479,8 @@ final class ActivityStack { } TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, boolean toTop) { - TaskRecord task = new TaskRecord(taskId, info, intent, this); - if (toTop) { - mTaskHistory.add(task); - } else { - mTaskHistory.add(0, task); - } + TaskRecord task = new TaskRecord(taskId, info, intent); + addTask(task, toTop); return task; } @@ -3464,7 +3491,7 @@ final class ActivityStack { void addTask(final TaskRecord task, final boolean toTop) { task.stack = this; if (toTop) { - mTaskHistory.add(task); + insertTaskAtTop(task); } else { mTaskHistory.add(0, task); } diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java index 8d1a6654bc64..925fb3fa2bf9 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/java/com/android/server/am/ActivityStackSupervisor.java @@ -185,9 +185,6 @@ public final 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>(); - /** Set when we have taken too long waiting to go to sleep. */ boolean mSleepTimeout = false; @@ -206,6 +203,12 @@ public final class ActivityStackSupervisor { */ 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 @@ public final class ActivityStackSupervisor { } 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 @@ public final class ActivityStackSupervisor { 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 @@ public final class ActivityStackSupervisor { 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 @@ public final class ActivityStackSupervisor { } 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 @@ public final class ActivityStackSupervisor { 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 @@ public final class ActivityStackSupervisor { 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 @@ public final class ActivityStackSupervisor { 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 (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 (mFocusedStack != null) { + if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, + "adjustStackFocus: Have a focused stack=" + mFocusedStack); + return mFocusedStack; } - if (task != null) { - if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: Setting focused stack to r=" + - r + " task=" + task); - mFocusedStack = task.stack; + + 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; + } } + + // 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 @@ public final class ActivityStackSupervisor { 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 @@ public final class ActivityStackSupervisor { // 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 @@ public final class ActivityStackSupervisor { // 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 @@ public final class ActivityStackSupervisor { // 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 @@ public final class ActivityStackSupervisor { 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 @@ public final class ActivityStackSupervisor { } 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 @@ public final class ActivityStackSupervisor { 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 @@ public final class ActivityStackSupervisor { } } - private final class UserState { - final ActivityStack mSavedFocusedStack; - final int mSavedStackState; - - public UserState() { - ActivityStackSupervisor supervisor = ActivityStackSupervisor.this; - mSavedFocusedStack = supervisor.mFocusedStack; - mSavedStackState = supervisor.mStackState; - } + String getHomePackageName() { + return mHomePackageNames.get(mCurrentUser); + } - 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); } } diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java index d79211ccf5b5..ebcf22aded89 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/java/com/android/server/am/TaskRecord.java @@ -59,11 +59,10 @@ final class TaskRecord extends ThumbnailHolder { private boolean mApplicationTask = true; - TaskRecord(int _taskId, ActivityInfo info, Intent _intent, ActivityStack _stack) { + TaskRecord(int _taskId, ActivityInfo info, Intent _intent) { taskId = _taskId; affinity = info.taskAffinity; setIntent(_intent, info); - stack = _stack; } void touchActiveTime() { diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java index 088061cbf6a7..4f699ae1b7b2 100644 --- a/services/java/com/android/server/wm/DisplayContent.java +++ b/services/java/com/android/server/wm/DisplayContent.java @@ -25,7 +25,6 @@ import android.app.ActivityManager.StackBoxInfo; import android.graphics.Rect; import android.graphics.Region; import android.util.Slog; -import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; @@ -106,8 +105,6 @@ class DisplayContent { /** Detect user tapping outside of current focused stack bounds .*/ Region mTouchExcludeRegion = new Region(); - SparseArray<UserStacks> mUserStacks = new SparseArray<UserStacks>(); - /** Save allocating when retrieving tasks */ ArrayList<Task> mTmpTasks = new ArrayList<Task>(); @@ -166,22 +163,6 @@ 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()); @@ -359,14 +340,6 @@ 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; } @@ -400,12 +373,9 @@ class DisplayContent { 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); + + for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) { + mStackBoxes.get(stackBoxNdx).switchUserStacks(newUserId); } } @@ -508,49 +478,6 @@ 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/StackBox.java b/services/java/com/android/server/wm/StackBox.java index d352464b09ea..e7582d755bab 100644 --- a/services/java/com/android/server/wm/StackBox.java +++ b/services/java/com/android/server/wm/StackBox.java @@ -371,6 +371,15 @@ public class StackBox { mSecond.stopDimmingIfNeeded(); } + void switchUserStacks(int userId) { + if (mStack != null) { + mStack.switchUser(userId); + return; + } + mFirst.switchUserStacks(userId); + mSecond.switchUserStacks(userId); + } + public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("mParent="); pw.println(mParent); pw.print(prefix); pw.print("mBounds="); pw.print(mBounds.toShortString()); diff --git a/services/java/com/android/server/wm/Task.java b/services/java/com/android/server/wm/Task.java index 88eb96e22682..d9acbb95f72f 100644 --- a/services/java/com/android/server/wm/Task.java +++ b/services/java/com/android/server/wm/Task.java @@ -21,11 +21,13 @@ class Task { TaskStack mStack; final AppTokenList mAppTokens = new AppTokenList(); final int taskId; + final int mUserId; - Task(AppWindowToken wtoken, TaskStack stack) { + Task(AppWindowToken wtoken, TaskStack stack, int userId) { taskId = wtoken.groupId; mAppTokens.add(wtoken); mStack = stack; + mUserId = userId; } DisplayContent getDisplayContent() { diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java index 18019e68d85d..29156be6a89b 100644 --- a/services/java/com/android/server/wm/TaskStack.java +++ b/services/java/com/android/server/wm/TaskStack.java @@ -97,9 +97,28 @@ public class TaskStack { * @param toTop Whether to add it to the top or bottom. */ boolean addTask(Task task, boolean toTop) { - if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "addTask: task=" + task + " toTop=" + toTop); mStackBox.makeDirty(); - mTasks.add(toTop ? mTasks.size() : 0, task); + + int stackNdx; + if (!toTop) { + stackNdx = 0; + } else { + stackNdx = mTasks.size(); + final int currentUserId = mService.mCurrentUserId; + if (task.mUserId != currentUserId) { + // Place the task below all current user tasks. + while (--stackNdx >= 0) { + if (currentUserId != mTasks.get(stackNdx).mUserId) { + break; + } + } + ++stackNdx; + } + } + if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "addTask: task=" + task + " toTop=" + toTop + + " pos=" + stackNdx); + mTasks.add(stackNdx, task); + task.mStack = this; return mDisplayContent.moveHomeStackBox(mStackId == HOME_STACK_ID); } @@ -256,6 +275,18 @@ public class TaskStack { } } + void switchUser(int userId) { + int top = mTasks.size(); + for (int taskNdx = 0; taskNdx < top; ++taskNdx) { + Task task = mTasks.get(taskNdx); + if (task.mUserId == userId) { + mTasks.remove(taskNdx); + mTasks.add(task); + --top; + } + } + } + public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("mStackId="); pw.println(mStackId); for (int taskNdx = 0; taskNdx < mTasks.size(); ++taskNdx) { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 3e7509ae7a9d..e65ec10328bc 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -3371,7 +3371,7 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, - int requestedOrientation, boolean fullscreen, boolean showWhenLocked) { + int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "addAppToken()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); @@ -3404,7 +3404,7 @@ public class WindowManagerService extends IWindowManager.Stub atoken.showWhenLocked = showWhenLocked; atoken.requestedOrientation = requestedOrientation; if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken - + " at " + addPos); + + " to stack=" + stackId + " task=" + taskId + " at " + addPos); Task task = mTaskIdToTask.get(taskId); if (task == null) { @@ -3412,7 +3412,7 @@ public class WindowManagerService extends IWindowManager.Stub if (stack == null) { throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); } - task = new Task(atoken, stack); + task = new Task(atoken, stack, userId); stack.addTask(task, true); stack.getDisplayContent().moveStack(stack, true); mTaskIdToTask.put(taskId, task); diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 6343049cb89b..f0c3a758fa3e 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -81,7 +81,7 @@ public class IWindowManagerImpl implements IWindowManager { @Override public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, int arg4, - boolean arg5, boolean arg6) + boolean arg5, boolean arg6, int arg7) throws RemoteException { // TODO Auto-generated method stub |