Merge "Fix home activity and user switch interactions."
This commit is contained in:
committed by
Android (Google) Code Review
commit
acb837fe63
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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() {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user