summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorCraig Mautner <cmautner@google.com>2013-04-13 00:05:50 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-04-13 00:05:50 +0000
commitfd7e534b1f783c6bdd0e27196071d33fb14a7d57 (patch)
tree6f6fd4039cdb3df4d91d33e2fbf4b9088a1898f5 /services
parent0f6ba077321ef275649fdcc29c0b323e9740d739 (diff)
parentde4ef020ec5c3acdc90c4ba43011dda20d98d4dd (diff)
downloadframeworks_base-fd7e534b1f783c6bdd0e27196071d33fb14a7d57.zip
frameworks_base-fd7e534b1f783c6bdd0e27196071d33fb14a7d57.tar.gz
frameworks_base-fd7e534b1f783c6bdd0e27196071d33fb14a7d57.tar.bz2
Merge "Implement separate stacks."
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java60
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java36
-rw-r--r--services/java/com/android/server/am/ActivityStack.java390
-rw-r--r--services/java/com/android/server/am/ActivityStackSupervisor.java419
-rw-r--r--services/java/com/android/server/am/CompatModePackages.java10
-rw-r--r--services/java/com/android/server/am/TaskRecord.java35
-rw-r--r--services/java/com/android/server/wm/DisplayContent.java106
-rw-r--r--services/java/com/android/server/wm/StackBox.java21
-rw-r--r--services/java/com/android/server/wm/Task.java2
-rw-r--r--services/java/com/android/server/wm/TaskStack.java11
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java10
11 files changed, 628 insertions, 472 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index e86340d..74b838f 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2610,7 +2610,7 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (this) {
// If this is coming from the currently resumed activity, it is
// effectively saying that app switches are allowed at this point.
- final ActivityStack stack = getMainStack();
+ final ActivityStack stack = getTopStack();
if (stack.mResumedActivity != null &&
stack.mResumedActivity.info.applicationInfo.uid == Binder.getCallingUid()) {
mAppSwitchesAllowedTime = 0;
@@ -5898,6 +5898,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) {
+ mRecentTasks.remove(tr);
+ mStackSupervisor.removeTask(tr);
final boolean killProcesses = (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0;
Intent baseIntent = new Intent(
tr.intent != null ? tr.intent : tr.affinityIntent);
@@ -5955,14 +5957,12 @@ public final class ActivityManagerService extends ActivityManagerNative
if (tr != null) {
ActivityRecord r = tr.stack.removeTaskActivitiesLocked(taskId, -1, false);
if (r != null) {
- mRecentTasks.remove(tr);
cleanUpRemovedTaskLocked(tr, flags);
return true;
}
if (tr.mActivities.size() == 0) {
// Caller is just removing a recent task that is
// not actively running. That is easy!
- mRecentTasks.remove(tr);
cleanUpRemovedTaskLocked(tr, flags);
return true;
}
@@ -6003,12 +6003,12 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void moveTaskToBack(int task) {
+ public void moveTaskToBack(int taskId) {
enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
"moveTaskToBack()");
synchronized(this) {
- TaskRecord tr = recentTaskForIdLocked(task);
+ TaskRecord tr = recentTaskForIdLocked(taskId);
if (tr != null) {
ActivityStack stack = tr.stack;
if (stack.mResumedActivity != null && stack.mResumedActivity.task == tr) {
@@ -6018,7 +6018,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
final long origId = Binder.clearCallingIdentity();
- stack.moveTaskToBackLocked(task, null);
+ stack.moveTaskToBackLocked(taskId, null);
Binder.restoreCallingIdentity(origId);
}
}
@@ -6071,7 +6071,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public int createStack(int relativeStackId, int position, float weight) {
synchronized (this) {
int stackId = mStackSupervisor.createStack(relativeStackId, position, weight);
- mWindowManager.createStack(stackId, position, relativeStackId, weight);
+ mWindowManager.createStack(stackId, relativeStackId, position, weight);
return stackId;
}
}
@@ -7003,7 +7003,7 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(this) {
final long origId = Binder.clearCallingIdentity();
try {
- getMainStack().unhandledBackLocked();
+ getTopStack().unhandledBackLocked();
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -7393,7 +7393,7 @@ public final class ActivityManagerService extends ActivityManagerNative
PendingActivityExtras pae;
Bundle extras = new Bundle();
synchronized (this) {
- ActivityRecord activity = getMainStack().mResumedActivity;
+ ActivityRecord activity = getTopStack().mResumedActivity;
if (activity == null) {
Slog.w(TAG, "getTopActivityExtras failed: no resumed activity");
return null;
@@ -7489,7 +7489,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public boolean isTopActivityImmersive() {
enforceNotIsolatedCaller("startActivity");
synchronized (this) {
- ActivityRecord r = getMainStack().topRunningActivityLocked(null);
+ ActivityRecord r = getTopStack().topRunningActivityLocked(null);
return (r != null) ? r.immersive : false;
}
}
@@ -9391,7 +9391,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
pw.println(" mConfiguration: " + mConfiguration);
if (dumpAll) {
- pw.println(" mConfigWillChange: " + getMainStack().mConfigWillChange);
+ pw.println(" mConfigWillChange: " + getTopStack().mConfigWillChange);
if (mCompatModePackages.getPackages().size() > 0) {
boolean printed = false;
for (Map.Entry<String, Integer> entry
@@ -9451,8 +9451,8 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.print(" mLastPowerCheckUptime=");
TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
pw.println("");
- pw.println(" mGoingToSleep=" + getMainStack().mGoingToSleep);
- pw.println(" mLaunchingActivity=" + getMainStack().mLaunchingActivity);
+ pw.println(" mGoingToSleep=" + getTopStack().mGoingToSleep);
+ pw.println(" mLaunchingActivity=" + getTopStack().mLaunchingActivity);
pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
pw.println(" mNumNonHiddenProcs=" + mNumNonHiddenProcs
+ " mNumHiddenProcs=" + mNumHiddenProcs
@@ -12185,8 +12185,8 @@ public final class ActivityManagerService extends ActivityManagerNative
return config;
}
- ActivityStack getMainStack() {
- return mStackSupervisor.getMainStack();
+ ActivityStack getTopStack() {
+ return mStackSupervisor.getTopStack();
}
public Configuration getConfiguration() {
@@ -12250,9 +12250,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (mHeadless) return true;
int changes = 0;
-
- boolean kept = true;
-
+
if (values != null) {
Configuration newConfig = new Configuration(mConfiguration);
changes = newConfig.updateFrom(values);
@@ -12331,7 +12329,21 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- kept = mStackSupervisor.updateConfigurationLocked(changes, starting);
+ boolean kept = true;
+ final ActivityStack mainStack = mStackSupervisor.getTopStack();
+ if (changes != 0 && starting == null) {
+ // If the configuration changed, and the caller is not already
+ // in the process of starting an activity, then find the top
+ // activity to check if its configuration needs to change.
+ starting = mainStack.topRunningActivityLocked(null);
+ }
+
+ if (starting != null) {
+ kept = mainStack.ensureActivityConfigurationLocked(starting, changes);
+ // And we need to make sure at this point that all other activities
+ // are made visible with the correct configuration.
+ mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes);
+ }
if (values != null && mWindowManager != null) {
mWindowManager.setNewConfiguration(mConfiguration);
@@ -13409,15 +13421,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private final ActivityRecord resumedAppLocked() {
- final ActivityStack stack = mStackSupervisor.getMainStack();
- ActivityRecord resumedActivity = stack.mResumedActivity;
- if (resumedActivity == null || resumedActivity.app == null) {
- resumedActivity = stack.mPausingActivity;
- if (resumedActivity == null || resumedActivity.app == null) {
- resumedActivity = stack.topRunningActivityLocked(null);
- }
- }
- return resumedActivity;
+ return mStackSupervisor.resumedAppLocked();
}
final boolean updateOomAdjLocked(ProcessRecord app) {
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 3384c20..351d329 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -127,8 +127,12 @@ final class ActivityRecord {
long lastLaunchTime; // time of last lauch of this activity
String stringName; // for caching of toString().
-
+
private boolean inHistory; // are we in the history stack?
+ final ActivityStackSupervisor mStackSupervisor;
+
+ /** Launch the home activity rather than the activity at the top of stack */
+ boolean mLaunchHomeTaskNext;
void dump(PrintWriter pw, String prefix) {
final long now = SystemClock.uptimeMillis();
@@ -268,28 +272,28 @@ final class ActivityRecord {
weakActivity = new WeakReference<ActivityRecord>(activity);
}
- @Override public void windowsDrawn() throws RemoteException {
+ @Override public void windowsDrawn() {
ActivityRecord activity = weakActivity.get();
if (activity != null) {
activity.windowsDrawn();
}
}
- @Override public void windowsVisible() throws RemoteException {
+ @Override public void windowsVisible() {
ActivityRecord activity = weakActivity.get();
if (activity != null) {
activity.windowsVisible();
}
}
- @Override public void windowsGone() throws RemoteException {
+ @Override public void windowsGone() {
ActivityRecord activity = weakActivity.get();
if (activity != null) {
activity.windowsGone();
}
}
- @Override public boolean keyDispatchingTimedOut() throws RemoteException {
+ @Override public boolean keyDispatchingTimedOut() {
ActivityRecord activity = weakActivity.get();
if (activity != null) {
return activity.keyDispatchingTimedOut();
@@ -297,7 +301,7 @@ final class ActivityRecord {
return false;
}
- @Override public long getKeyDispatchingTimeout() throws RemoteException {
+ @Override public long getKeyDispatchingTimeout() {
ActivityRecord activity = weakActivity.get();
if (activity != null) {
return activity.getKeyDispatchingTimeout();
@@ -305,6 +309,7 @@ final class ActivityRecord {
return 0;
}
+ @Override
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("Token{");
@@ -329,7 +334,7 @@ final class ActivityRecord {
int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration,
ActivityRecord _resultTo, String _resultWho, int _reqCode,
- boolean _componentSpecified) {
+ boolean _componentSpecified, ActivityStackSupervisor supervisor) {
service = _service;
appToken = new Token(this);
info = aInfo;
@@ -359,6 +364,7 @@ final class ActivityRecord {
thumbnailNeeded = false;
idle = false;
hasBeenLaunched = false;
+ mStackSupervisor = supervisor;
// This starts out true, since the initial state of an activity
// is that we have everything, and we shouldn't never consider it
@@ -466,6 +472,9 @@ final class ActivityRecord {
}
void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) {
+ if (task != null && task.removeActivity(this)) {
+ mStackSupervisor.removeTask(task);
+ }
if (inHistory && !finishing) {
if (task != null) {
task.numActivities--;
@@ -524,6 +533,11 @@ final class ActivityRecord {
}
}
+ boolean isRootActivity() {
+ ArrayList<ActivityRecord> activities = task.mActivities;
+ return activities.size() == 0 || this == task.mActivities.get(0);
+ }
+
UriPermissionOwner getUriPermissionsLocked() {
if (uriPermissions == null) {
uriPermissions = new UriPermissionOwner(service, this);
@@ -814,23 +828,23 @@ final class ActivityRecord {
// Instead of doing the full stop routine here, let's just
// hide any activities we now can, and let them stop when
// the normal idle happens.
- stack.processStoppingActivitiesLocked(false);
+ mStackSupervisor.processStoppingActivitiesLocked(false);
} else {
// If this activity was already idle, then we now need to
// make sure we perform the full stop of any activities
// that are waiting to do so. This is because we won't
// do that while they are still waiting for this one to
// become visible.
- final int N = stack.mWaitingVisibleActivities.size();
+ final int N = mStackSupervisor.mWaitingVisibleActivities.size();
if (N > 0) {
for (int i=0; i<N; i++) {
- ActivityRecord r = stack.mWaitingVisibleActivities.get(i);
+ ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
r.waitingVisible = false;
if (ActivityManagerService.DEBUG_SWITCH) Log.v(
ActivityManagerService.TAG,
"Was waiting for visible: " + r);
}
- stack.mWaitingVisibleActivities.clear();
+ mStackSupervisor.mWaitingVisibleActivities.clear();
Message msg = Message.obtain();
msg.what = ActivityStack.IDLE_NOW_MSG;
stack.mHandler.sendMessage(msg);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index ca3da0b..568689f 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
+
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.util.Objects;
import com.android.server.am.ActivityManagerService.ItemMatcher;
@@ -73,7 +75,7 @@ final class ActivityStack {
static final boolean localLOGV = ActivityManagerService.localLOGV;
static final boolean DEBUG_SWITCH = ActivityManagerService.DEBUG_SWITCH;
static final boolean DEBUG_PAUSE = ActivityManagerService.DEBUG_PAUSE;
- static final boolean DEBUG_VISBILITY = ActivityManagerService.DEBUG_VISBILITY;
+ static final boolean DEBUG_VISBILITY = ActivityManagerService.DEBUG_VISBILITY || true;
static final boolean DEBUG_USER_LEAVING = ActivityManagerService.DEBUG_USER_LEAVING;
static final boolean DEBUG_TRANSITION = ActivityManagerService.DEBUG_TRANSITION;
static final boolean DEBUG_RESULTS = ActivityManagerService.DEBUG_RESULTS;
@@ -162,22 +164,6 @@ final class ActivityStack {
final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();
/**
- * List of activities that are waiting for a new activity
- * to become visible before completing whatever operation they are
- * supposed to do.
- */
- final ArrayList<ActivityRecord> mWaitingVisibleActivities
- = new ArrayList<ActivityRecord>();
-
- /**
- * List of activities that are ready to be stopped, but waiting
- * for the next activity to settle down before doing so. It contains
- * HistoryRecord objects.
- */
- final ArrayList<ActivityRecord> mStoppingActivities
- = new ArrayList<ActivityRecord>();
-
- /**
* List of activities that are in the process of going to sleep.
*/
final ArrayList<ActivityRecord> mGoingToSleepActivities
@@ -259,12 +245,6 @@ final class ActivityStack {
*/
boolean mConfigWillChange;
- /**
- * Set to indicate whether to issue an onUserLeaving callback when a
- * newly launched activity is being brought in front of us.
- */
- boolean mUserLeaving = false;
-
long mInitialStartTime = 0;
/**
@@ -409,7 +389,7 @@ final class ActivityStack {
} break;
case RESUME_TOP_ACTIVITY_MSG: {
synchronized (mService) {
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
}
} break;
case STOP_TIMEOUT_MSG: {
@@ -518,16 +498,14 @@ final class ActivityStack {
final ActivityRecord topActivity() {
// Iterate to find the first non-empty task stack. Note that this code can
- // go away once we stop storing tasks with empty mActivities lists.
- ActivityRecord prev = null;
+ // be simplified once we stop storing tasks with empty mActivities lists.
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- prev = activities.get(activityNdx);
- break;
+ return activities.get(activityNdx);
}
}
- return prev;
+ return null;
}
TaskRecord taskForIdLocked(int id) {
@@ -559,6 +537,10 @@ final class ActivityStack {
return hadit;
}
+ final boolean isHomeStack() {
+ return mStackId == HOME_STACK_ID;
+ }
+
/**
* Returns the top activity in any existing task matching the given
* Intent. Returns null if no such task is found.
@@ -747,10 +729,10 @@ final class ActivityStack {
return;
}
- if (mStoppingActivities.size() > 0) {
+ if (mStackSupervisor.mStoppingActivities.size() > 0) {
// Still need to tell some activities to stop; can't sleep yet.
if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
- + mStoppingActivities.size() + " activities");
+ + mStackSupervisor.mStoppingActivities.size() + " activities");
scheduleIdleLocked();
return;
}
@@ -826,7 +808,7 @@ final class ActivityStack {
if (prev == null) {
Slog.e(TAG, "Trying to pause when nothing is resumed",
new RuntimeException("here").fillInStackTrace());
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
return;
}
if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
@@ -848,7 +830,7 @@ final class ActivityStack {
prev.shortComponentName);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags);
- if (mStackSupervisor.isMainStack(this)) {
+ if (mStackSupervisor.isFrontStack(this)) {
mService.updateUsageStats(prev, false);
}
} catch (Exception e) {
@@ -896,7 +878,7 @@ final class ActivityStack {
// This activity failed to schedule the
// pause, so just treat it as being paused now.
if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
}
}
@@ -954,7 +936,7 @@ final class ActivityStack {
} else {
if (r.configDestroy) {
destroyActivityLocked(r, true, false, "stop-config");
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
} else {
// Now that this process has stopped, we may want to consider
// it to be the previous app to try to keep around in case
@@ -988,7 +970,7 @@ final class ActivityStack {
if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
if (prev.waitingVisible) {
prev.waitingVisible = false;
- mWaitingVisibleActivities.remove(prev);
+ mStackSupervisor.mWaitingVisibleActivities.remove(prev);
if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
TAG, "Complete pause, no longer waiting: " + prev);
}
@@ -1001,8 +983,8 @@ final class ActivityStack {
if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
destroyActivityLocked(prev, true, false, "pause-config");
} else {
- mStoppingActivities.add(prev);
- if (mStoppingActivities.size() > 3) {
+ mStackSupervisor.mStoppingActivities.add(prev);
+ if (mStackSupervisor.mStoppingActivities.size() > 3) {
// If we already have a few activities waiting to stop,
// then give up on things going idle and start clearing
// them out.
@@ -1019,18 +1001,19 @@ final class ActivityStack {
mPausingActivity = null;
}
+ final ActivityStack topStack = mStackSupervisor.getTopStack();
if (!mService.isSleepingOrShuttingDown()) {
- resumeTopActivityLocked(prev);
+ topStack.resumeTopActivityLocked(prev);
} else {
checkReadyForSleepLocked();
- ActivityRecord top = topRunningActivityLocked(null);
+ ActivityRecord top = topStack.topRunningActivityLocked(null);
if (top == null || (prev != null && top != prev)) {
// If there are no more activities available to run,
// do resume anyway to start something. Also if the top
// activity on the stack is not the just paused activity,
// we need to go ahead and resume it to ensure we complete
// an in-flight app switch.
- resumeTopActivityLocked(null);
+ topStack.resumeTopActivityLocked(null);
}
}
@@ -1086,18 +1069,17 @@ final class ActivityStack {
mHandler.sendMessage(msg);
}
- if (mStackSupervisor.isMainStack(this)) {
- // Should this be done for all stacks, not just mMainStack?
+ if (mStackSupervisor.isFrontStack(this)) {
+ // TODO: Should this be done for all stacks, not just mMainStack?
mService.reportResumedActivityLocked(next);
- }
-
- if (mStackSupervisor.isMainStack(this)) {
mService.setFocusedActivityLocked(next);
}
- next.resumeKeyDispatchingLocked();
- ensureActivitiesVisibleLocked(null, 0);
- mService.mWindowManager.executeAppTransition();
- mNoAnimActivities.clear();
+ if (mStackSupervisor.allResumedActivitiesComplete()) {
+ next.resumeKeyDispatchingLocked();
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ mService.mWindowManager.executeAppTransition();
+ mNoAnimActivities.clear();
+ }
// Mark the point when the activity is resuming
// TODO: To be more accurate, the mark should be before the onCreate,
@@ -1125,8 +1107,9 @@ final class ActivityStack {
// If the top activity is not fullscreen, then we need to
// make sure any activities under it are now visible.
boolean aboveTop = true;
- boolean behindFullscreen = false;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+ boolean behindFullscreen = !mStackSupervisor.isFrontStack(this);
+ int taskNdx;
+ for (taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
@@ -1152,13 +1135,11 @@ final class ActivityStack {
}
if (r.app == null || r.app.thread == null) {
- if (onlyThisProcess == null
- || onlyThisProcess.equals(r.processName)) {
+ if (onlyThisProcess == null || onlyThisProcess.equals(r.processName)) {
// This activity needs to be visible, but isn't even
// running... get it started, but don't resume it
// at this point.
- if (DEBUG_VISBILITY) Slog.v(
- TAG, "Start and freeze screen for " + r);
+ if (DEBUG_VISBILITY) Slog.v(TAG, "Start and freeze screen for " + r);
if (r != starting) {
r.startFreezingScreenLocked(r.app, configChanges);
}
@@ -1175,8 +1156,7 @@ final class ActivityStack {
} else if (r.visible) {
// If this activity is already visible, then there is nothing
// else to do here.
- if (DEBUG_VISBILITY) Slog.v(
- TAG, "Skipping: already visible at " + r);
+ if (DEBUG_VISBILITY) Slog.v(TAG, "Skipping: already visible at " + r);
r.stopFreezingScreenLocked(false);
} else if (onlyThisProcess == null) {
@@ -1213,17 +1193,21 @@ final class ActivityStack {
behindFullscreen = true;
}
} else {
+ if (DEBUG_VISBILITY) Slog.v(
+ TAG, "Make invisible? " + r + " finishing=" + r.finishing
+ + " state=" + r.state
+ + " behindFullscreen=" + behindFullscreen);
+ // Now for any activities that aren't visible to the user, make
+ // sure they no longer are keeping the screen frozen.
if (r.visible) {
- if (DEBUG_VISBILITY) Slog.v(
- TAG, "Making invisible: " + r);
+ if (DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
r.visible = false;
try {
mService.mWindowManager.setAppVisibility(r.appToken, false);
if ((r.state == ActivityState.STOPPING
|| r.state == ActivityState.STOPPED)
&& r.app != null && r.app.thread != null) {
- if (DEBUG_VISBILITY) Slog.v(
- TAG, "Scheduling invisibility: " + r);
+ if (DEBUG_VISBILITY) Slog.v(TAG, "Scheduling invisibility: " + r);
r.app.thread.scheduleWindowVisibility(r.appToken, false);
}
} catch (Exception e) {
@@ -1233,8 +1217,7 @@ final class ActivityStack {
+ r.intent.getComponent(), e);
}
} else {
- if (DEBUG_VISBILITY) Slog.v(
- TAG, "Already invisible: " + r);
+ if (DEBUG_VISBILITY) Slog.v(TAG, "Already invisible: " + r);
}
}
}
@@ -1273,22 +1256,21 @@ final class ActivityStack {
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
- final boolean userLeaving = mUserLeaving;
- mUserLeaving = false;
+ final boolean userLeaving = mStackSupervisor.mUserLeaving;
+ mStackSupervisor.mUserLeaving = false;
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
- if (mStackSupervisor.isMainStack(this)) {
- ActivityOptions.abort(options);
- return mService.startHomeActivityLocked(mCurrentUser);
- }
+ ActivityOptions.abort(options);
+ return mService.startHomeActivityLocked(mCurrentUser);
}
next.delayedResume = false;
// If the top activity is the resumed one, nothing to do.
- if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
+ if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
+ mStackSupervisor.allResumedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mService.mWindowManager.executeAppTransition();
@@ -1297,13 +1279,17 @@ final class ActivityStack {
return false;
}
+ if (prev != null && prev.mLaunchHomeTaskNext && prev.finishing &&
+ prev.task.getTopActivity() == null) {
+ prev.mLaunchHomeTaskNext = false;
+ return mService.startHomeActivityLocked(mCurrentUser);
+ }
+
// If we are sleeping, and there is no resumed activity, and the top
// activity is paused, well that is the state we want.
- if ((mService.mSleeping || mService.mShuttingDown)
+ if ((mService.isSleepingOrShuttingDown())
&& mLastPausedActivity == next
- && (next.state == ActivityState.PAUSED
- || next.state == ActivityState.STOPPED
- || next.state == ActivityState.STOPPING)) {
+ && mStackSupervisor.allPausedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mService.mWindowManager.executeAppTransition();
@@ -1323,10 +1309,10 @@ final class ActivityStack {
// The activity may be waiting for stop, but that is no longer
// appropriate for it.
- mStoppingActivities.remove(next);
+ mStackSupervisor.mStoppingActivities.remove(next);
mGoingToSleepActivities.remove(next);
next.sleeping = false;
- mWaitingVisibleActivities.remove(next);
+ mStackSupervisor.mWaitingVisibleActivities.remove(next);
next.updateOptionsLocked(options);
@@ -1371,7 +1357,8 @@ final class ActivityStack {
// We need to start pausing the current activity so the top one
// can be resumed...
- if (mResumedActivity != null) {
+ final ActivityStack lastStack = mStackSupervisor.getLastStack();
+ if (lastStack.mResumedActivity != null) {
if (DEBUG_SWITCH) Slog.v(TAG, "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
@@ -1382,7 +1369,7 @@ final class ActivityStack {
// happen whenever it needs to later.
mService.updateLruProcessLocked(next.app, false);
}
- startPausingLocked(userLeaving, false);
+ lastStack.startPausingLocked(userLeaving, false);
return true;
}
@@ -1404,7 +1391,7 @@ final class ActivityStack {
if (prev != null && prev != next) {
if (!prev.waitingVisible && next != null && !next.nowVisible) {
prev.waitingVisible = true;
- mWaitingVisibleActivities.add(prev);
+ mStackSupervisor.mWaitingVisibleActivities.add(prev);
if (DEBUG_SWITCH) Slog.v(
TAG, "Resuming top, waiting visible to hide: " + prev);
} else {
@@ -1504,7 +1491,7 @@ final class ActivityStack {
// schedule launch ticks to collect information about slow apps.
next.startLaunchTickingLocked();
- ActivityRecord lastResumedActivity = mResumedActivity;
+ ActivityRecord lastResumedActivity = lastStack.mResumedActivity;
ActivityState lastState = next.state;
mService.updateCpuStats();
@@ -1520,7 +1507,7 @@ final class ActivityStack {
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order.
boolean updated = false;
- if (mStackSupervisor.isMainStack(this)) {
+ if (mStackSupervisor.isFrontStack(this)) {
Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
@@ -1544,13 +1531,16 @@ final class ActivityStack {
// Do over!
mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
}
- if (mStackSupervisor.isMainStack(this)) {
+ if (mStackSupervisor.isFrontStack(this)) {
mService.setFocusedActivityLocked(next);
}
- ensureActivitiesVisibleLocked(null, 0);
- mService.mWindowManager.executeAppTransition();
- mNoAnimActivities.clear();
- return true;
+ if (mStackSupervisor.allResumedActivitiesComplete()) {
+ ensureActivitiesVisibleLocked(null, 0);
+ mService.mWindowManager.executeAppTransition();
+ mNoAnimActivities.clear();
+ return true;
+ }
+ return false;
}
try {
@@ -1587,12 +1577,12 @@ final class ActivityStack {
if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
+ lastState + ": " + next);
next.state = lastState;
- mResumedActivity = lastResumedActivity;
+ lastStack.mResumedActivity = lastResumedActivity;
Slog.i(TAG, "Restarting because process died: " + next);
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
- if (SHOW_APP_STARTING_PREVIEW && mStackSupervisor.isMainStack(this)) {
+ if (SHOW_APP_STARTING_PREVIEW && mStackSupervisor.isFrontStack(lastStack)) {
mService.mWindowManager.setAppStartingWindow(
next.appToken, next.packageName, next.theme,
mService.compatibilityInfoForPackageLocked(
@@ -1696,7 +1686,7 @@ final class ActivityStack {
// to deliver the onUserLeaving callback to the actual frontmost
// activity
if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
- mUserLeaving = false;
+ mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG,
"startActivity() behind front, mUserLeaving=false");
}
@@ -1710,7 +1700,7 @@ final class ActivityStack {
r.putInHistory();
r.frontOfTask = newTask;
- if (numActivities() > 1) {
+ if (!isHomeStack() || numActivities() > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
// not currently running.
@@ -1784,7 +1774,7 @@ final class ActivityStack {
}
if (doResume) {
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
}
}
@@ -1874,11 +1864,11 @@ final class ActivityStack {
// If the activity currently at the bottom has the
// same task affinity as the one we are moving,
// then merge it into the same task.
- setTask(target, p.task, p.thumbHolder, false);
+ target.setTask(p.task, p.thumbHolder, false);
if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
+ " out to bottom task " + p.task);
} else {
- setTask(target, createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
+ target.setTask(createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
null, false), null, false);
target.task.affinityIntent = target.intent;
if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
@@ -1912,7 +1902,7 @@ final class ActivityStack {
new RuntimeException("here").fillInStackTrace());
if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
+ " out to target's task " + target.task);
- setTask(p, targetTask, curThumbHolder, false);
+ p.setTask(targetTask, curThumbHolder, false);
targetTask.addActivityAtBottom(p);
mService.mWindowManager.setAppGroupId(p.appToken, targetTaskId);
@@ -2042,7 +2032,7 @@ final class ActivityStack {
+ start + "-" + i + " to task=" + task + ":" + taskInsertionPoint);
for (int srcPos = start; srcPos >= i; --srcPos) {
final ActivityRecord p = activities.get(srcPos);
- setTask(p, task, null, false);
+ p.setTask(task, null, false);
task.addActivityAtIndex(taskInsertionPoint, p);
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + p
@@ -2153,31 +2143,6 @@ final class ActivityStack {
return null;
}
- /**
- * Reorder the history stack so that the activity at the given index is
- * brought to the front.
- */
- final void moveActivityToFrontLocked(ActivityRecord newTop) {
- if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + newTop
- + " to stack at top", new RuntimeException("here").fillInStackTrace());
-
- final TaskRecord task = newTop.task;
- task.getTopActivity().frontOfTask = false;
- task.mActivities.remove(newTop);
- task.mActivities.add(newTop);
- newTop.frontOfTask = true;
- }
-
- final void moveHomeToFrontFromLaunchLocked(int launchFlags) {
- if ((launchFlags &
- (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
- == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
- // Caller wants to appear on home activity, so before starting
- // their own activity we will bring home to the front.
- moveHomeToFrontLocked();
- }
- }
-
void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
long thisTime, long totalTime) {
for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
@@ -2251,7 +2216,7 @@ final class ActivityStack {
}
if (r.app != null && r.app.thread != null) {
- if (mStackSupervisor.isMainStack(this)) {
+ if (mStackSupervisor.isFrontStack(this)) {
if (mService.mFocusedActivity == r) {
mService.setFocusedActivityLocked(topRunningActivityLocked(null));
}
@@ -2290,49 +2255,6 @@ final class ActivityStack {
}
}
- final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
- boolean remove) {
- int N = mStoppingActivities.size();
- if (N <= 0) return null;
-
- ArrayList<ActivityRecord> stops = null;
-
- final boolean nowVisible = mResumedActivity != null
- && mResumedActivity.nowVisible
- && !mResumedActivity.waitingVisible;
- for (int i=0; i<N; i++) {
- ActivityRecord s = mStoppingActivities.get(i);
- if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
- + nowVisible + " waitingVisible=" + s.waitingVisible
- + " finishing=" + s.finishing);
- if (s.waitingVisible && nowVisible) {
- mWaitingVisibleActivities.remove(s);
- s.waitingVisible = false;
- if (s.finishing) {
- // If this activity is finishing, it is sitting on top of
- // everyone else but we now know it is no longer needed...
- // so get rid of it. Otherwise, we need to go through the
- // normal flow and hide it once we determine that it is
- // hidden by the activities in front of it.
- if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
- mService.mWindowManager.setAppVisibility(s.appToken, false);
- }
- }
- if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
- if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
- if (stops == null) {
- stops = new ArrayList<ActivityRecord>();
- }
- stops.add(s);
- mStoppingActivities.remove(i);
- N--;
- i--;
- }
- }
-
- return stops;
- }
-
final void scheduleIdleLocked() {
Message msg = Message.obtain();
msg.what = IDLE_NOW_MSG;
@@ -2402,7 +2324,7 @@ final class ActivityStack {
ensureActivitiesVisibleLocked(null, 0);
//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
- if (!mService.mBooted && mStackSupervisor.isMainStack(this)) {
+ if (!mService.mBooted && mStackSupervisor.isFrontStack(this)) {
mService.mBooted = true;
enableScreen = true;
}
@@ -2411,7 +2333,7 @@ final class ActivityStack {
}
// Atomically retrieve all of the other things to do.
- stops = processStoppingActivitiesLocked(true);
+ stops = mStackSupervisor.processStoppingActivitiesLocked(true);
NS = stops != null ? stops.size() : 0;
if ((NF=mFinishingActivities.size()) > 0) {
finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
@@ -2427,7 +2349,7 @@ final class ActivityStack {
thumbnails = null;
}
- if (mStackSupervisor.isMainStack(this)) {
+ if (mStackSupervisor.isFrontStack(this)) {
booting = mService.mBooting;
mService.mBooting = false;
}
@@ -2494,7 +2416,7 @@ final class ActivityStack {
}
if (activityRemoved) {
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
}
return res;
@@ -2581,8 +2503,7 @@ final class ActivityStack {
if (!Objects.equal(cur.taskAffinity, r.taskAffinity)) {
break;
}
- finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity",
- true);
+ finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true);
}
return true;
}
@@ -2620,15 +2541,6 @@ final class ActivityStack {
*/
final boolean finishActivityLocked(ActivityRecord r, int resultCode,
Intent resultData, String reason, boolean oomAdj) {
- return finishActivityLocked(r, resultCode, resultData, reason, false, oomAdj);
- }
-
- /**
- * @return Returns true if this activity has been removed from the history
- * list, or false if it is still in the list and will be removed later.
- */
- final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
- String reason, boolean immediate, boolean oomAdj) {
if (r.finishing) {
Slog.w(TAG, "Duplicate finish request for " + r);
return false;
@@ -2655,7 +2567,7 @@ final class ActivityStack {
}
r.pauseKeyDispatchingLocked();
- if (mStackSupervisor.isMainStack(this)) {
+ if (mStackSupervisor.isFrontStack(this)) {
if (mService.mFocusedActivity == r) {
mService.setFocusedActivityLocked(topRunningActivityLocked(null));
}
@@ -2670,9 +2582,7 @@ final class ActivityStack {
mCancelledThumbnails.add(r);
}
- if (immediate) {
- return finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, oomAdj) == null;
- } else if (mResumedActivity == r) {
+ if (mResumedActivity == r) {
boolean endTask = index <= 0;
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare close transition: finishing " + r);
@@ -2711,9 +2621,9 @@ final class ActivityStack {
// and the resumed activity is not yet visible, then hold off on
// finishing until the resumed one becomes visible.
if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
- if (!mStoppingActivities.contains(r)) {
- mStoppingActivities.add(r);
- if (mStoppingActivities.size() > 3) {
+ if (!mStackSupervisor.mStoppingActivities.contains(r)) {
+ mStackSupervisor.mStoppingActivities.add(r);
+ if (mStackSupervisor.mStoppingActivities.size() > 3) {
// If we already have a few activities waiting to stop,
// then give up on things going idle and start clearing
// them out.
@@ -2732,9 +2642,9 @@ final class ActivityStack {
}
// make sure the record is cleaned out of other places.
- mStoppingActivities.remove(r);
+ mStackSupervisor.mStoppingActivities.remove(r);
mGoingToSleepActivities.remove(r);
- mWaitingVisibleActivities.remove(r);
+ mStackSupervisor.mWaitingVisibleActivities.remove(r);
if (mResumedActivity == r) {
mResumedActivity = null;
}
@@ -2750,7 +2660,7 @@ final class ActivityStack {
boolean activityRemoved = destroyActivityLocked(r, true,
oomAdj, "finish-imm");
if (activityRemoved) {
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
}
return activityRemoved ? null : r;
}
@@ -2759,7 +2669,7 @@ final class ActivityStack {
// activity into the stopped state and then finish it.
if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
mFinishingActivities.add(r);
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
return r;
}
@@ -2872,7 +2782,7 @@ final class ActivityStack {
// This could happen, for example, if we are trimming activities
// down to the max limit while they are still waiting to finish.
mFinishingActivities.remove(r);
- mWaitingVisibleActivities.remove(r);
+ mStackSupervisor.mWaitingVisibleActivities.remove(r);
// Remove any pending results.
if (r.finishing && r.pendingResults != null) {
@@ -2916,8 +2826,9 @@ final class ActivityStack {
here.fillInStackTrace();
Slog.i(TAG, "Removing activity " + r + " from stack");
}
- if (r.task != null) {
- removeActivity(r);
+ final TaskRecord task = r.task;
+ if (task != null && task.removeActivity(r)) {
+ mStackSupervisor.removeTask(task);
}
r.takeFromHistory();
removeTimeoutsForActivityLocked(r);
@@ -2989,7 +2900,7 @@ final class ActivityStack {
}
}
if (activityRemoved) {
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
}
}
@@ -3106,12 +3017,12 @@ final class ActivityStack {
removeActivityFromHistoryLocked(r);
}
}
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
} finally {
Binder.restoreCallingIdentity(origId);
}
}
-
+
private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
ProcessRecord app, String listName) {
int i = list.size();
@@ -3132,9 +3043,10 @@ final class ActivityStack {
boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
- removeHistoryRecordsForAppLocked(mStoppingActivities, app, "mStoppingActivities");
+ removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
+ "mStoppingActivities");
removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app, "mGoingToSleepActivities");
- removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app,
+ removeHistoryRecordsForAppLocked(mStackSupervisor.mWaitingVisibleActivities, app,
"mWaitingVisibleActivities");
removeHistoryRecordsForAppLocked(mFinishingActivities, app, "mFinishingActivities");
@@ -3212,24 +3124,6 @@ final class ActivityStack {
return hasVisibleActivities;
}
- /**
- * Move the current home activity's task (if one exists) to the front
- * of the stack.
- */
- final void moveHomeToFrontLocked() {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
- final ArrayList<ActivityRecord> activities = task.mActivities;
- for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- final ActivityRecord r = activities.get(activityNdx);
- if (r.isHomeActivity) {
- moveTaskToFrontLocked(task, null, null);
- return;
- }
- }
- }
- }
-
final void updateTransitLocked(int transit, Bundle options) {
if (options != null) {
ActivityRecord r = topRunningActivityLocked(null);
@@ -3246,12 +3140,12 @@ final class ActivityStack {
final TaskRecord task = taskForIdLocked(taskId);
if (task != null) {
if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
- mUserLeaving = true;
+ mStackSupervisor.mUserLeaving = true;
}
if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
// Caller wants the home activity moved with it. To accomplish this,
// we'll just move the home task to the top first.
- moveHomeToFrontLocked();
+ task.mActivities.get(0).mLaunchHomeTaskNext = true;
}
moveTaskToFrontLocked(task, null, options);
return true;
@@ -3295,7 +3189,7 @@ final class ActivityStack {
mService.mWindowManager.moveTaskToTop(tr.taskId);
- resumeTopActivityLocked(null);
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
if (VALIDATE_TOKENS) {
@@ -3320,7 +3214,7 @@ final class ActivityStack {
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
- if (mStackSupervisor.isMainStack(this) && mService.mController != null) {
+ if (mStackSupervisor.isFrontStack(this) && mService.mController != null) {
ActivityRecord next = topRunningActivityLocked(null, task);
if (next == null) {
next = topRunningActivityLocked(null, 0);
@@ -3366,15 +3260,20 @@ final class ActivityStack {
validateAppTokensLocked();
}
- resumeTopActivityLocked(null);
+ if (mResumedActivity != null && mResumedActivity.task == tr &&
+ mResumedActivity.mLaunchHomeTaskNext) {
+ mResumedActivity.mLaunchHomeTaskNext = false;
+ return mService.startHomeActivityLocked(mCurrentUser);
+ }
+
+ mStackSupervisor.getTopStack().resumeTopActivityLocked(null);
return true;
}
public ActivityManager.TaskThumbnails getTaskThumbnailsLocked(TaskRecord tr) {
TaskAccessInfo info = getTaskAccessInfoLocked(tr, true);
- ActivityRecord resumed = mResumedActivity;
- if (resumed != null && resumed.thumbHolder == tr) {
- info.mainThumbnail = screenshotActivities(resumed);
+ if (mResumedActivity != null && mResumedActivity.thumbHolder == tr) {
+ info.mainThumbnail = screenshotActivities(mResumedActivity);
}
if (info.mainThumbnail == null) {
info.mainThumbnail = tr.lastThumbnail;
@@ -3383,11 +3282,10 @@ final class ActivityStack {
}
public Bitmap getTaskTopThumbnailLocked(TaskRecord tr) {
- ActivityRecord resumed = mResumedActivity;
- if (resumed != null && resumed.task == tr) {
+ if (mResumedActivity != null && mResumedActivity.task == tr) {
// This task is the current resumed task, we just need to take
// a screenshot of it and return that.
- return screenshotActivities(resumed);
+ return screenshotActivities(mResumedActivity);
}
// Return the information about the task, to figure out the top
// thumbnail to return.
@@ -3483,9 +3381,8 @@ final class ActivityStack {
return null;
}
TaskAccessInfo.SubTask sub = thumbs.subtasks.get(index);
- ActivityRecord resumed = mResumedActivity;
- if (resumed != null && resumed.thumbHolder == sub.holder) {
- return screenshotActivities(resumed);
+ if (mResumedActivity != null && mResumedActivity.thumbHolder == sub.holder) {
+ return screenshotActivities(mResumedActivity);
}
return sub.holder.lastThumbnail;
}
@@ -3663,7 +3560,7 @@ final class ActivityStack {
if (andResume) {
r.results = null;
r.newIntents = null;
- if (mStackSupervisor.isMainStack(this)) {
+ if (mStackSupervisor.isFrontStack(this)) {
mService.reportResumedActivityLocked(r);
}
r.state = ActivityState.RESUMED;
@@ -3829,7 +3726,7 @@ final class ActivityStack {
boolean hasVisibleActivities = removeHistoryRecordsForAppLocked(app);
if (!restarting) {
- if (!resumeTopActivityLocked(null)) {
+ if (!mStackSupervisor.getTopStack().resumeTopActivityLocked(null)) {
// If there was nothing to resume, and we are not already
// restarting this process, but there is a visible activity that
// is hosted by the process... then make sure all visible
@@ -3920,26 +3817,12 @@ final class ActivityStack {
return starting;
}
- private void removeActivity(ActivityRecord r) {
- final TaskRecord task = r.task;
- // TODO: use ActivityManagerService.removeTask to do this.
- if (task.removeActivity(r)) {
- if (DEBUG_ADD_REMOVE) Slog.i(TAG, "removeActivity: Removing from history, task="
- + task);
- mTaskHistory.remove(task);
- }
- }
-
- void setTask(ActivityRecord r, TaskRecord newTask, ThumbnailHolder newThumbHolder,
- boolean isRoot) {
- if (r.task != null) {
- removeActivity(r);
- }
- r.setTask(newTask, newThumbHolder, isRoot);
+ boolean removeTask(TaskRecord task) {
+ mTaskHistory.remove(task);
+ return mTaskHistory.size() == 0;
}
- TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
- boolean toTop) {
+ TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, boolean toTop) {
TaskRecord task = new TaskRecord(taskId, info, intent, this);
if (toTop) {
mTaskHistory.add(task);
@@ -3970,4 +3853,9 @@ final class ActivityStack {
public int getStackId() {
return mStackId;
}
+
+ @Override
+ public String toString() {
+ return "stackId=" + mStackId + " tasks=" + mTaskHistory;
+ }
}
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 4c08f85..d3e5b48 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -61,6 +61,7 @@ import android.util.Slog;
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.wm.StackBox;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -69,10 +70,11 @@ import java.util.ArrayList;
import java.util.List;
public class ActivityStackSupervisor {
- static final boolean DEBUG_ADD_REMOVE = false;
- static final boolean DEBUG_APP = false;
- static final boolean DEBUG_SAVED_STATE = false;
- static final boolean DEBUG_STATES = false;
+ static final boolean DEBUG = ActivityManagerService.DEBUG || false;
+ static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
+ static final boolean DEBUG_APP = DEBUG || false;
+ static final boolean DEBUG_SAVED_STATE = DEBUG || false;
+ static final boolean DEBUG_STATES = DEBUG || false;
public static final int HOME_STACK_ID = 0;
@@ -96,12 +98,31 @@ public class ActivityStackSupervisor {
/** The stack containing the launcher app */
private ActivityStack mHomeStack;
- /** The stack currently receiving input or launching the next activity */
+ /** The non-home stack currently receiving input or launching the next activity. If home is
+ * in front then mHomeStack overrides mMainStack. */
private ActivityStack mMainStack;
/** All the non-launcher stacks */
private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
+ private static final int STACK_STATE_HOME_IN_FRONT = 0;
+ private static final int STACK_STATE_HOME_TO_BACK = 1;
+ private static final int STACK_STATE_HOME_IN_BACK = 2;
+ private static final int STACK_STATE_HOME_TO_FRONT = 3;
+ private int mStackState = STACK_STATE_HOME_IN_FRONT;
+
+ /** List of activities that are waiting for a new activity to become visible before completing
+ * whatever operation they are supposed to do. */
+ final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
+
+ /** List of activities that are ready to be stopped, but waiting for the next activity to
+ * settle down before doing so. */
+ final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
+
+ /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
+ * is being brought in front of us. */
+ boolean mUserLeaving = false;
+
public ActivityStackSupervisor(ActivityManagerService service, Context context,
Looper looper) {
mService = service;
@@ -111,7 +132,6 @@ public class ActivityStackSupervisor {
void init(int userId) {
mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this, userId);
- setMainStack(mHomeStack);
mStacks.add(mHomeStack);
}
@@ -122,20 +142,59 @@ public class ActivityStackSupervisor {
}
}
- boolean isHomeStackMain() {
- return mHomeStack == mMainStack;
+ ActivityStack getTopStack() {
+ switch (mStackState) {
+ case STACK_STATE_HOME_IN_FRONT:
+ case STACK_STATE_HOME_TO_FRONT:
+ return mHomeStack;
+ case STACK_STATE_HOME_IN_BACK:
+ case STACK_STATE_HOME_TO_BACK:
+ default:
+ return mMainStack;
+ }
}
- boolean isMainStack(ActivityStack stack) {
- return stack == mMainStack;
+ ActivityStack getLastStack() {
+ switch (mStackState) {
+ case STACK_STATE_HOME_IN_FRONT:
+ case STACK_STATE_HOME_TO_BACK:
+ return mHomeStack;
+ case STACK_STATE_HOME_TO_FRONT:
+ case STACK_STATE_HOME_IN_BACK:
+ default:
+ return mMainStack;
+ }
}
- ActivityStack getMainStack() {
- return mMainStack;
+ boolean isFrontStack(ActivityStack stack) {
+ return stack == getTopStack();
}
- void setMainStack(ActivityStack stack) {
- mMainStack = stack;
+ boolean homeIsInFront() {
+ return isFrontStack(mHomeStack);
+ }
+
+ void moveHomeStack(boolean toFront) {
+ final boolean homeInFront = isFrontStack(mHomeStack);
+ if (homeInFront ^ toFront) {
+ mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
+ }
+ }
+
+ final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
+ ActivityStack stack) {
+ if (stack == mHomeStack) {
+ return;
+ }
+ if ((sourceRecord == null && getLastStack() == mHomeStack) ||
+ (sourceRecord != null && sourceRecord.isHomeActivity)) {
+ if (r == null) {
+ r = stack.topRunningActivityLocked(null);
+ }
+ if (r != null && !r.isHomeActivity && r.isRootActivity()) {
+ r.mLaunchHomeTaskNext = true;
+ }
+ }
}
void setDismissKeyguard(boolean dismiss) {
@@ -173,6 +232,33 @@ public class ActivityStackSupervisor {
return mCurTaskId;
}
+ void removeTask(TaskRecord task) {
+ final ActivityStack stack = task.stack;
+ if (stack.removeTask(task) && !stack.isHomeStack()) {
+ mStacks.remove(stack);
+ final int oldStackId = stack.mStackId;
+ final int newMainStackId = mService.mWindowManager.removeStack(oldStackId);
+ if (newMainStackId == HOME_STACK_ID) {
+ return;
+ }
+ if (mMainStack.mStackId == oldStackId) {
+ mMainStack = getStack(newMainStackId);
+ }
+ }
+ }
+
+ ActivityRecord resumedAppLocked() {
+ ActivityStack stack = getTopStack();
+ ActivityRecord resumedActivity = stack.mResumedActivity;
+ if (resumedActivity == null || resumedActivity.app == null) {
+ resumedActivity = stack.mPausingActivity;
+ if (resumedActivity == null || resumedActivity.app == null) {
+ resumedActivity = stack.topRunningActivityLocked(null);
+ }
+ }
+ return resumedActivity;
+ }
+
boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
boolean didSomething = false;
final String processName = app.processName;
@@ -212,6 +298,65 @@ public class ActivityStackSupervisor {
return true;
}
+ boolean allResumedActivitiesComplete() {
+ final boolean homeInBack = !homeIsInFront();
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = mStacks.get(stackNdx);
+ if (stack.isHomeStack() ^ homeInBack) {
+ final ActivityRecord r = stack.mResumedActivity;
+ if (r != null && r.state != ActivityState.RESUMED) {
+ return false;
+ }
+ }
+ }
+ // TODO: Not sure if this should check if all Paused are complete too.
+ switch (mStackState) {
+ case STACK_STATE_HOME_TO_BACK:
+ mStackState = STACK_STATE_HOME_IN_BACK;
+ break;
+ case STACK_STATE_HOME_TO_FRONT:
+ mStackState = STACK_STATE_HOME_IN_FRONT;
+ break;
+ }
+ return true;
+ }
+
+ boolean allResumedActivitiesVisible() {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = mStacks.get(stackNdx);
+ final ActivityRecord r = stack.mResumedActivity;
+ if (r != null && (!r.nowVisible || r.waitingVisible)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ boolean allPausedActivitiesComplete() {
+ final boolean homeInBack = !homeIsInFront();
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = mStacks.get(stackNdx);
+ if (stack.isHomeStack() ^ homeInBack) {
+ final ActivityRecord r = stack.mLastPausedActivity;
+ if (r != null && r.state != ActivityState.PAUSED
+ && r.state != ActivityState.STOPPED
+ && r.state != ActivityState.STOPPING) {
+ return false;
+ }
+ }
+ }
+ // TODO: Not sure if this should check if all Resumed are complete too.
+ switch (mStackState) {
+ case STACK_STATE_HOME_TO_BACK:
+ mStackState = STACK_STATE_HOME_IN_BACK;
+ break;
+ case STACK_STATE_HOME_TO_FRONT:
+ mStackState = STACK_STATE_HOME_IN_FRONT;
+ break;
+ }
+ return true;
+ }
+
ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
ActivityRecord r = null;
@@ -220,7 +365,7 @@ public class ActivityStackSupervisor {
final ActivityStack stack = mStacks.get(stackNdx);
final ActivityRecord ar =
stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
- if (isMainStack(stack)) {
+ if (isFrontStack(stack)) {
r = ar;
}
}
@@ -275,6 +420,7 @@ public class ActivityStackSupervisor {
}
void startHomeActivity(Intent intent, ActivityInfo aInfo) {
+ moveHomeStack(true);
startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
null, false, null);
}
@@ -308,10 +454,11 @@ public class ActivityStackSupervisor {
callingPid = callingUid = -1;
}
- mMainStack.mConfigWillChange = config != null
+ final ActivityStack stack = getTopStack();
+ stack.mConfigWillChange = config != null
&& mService.mConfiguration.diff(config) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG,
- "Starting activity when config will change = " + mMainStack.mConfigWillChange);
+ "Starting activity when config will change = " + stack.mConfigWillChange);
final long origId = Binder.clearCallingIdentity();
@@ -389,14 +536,14 @@ public class ActivityStackSupervisor {
aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
callingPackage, startFlags, options, componentSpecified, null);
- if (mMainStack.mConfigWillChange) {
+ if (stack.mConfigWillChange) {
// If the caller also wants to switch to a new configuration,
// do so now. This allows a clean switch, as we are waiting
// for the current activity to pause (so we will not destroy
// it), and have not yet started the next activity.
mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
"updateConfiguration()");
- mMainStack.mConfigWillChange = false;
+ stack.mConfigWillChange = false;
if (DEBUG_CONFIGURATION) Slog.v(TAG,
"Updating to new configuration after starting activity.");
mService.updateConfigurationLocked(config, null, false, false);
@@ -407,7 +554,7 @@ public class ActivityStackSupervisor {
if (outResult != null) {
outResult.result = res;
if (res == ActivityManager.START_SUCCESS) {
- mMainStack.mWaitingActivityLaunched.add(outResult);
+ stack.mWaitingActivityLaunched.add(outResult);
do {
try {
mService.wait();
@@ -415,7 +562,7 @@ public class ActivityStackSupervisor {
}
} while (!outResult.timeout && outResult.who == null);
} else if (res == ActivityManager.START_TASK_TO_FRONT) {
- ActivityRecord r = mMainStack.topRunningActivityLocked(null);
+ ActivityRecord r = stack.topRunningActivityLocked(null);
if (r.nowVisible) {
outResult.timeout = false;
outResult.who = new ComponentName(r.info.packageName, r.info.name);
@@ -423,7 +570,7 @@ public class ActivityStackSupervisor {
outResult.thisTime = 0;
} else {
outResult.thisTime = SystemClock.uptimeMillis();
- mMainStack.mWaitingActivityVisible.add(outResult);
+ stack.mWaitingActivityVisible.add(outResult);
do {
try {
mService.wait();
@@ -679,7 +826,7 @@ public class ActivityStackSupervisor {
// launching the initial activity (that is, home), so that it can have
// a chance to initialize itself while in the background, making the
// switch back to it faster and look better.
- if (isMainStack(stack)) {
+ if (isFrontStack(stack)) {
mService.startSetupActivityLocked();
}
@@ -852,16 +999,17 @@ public class ActivityStackSupervisor {
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration,
- resultRecord, resultWho, requestCode, componentSpecified);
+ resultRecord, resultWho, requestCode, componentSpecified, this);
if (outActivity != null) {
outActivity[0] = r;
}
- if (mMainStack.mResumedActivity == null
- || mMainStack.mResumedActivity.info.applicationInfo.uid != callingUid) {
+ final ActivityStack stack = getTopStack();
+ if (stack.mResumedActivity == null
+ || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
PendingActivityLaunch pal =
- new PendingActivityLaunch(r, sourceRecord, startFlags, mMainStack);
+ new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
mService.mPendingActivityLaunches.add(pal);
setDismissKeyguard(false);
ActivityOptions.abort(options);
@@ -883,7 +1031,7 @@ public class ActivityStackSupervisor {
mService.doPendingActivityLaunchesLocked(false);
err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
- if (mMainStack.mPausingActivity == null) {
+ if (stack.mPausingActivity == null) {
// Someone asked to have the keyguard dismissed on the next
// activity start, but we are not actually doing an activity
// switch... just dismiss the keyguard now, because we
@@ -893,6 +1041,19 @@ public class ActivityStackSupervisor {
return err;
}
+ ActivityStack getCorrectStack(ActivityRecord r) {
+ if (!r.isHomeActivity) {
+ if (mStacks.size() == 1) {
+ // Time to create the first app stack.
+ int stackId =
+ mService.createStack(HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);
+ mMainStack = getStack(stackId);
+ }
+ return mMainStack;
+ }
+ return mHomeStack;
+ }
+
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
@@ -901,14 +1062,10 @@ public class ActivityStackSupervisor {
int launchFlags = intent.getFlags();
- final ActivityStack stack = mMainStack;
- ActivityStack targetStack = mMainStack;
-
// We'll invoke onUserLeaving before onPause only if the launching
// activity did not explicitly state that this is an automated launch.
- targetStack.mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
- if (DEBUG_USER_LEAVING) Slog.v(TAG,
- "startActivity() => mUserLeaving=" + targetStack.mUserLeaving);
+ mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
+ if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
// If the caller has asked not to resume at this point, we make note
// of this in the record so that we can skip it when trying to find
@@ -926,7 +1083,7 @@ public class ActivityStackSupervisor {
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
ActivityRecord checkedCaller = sourceRecord;
if (checkedCaller == null) {
- checkedCaller = targetStack.topRunningNonDelayedActivityLocked(notTop);
+ checkedCaller = getTopStack().topRunningNonDelayedActivityLocked(notTop);
}
if (!checkedCaller.realActivity.equals(r.realActivity)) {
// Caller is not the same as launcher, so always needed.
@@ -954,6 +1111,16 @@ public class ActivityStackSupervisor {
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
+ final ActivityStack sourceStack;
+ final TaskRecord sourceTask;
+ if (sourceRecord != null) {
+ sourceTask = sourceRecord.task;
+ sourceStack = sourceTask.stack;
+ } else {
+ sourceTask = null;
+ sourceStack = null;
+ }
+
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
// For whatever reason this activity is being launched into a new
// task... yet the caller has requested a result back. Well, that
@@ -970,6 +1137,7 @@ public class ActivityStackSupervisor {
boolean addingToTask = false;
boolean movedHome = false;
TaskRecord reuseTask = null;
+ ActivityStack targetStack;
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
@@ -987,6 +1155,7 @@ public class ActivityStackSupervisor {
: findActivityLocked(intent, r.info);
if (intentActivity != null) {
targetStack = intentActivity.task.stack;
+ moveHomeStack(targetStack.isHomeStack());
if (intentActivity.task.intent == null) {
// This task was started because of movement of
// the activity based on affinity... now that we
@@ -1000,16 +1169,21 @@ public class ActivityStackSupervisor {
// to have the same behavior as if a new instance was
// being started, which means not bringing it to the front
// if the caller is not itself in the front.
- ActivityRecord curTop = targetStack.topRunningNonDelayedActivityLocked(notTop);
+ ActivityRecord curTop =
+ targetStack.topRunningNonDelayedActivityLocked(notTop);
if (curTop != null && curTop.task != intentActivity.task) {
r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
- boolean callerAtFront = sourceRecord == null
- || curTop.task == sourceRecord.task;
- if (callerAtFront) {
+ if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
// We really do want to push this one into the
// user's face, right now.
movedHome = true;
- targetStack.moveHomeToFrontFromLaunchLocked(launchFlags);
+ if ((launchFlags &
+ (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
+ == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
+ // Caller wants to appear on home activity, so before starting
+ // their own activity we will bring home to the front.
+ r.mLaunchHomeTaskNext = true;
+ }
targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
options = null;
}
@@ -1025,6 +1199,7 @@ public class ActivityStackSupervisor {
// is the case, so this is it! And for paranoia, make
// sure we have correctly resumed the top activity.
if (doResume) {
+ setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
targetStack.resumeTopActivityLocked(null, options);
} else {
ActivityOptions.abort(options);
@@ -1117,7 +1292,8 @@ public class ActivityStackSupervisor {
// don't use that intent!) And for paranoia, make
// sure we have correctly resumed the top activity.
if (doResume) {
- stack.resumeTopActivityLocked(null, options);
+ setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
+ targetStack.resumeTopActivityLocked(null, options);
} else {
ActivityOptions.abort(options);
}
@@ -1137,7 +1313,8 @@ public class ActivityStackSupervisor {
// If the activity being launched is the same as the one currently
// at the top, then we need to check if it should only be launched
// once.
- ActivityRecord top = targetStack.topRunningNonDelayedActivityLocked(notTop);
+ ActivityStack topStack = getTopStack();
+ ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
if (top.app != null && top.app.thread != null) {
@@ -1149,7 +1326,8 @@ public class ActivityStackSupervisor {
// For paranoia, make sure we have correctly
// resumed the top activity.
if (doResume) {
- targetStack.resumeTopActivityLocked(null);
+ setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
+ topStack.resumeTopActivityLocked(null);
}
ActivityOptions.abort(options);
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
@@ -1167,9 +1345,8 @@ public class ActivityStackSupervisor {
} else {
if (r.resultTo != null) {
- r.resultTo.task.stack.sendActivityResultLocked(-1,
- r.resultTo, r.resultWho, r.requestCode,
- Activity.RESULT_CANCELED, null);
+ r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
+ r.requestCode, Activity.RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
return ActivityManager.START_CLASS_NOT_FOUND;
@@ -1181,20 +1358,29 @@ public class ActivityStackSupervisor {
// Should this be considered a new task?
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+ targetStack = getCorrectStack(r);
+ moveHomeStack(targetStack.isHomeStack());
if (reuseTask == null) {
- stack.setTask(r, targetStack.createTaskRecord(getNextTaskId(), r.info, intent,
- true), null, true);
- if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
- + " in new task " + r.task);
+ r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
+ null, true);
+ if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
+ r.task);
} else {
- stack.setTask(r, reuseTask, reuseTask, true);
+ r.setTask(reuseTask, reuseTask, true);
}
newTask = true;
if (!movedHome) {
- stack.moveHomeToFrontFromLaunchLocked(launchFlags);
+ if ((launchFlags &
+ (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
+ == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
+ // Caller wants to appear on home activity, so before starting
+ // their own activity we will bring home to the front.
+ r.mLaunchHomeTaskNext = true;
+ }
}
-
} else if (sourceRecord != null) {
+ targetStack = sourceRecord.task.stack;
+ moveHomeStack(targetStack.isHomeStack());
if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
// In this case, we are adding the activity to an existing
@@ -1208,6 +1394,7 @@ public class ActivityStackSupervisor {
// For paranoia, make sure we have correctly
// resumed the top activity.
if (doResume) {
+ setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
targetStack.resumeTopActivityLocked(null);
}
ActivityOptions.abort(options);
@@ -1221,11 +1408,13 @@ public class ActivityStackSupervisor {
final ActivityRecord top =
targetStack.findActivityInHistoryLocked(r, sourceRecord.task);
if (top != null) {
- targetStack.moveActivityToFrontLocked(top);
- ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
+ final TaskRecord task = top.task;
+ task.moveActivityToFrontLocked(top);
+ ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
top.updateOptionsLocked(options);
top.deliverNewIntentLocked(callingUid, r.intent);
if (doResume) {
+ setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
targetStack.resumeTopActivityLocked(null);
}
return ActivityManager.START_DELIVERED_TO_TOP;
@@ -1234,7 +1423,7 @@ public class ActivityStackSupervisor {
// An existing activity is starting this new activity, so we want
// to keep the new one in the same task as the one that is starting
// it.
- stack.setTask(r, sourceRecord.task, sourceRecord.thumbHolder, false);
+ r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in existing task " + r.task);
@@ -1242,10 +1431,12 @@ public 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.
- ActivityRecord prev = stack.topActivity();
- stack.setTask(r, prev != null
- ? prev.task
- : stack.createTaskRecord(getNextTaskId(), r.info, intent, true), null, true);
+ targetStack = getLastStack();
+ moveHomeStack(targetStack.isHomeStack());
+ ActivityRecord prev = targetStack.topActivity();
+ r.setTask(prev != null ? prev.task
+ : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
+ null, true);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in new guessed " + r.task);
}
@@ -1257,6 +1448,7 @@ public class ActivityStackSupervisor {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
}
ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
+ setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
return ActivityManager.START_SUCCESS;
}
@@ -1407,11 +1599,14 @@ public class ActivityStackSupervisor {
}
void comeOutOfSleepIfNeededLocked() {
+ final boolean homeIsBack = !homeIsInFront();
final int numStacks = mStacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
- stack.awakeFromSleepingLocked();
- stack.resumeTopActivityLocked(null);
+ if (stack.isHomeStack() ^ homeIsBack) {
+ stack.awakeFromSleepingLocked();
+ stack.resumeTopActivityLocked(null);
+ }
}
}
@@ -1423,28 +1618,10 @@ public class ActivityStackSupervisor {
}
}
- boolean updateConfigurationLocked(int changes, ActivityRecord starting) {
- boolean kept = true;
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (changes != 0 && starting == null) {
- // If the configuration changed, and the caller is not already
- // in the process of starting an activity, then find the top
- // activity to check if its configuration needs to change.
- starting = stack.topRunningActivityLocked(null);
- }
-
- if (starting != null) {
- if (!stack.ensureActivityConfigurationLocked(starting, changes)) {
- kept = false;
- }
- // And we need to make sure at this point that all other activities
- // are made visible with the correct configuration.
- stack.ensureActivitiesVisibleLocked(starting, changes);
- }
+ void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ mStacks.get(stackNdx).ensureActivitiesVisibleLocked(starting, configChanges);
}
- return kept;
}
void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
@@ -1457,22 +1634,65 @@ public class ActivityStackSupervisor {
boolean switchUserLocked(int userId, UserStartedState uss) {
mCurrentUser = userId;
+ boolean homeInBack = !homeIsInFront();
boolean haveActivities = false;
final int numStacks = mStacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
- haveActivities |= stack.switchUserLocked(userId, uss);
+ if (stack.isHomeStack() ^ homeInBack) {
+ haveActivities |= stack.switchUserLocked(userId, uss);
+ }
}
return haveActivities;
}
+ final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
+ int N = mStoppingActivities.size();
+ if (N <= 0) return null;
+
+ ArrayList<ActivityRecord> stops = null;
+
+ final boolean nowVisible = allResumedActivitiesVisible();
+ for (int i=0; i<N; i++) {
+ ActivityRecord s = mStoppingActivities.get(i);
+ if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
+ + nowVisible + " waitingVisible=" + s.waitingVisible
+ + " finishing=" + s.finishing);
+ if (s.waitingVisible && nowVisible) {
+ mWaitingVisibleActivities.remove(s);
+ s.waitingVisible = false;
+ if (s.finishing) {
+ // If this activity is finishing, it is sitting on top of
+ // everyone else but we now know it is no longer needed...
+ // so get rid of it. Otherwise, we need to go through the
+ // normal flow and hide it once we determine that it is
+ // hidden by the activities in front of it.
+ if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
+ mService.mWindowManager.setAppVisibility(s.appToken, false);
+ }
+ }
+ if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
+ if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
+ if (stops == null) {
+ stops = new ArrayList<ActivityRecord>();
+ }
+ stops.add(s);
+ mStoppingActivities.remove(i);
+ N--;
+ i--;
+ }
+ }
+
+ return stops;
+ }
+
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
pw.println(mDismissKeyguardOnNextActivity);
}
ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
- return mMainStack.getDumpActivitiesLocked(name);
+ return getTopStack().getDumpActivitiesLocked(name);
}
boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
@@ -1486,18 +1706,6 @@ public class ActivityStackSupervisor {
pw.println(" Running activities (most recent first):");
dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
dumpPackage);
- if (stack.mWaitingVisibleActivities.size() > 0) {
- pw.println(" ");
- pw.println(" Activities waiting for another to become visible:");
- dumpHistoryList(fd, pw, stack.mWaitingVisibleActivities, " ", "Wait", false,
- !dumpAll, false, dumpPackage);
- }
- if (stack.mStoppingActivities.size() > 0) {
- pw.println(" ");
- pw.println(" Activities waiting to stop:");
- dumpHistoryList(fd, pw, stack.mStoppingActivities, " ", "Stop", false,
- !dumpAll, false, dumpPackage);
- }
if (stack.mGoingToSleepActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting to sleep:");
@@ -1510,10 +1718,7 @@ public class ActivityStackSupervisor {
dumpHistoryList(fd, pw, stack.mFinishingActivities, " ", "Fin", false,
!dumpAll, false, dumpPackage);
}
- }
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
if (stack.mPausingActivity != null) {
pw.println(" mPausingActivity: " + stack.mPausingActivity);
@@ -1525,6 +1730,20 @@ public class ActivityStackSupervisor {
}
}
+ if (mStoppingActivities.size() > 0) {
+ pw.println(" ");
+ pw.println(" Activities waiting to stop:");
+ dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
+ dumpPackage);
+ }
+
+ if (mWaitingVisibleActivities.size() > 0) {
+ pw.println(" ");
+ pw.println(" Activities waiting for another to become visible:");
+ dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
+ false, dumpPackage);
+ }
+
if (dumpAll) {
pw.println(" ");
pw.println(" mCurTaskId: " + mCurTaskId);
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index 8638140..64b9572 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -165,7 +165,7 @@ public class CompatModePackages {
}
public boolean getFrontActivityAskCompatModeLocked() {
- ActivityRecord r = mService.getMainStack().topRunningActivityLocked(null);
+ ActivityRecord r = mService.getTopStack().topRunningActivityLocked(null);
if (r == null) {
return false;
}
@@ -177,7 +177,7 @@ public class CompatModePackages {
}
public void setFrontActivityAskCompatModeLocked(boolean ask) {
- ActivityRecord r = mService.getMainStack().topRunningActivityLocked(null);
+ ActivityRecord r = mService.getTopStack().topRunningActivityLocked(null);
if (r != null) {
setPackageAskCompatModeLocked(r.packageName, ask);
}
@@ -199,7 +199,7 @@ public class CompatModePackages {
}
public int getFrontActivityScreenCompatModeLocked() {
- ActivityRecord r = mService.getMainStack().topRunningActivityLocked(null);
+ ActivityRecord r = mService.getTopStack().topRunningActivityLocked(null);
if (r == null) {
return ActivityManager.COMPAT_MODE_UNKNOWN;
}
@@ -207,7 +207,7 @@ public class CompatModePackages {
}
public void setFrontActivityScreenCompatModeLocked(int mode) {
- ActivityRecord r = mService.getMainStack().topRunningActivityLocked(null);
+ ActivityRecord r = mService.getTopStack().topRunningActivityLocked(null);
if (r == null) {
Slog.w(TAG, "setFrontActivityScreenCompatMode failed: no top activity");
return;
@@ -294,7 +294,7 @@ public class CompatModePackages {
Message msg = mHandler.obtainMessage(MSG_WRITE);
mHandler.sendMessageDelayed(msg, 10000);
- final ActivityStack stack = mService.getMainStack();
+ final ActivityStack stack = mService.getTopStack();
ActivityRecord starting = stack.restartPackage(packageName);
// Tell all processes that loaded this package about the change.
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index 94da7e5..45bd6d5 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -16,6 +16,9 @@
package com.android.server.am;
+import static com.android.server.am.ActivityManagerService.TAG;
+import static com.android.server.am.ActivityStack.DEBUG_ADD_REMOVE;
+
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.ComponentName;
@@ -128,6 +131,20 @@ class TaskRecord extends ThumbnailHolder {
return null;
}
+ /**
+ * Reorder the history stack so that the activity at the given index is
+ * brought to the front.
+ */
+ final void moveActivityToFrontLocked(ActivityRecord newTop) {
+ if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + newTop
+ + " to stack at top", new RuntimeException("here").fillInStackTrace());
+
+ getTopActivity().frontOfTask = false;
+ mActivities.remove(newTop);
+ mActivities.add(newTop);
+ newTop.frontOfTask = true;
+ }
+
void addActivityAtBottom(ActivityRecord r) {
addActivityAtIndex(0, r);
}
@@ -289,10 +306,16 @@ class TaskRecord extends ThumbnailHolder {
@Override
public String toString() {
+ StringBuilder sb = new StringBuilder(128);
if (stringName != null) {
- return stringName;
+ sb.append(stringName);
+ sb.append(" U=");
+ sb.append(userId);
+ sb.append(" sz=");
+ sb.append(mActivities.size());
+ sb.append('}');
+ return sb.toString();
}
- StringBuilder sb = new StringBuilder(128);
sb.append("TaskRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" #");
@@ -309,11 +332,7 @@ class TaskRecord extends ThumbnailHolder {
} else {
sb.append(" ??");
}
- sb.append(" U=");
- sb.append(userId);
- sb.append(" sz=");
- sb.append(mActivities.size());
- sb.append('}');
- return stringName = sb.toString();
+ stringName = sb.toString();
+ return toString();
}
}
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 75df1ec..5b2cf50 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -17,8 +17,11 @@
package com.android.server.wm;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
+import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerService.TAG;
import android.graphics.Rect;
+import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
@@ -36,7 +39,6 @@ class DisplayContentList extends ArrayList<DisplayContent> {
* WindowManagerService.mWindowMap.
*/
class DisplayContent {
-// private final static String TAG = "DisplayContent";
/** Unique identifier of this stack. */
private final int mDisplayId;
@@ -86,7 +88,7 @@ class DisplayContent {
private ArrayList<StackBox> mStackBoxes = new ArrayList<StackBox>();
/** True when the home StackBox is at the top of mStackBoxes, false otherwise */
- private boolean mHomeOnTop = true;
+ private TaskStack mHomeStack = null;
/**
* Sorted most recent at top, oldest at [0].
@@ -120,7 +122,7 @@ class DisplayContent {
}
boolean homeOnTop() {
- return mHomeOnTop;
+ return mStackBoxes.get(0).mStack != mHomeStack;
}
/**
@@ -138,7 +140,7 @@ class DisplayContent {
}
TaskStack getHomeStack() {
- return mStackBoxes.get(mHomeOnTop ? mStackBoxes.size() - 1 : 0).mStack;
+ return mHomeStack;
}
public void updateDisplayInfo() {
@@ -158,12 +160,19 @@ class DisplayContent {
/** Refer to {@link WindowManagerService#createStack(int, int, int, float)} */
TaskStack createStack(int stackId, int relativeStackId, int position, float weight) {
TaskStack newStack = null;
+ if (DEBUG_STACK) Slog.d(TAG, "createStack: stackId=" + stackId + " relativeStackId="
+ + relativeStackId + " position=" + position + " weight=" + weight);
if (mStackBoxes.isEmpty()) {
+ if (stackId != HOME_STACK_ID) {
+ throw new IllegalArgumentException("createStack: First stackId not "
+ + HOME_STACK_ID);
+ }
StackBox newBox = new StackBox(this, new Rect(0, 0, mDisplayInfo.logicalWidth,
mDisplayInfo.logicalHeight));
mStackBoxes.add(newBox);
newStack = new TaskStack(stackId, newBox);
newBox.mStack = newStack;
+ mHomeStack = newStack;
} else {
int stackBoxNdx;
for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
@@ -172,10 +181,12 @@ class DisplayContent {
|| position == StackBox.TASK_STACK_GOES_UNDER) {
// Position indicates a new box is added at top level only.
if (box.contains(relativeStackId)) {
- final int offset = position == StackBox.TASK_STACK_GOES_OVER ? 1 : 0;
StackBox newBox = new StackBox(this, box.mBounds);
newStack = new TaskStack(stackId, newBox);
newBox.mStack = newStack;
+ final int offset = position == StackBox.TASK_STACK_GOES_OVER ? 1 : 0;
+ if (DEBUG_STACK) Slog.d(TAG, "createStack: inserting stack at " +
+ (stackBoxNdx + offset));
mStackBoxes.add(stackBoxNdx + offset, newBox);
break;
}
@@ -208,9 +219,11 @@ class DisplayContent {
}
void removeStackBox(StackBox box) {
+ if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: box=" + box);
final TaskStack stack = box.mStack;
if (stack != null && stack.mStackId == HOME_STACK_ID) {
// Never delete the home stack, even if it is empty.
+ if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: Not deleting home stack.");
return;
}
mStackBoxes.remove(box);
@@ -223,14 +236,13 @@ class DisplayContent {
* @return true if a change was made, false otherwise.
*/
boolean moveHomeStackBox(boolean toTop) {
+ if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop);
switch (mStackBoxes.size()) {
case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!");
case 1: return false; // Only the home StackBox exists.
- case 2:
- if (mHomeOnTop != toTop) {
- final StackBox home = mStackBoxes.remove(toTop ? 0 : 1);
- mStackBoxes.add(toTop ? 1 : 0, home);
- mHomeOnTop = toTop;
+ case 2:
+ if (homeOnTop() ^ toTop) {
+ mStackBoxes.add(mStackBoxes.remove(0));
return true;
}
return false;
@@ -262,47 +274,47 @@ class DisplayContent {
pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
- for (int boxNdx = 0; boxNdx < mStackBoxes.size(); ++boxNdx) {
- pw.print(prefix); pw.print("StackBox #"); pw.println(boxNdx);
- mStackBoxes.get(boxNdx).dump(prefix + " ", pw);
- }
- int ndx = numTokens();
- if (ndx > 0) {
- pw.println();
- pw.println(" Application tokens in Z order:");
- getTasks();
- for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
- AppTokenList tokens = mTmpTasks.get(taskNdx).mAppTokens;
- for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
- final AppWindowToken wtoken = tokens.get(tokenNdx);
- pw.print(" App #"); pw.print(ndx--);
- pw.print(' '); pw.print(wtoken); pw.println(":");
- wtoken.dump(pw, " ");
- }
+ for (int boxNdx = 0; boxNdx < mStackBoxes.size(); ++boxNdx) {
+ pw.print(prefix); pw.print("StackBox #"); pw.println(boxNdx);
+ mStackBoxes.get(boxNdx).dump(prefix + " ", pw);
+ }
+ int ndx = numTokens();
+ if (ndx > 0) {
+ pw.println();
+ pw.println(" Application tokens in Z order:");
+ getTasks();
+ for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
+ AppTokenList tokens = mTmpTasks.get(taskNdx).mAppTokens;
+ for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+ final AppWindowToken wtoken = tokens.get(tokenNdx);
+ pw.print(" App #"); pw.print(ndx--);
+ pw.print(' '); pw.print(wtoken); pw.println(":");
+ wtoken.dump(pw, " ");
}
}
- if (mExitingTokens.size() > 0) {
- pw.println();
- pw.println(" Exiting tokens:");
- for (int i=mExitingTokens.size()-1; i>=0; i--) {
- WindowToken token = mExitingTokens.get(i);
- pw.print(" Exiting #"); pw.print(i);
- pw.print(' '); pw.print(token);
- pw.println(':');
- token.dump(pw, " ");
- }
+ }
+ if (mExitingTokens.size() > 0) {
+ pw.println();
+ pw.println(" Exiting tokens:");
+ for (int i=mExitingTokens.size()-1; i>=0; i--) {
+ WindowToken token = mExitingTokens.get(i);
+ pw.print(" Exiting #"); pw.print(i);
+ pw.print(' '); pw.print(token);
+ pw.println(':');
+ token.dump(pw, " ");
}
- if (mExitingAppTokens.size() > 0) {
- pw.println();
- pw.println(" Exiting application tokens:");
- for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
- WindowToken token = mExitingAppTokens.get(i);
- pw.print(" Exiting App #"); pw.print(i);
- pw.print(' '); pw.print(token);
- pw.println(':');
- token.dump(pw, " ");
- }
+ }
+ if (mExitingAppTokens.size() > 0) {
+ pw.println();
+ pw.println(" Exiting application tokens:");
+ for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
+ WindowToken token = mExitingAppTokens.get(i);
+ pw.print(" Exiting App #"); pw.print(i);
+ pw.print(' '); pw.print(token);
+ pw.println(':');
+ token.dump(pw, " ");
}
+ }
pw.println();
}
}
diff --git a/services/java/com/android/server/wm/StackBox.java b/services/java/com/android/server/wm/StackBox.java
index 31d1d52..9525d7c 100644
--- a/services/java/com/android/server/wm/StackBox.java
+++ b/services/java/com/android/server/wm/StackBox.java
@@ -212,7 +212,7 @@ public class StackBox {
mParent.absorb(mParent.mFirst);
}
mParent.makeDirty();
- return getStackId();
+ return mParent.getStackId();
}
/** TODO: */
@@ -222,19 +222,26 @@ public class StackBox {
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mParent="); pw.println(mParent);
- pw.print(prefix); pw.print("mFirst="); pw.println(mFirst);
- pw.print(prefix); pw.print("mSecond="); pw.println(mSecond);
pw.print(prefix); pw.print("mBounds="); pw.print(mBounds.toShortString());
pw.print(" mVertical="); pw.print(mVertical);
pw.print(" layoutNeeded="); pw.println(layoutNeeded);
- if (mStack != null) {
- pw.print(prefix); pw.print("mStack="); pw.println(mStack);
- mStack.dump(prefix + " ", pw);
- } else {
+ if (mFirst != null) {
pw.print(prefix); pw.print("mFirst="); pw.println(mStack);
mFirst.dump(prefix + " ", pw);
pw.print(prefix); pw.print("mSecond="); pw.println(mStack);
mSecond.dump(prefix + " ", pw);
+ } else {
+ pw.print(prefix); pw.print("mStack="); pw.println(mStack);
+ mStack.dump(prefix + " ", pw);
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (mStack != null) {
+ return "Box{" + hashCode() + " stack=" + mStack.mStackId + "}";
}
+ return "Box{" + hashCode() + " parent=" + mParent.hashCode()
+ + " first=" + mFirst.hashCode() + " second=" + mSecond.hashCode() + "}";
}
}
diff --git a/services/java/com/android/server/wm/Task.java b/services/java/com/android/server/wm/Task.java
index 81245c6..2520f31 100644
--- a/services/java/com/android/server/wm/Task.java
+++ b/services/java/com/android/server/wm/Task.java
@@ -47,6 +47,6 @@ class Task {
@Override
public String toString() {
- return "id=" + taskId + " appTokens=" + mAppTokens;
+ return "taskId=" + taskId + " appTokens=" + mAppTokens;
}
}
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java
index 683744a..3e5a933 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/java/com/android/server/wm/TaskStack.java
@@ -85,17 +85,10 @@ public class TaskStack {
* Delete a Task from this stack. If it is the last Task in the stack, remove this stack from
* its parent StackBox and merge the parent.
* @param task The Task to delete.
- * @return True if #task was in this stack.
*/
- boolean removeTask(Task task) {
+ void removeTask(Task task) {
mParent.makeDirty();
- if (mTasks.remove(task)) {
- if (mTasks.size() == 0) {
- mParent.removeStack();
- }
- return true;
- }
- return false;
+ mTasks.remove(task);
}
int remove() {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 8b43537..ad49d0a 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -181,6 +181,7 @@ public class WindowManagerService extends IWindowManager.Stub
static final boolean DEBUG_SURFACE_TRACE = false;
static final boolean DEBUG_WINDOW_TRACE = false;
static final boolean DEBUG_TASK_MOVEMENT = false;
+ static final boolean DEBUG_STACK = false;
static final boolean SHOW_SURFACE_ALLOC = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
@@ -2318,9 +2319,9 @@ public class WindowManagerService extends IWindowManager.Stub
if (localLOGV || DEBUG_FOCUS) Slog.v(
TAG, "Remove " + win + " client="
- + Integer.toHexString(System.identityHashCode(
- win.mClient.asBinder()))
- + ", surface=" + win.mWinAnimator.mSurfaceControl);
+ + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
+ + ", surface=" + win.mWinAnimator.mSurfaceControl,
+ new RuntimeException("here").fillInStackTrace());
final long origId = Binder.clearCallingIdentity();
@@ -7676,8 +7677,7 @@ public class WindowManagerService extends IWindowManager.Stub
win.mRebuilding = true;
mRebuildTmp[numRemoved] = win;
mWindowsChanged = true;
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
- "Rebuild removing window: " + win);
+ if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
NW--;
numRemoved++;
continue;