Merge "Fix home activity and user switch interactions."

This commit is contained in:
Craig Mautner
2013-07-19 23:07:51 +00:00
committed by Android (Google) Code Review
12 changed files with 218 additions and 180 deletions

View File

@ -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);

View File

@ -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;
@ -2049,7 +2050,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) {
@ -2486,6 +2487,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

View File

@ -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 {

View File

@ -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);
}

View File

@ -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 (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 @@ 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;
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);
}
}

View File

@ -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() {

View File

@ -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);
}
}
}
}

View File

@ -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());

View File

@ -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() {

View File

@ -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) {

View File

@ -3374,7 +3374,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");
@ -3407,7 +3407,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) {
@ -3415,7 +3415,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);

View File

@ -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