summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Craig Mautner <cmautner@google.com> 2013-07-17 13:24:59 -0700
committer Craig Mautner <cmautner@google.com> 2013-07-19 16:05:59 -0700
commitac6f843c917b68ea8805711965b149a9338e3a0e (patch)
tree8dbcb9d8f1ae101e1a7b12fac3693c5270c327b2
parent350503fba389a753cbb92864c36864830fdd8efe (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
-rw-r--r--core/java/android/view/IWindowManager.aidl2
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java17
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java19
-rw-r--r--services/java/com/android/server/am/ActivityStack.java73
-rw-r--r--services/java/com/android/server/am/ActivityStackSupervisor.java145
-rw-r--r--services/java/com/android/server/am/TaskRecord.java3
-rw-r--r--services/java/com/android/server/wm/DisplayContent.java79
-rw-r--r--services/java/com/android/server/wm/StackBox.java9
-rw-r--r--services/java/com/android/server/wm/Task.java4
-rw-r--r--services/java/com/android/server/wm/TaskStack.java35
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java6
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java2
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