From ae7ecab400374f083718995454ec03e5e57b7203 Mon Sep 17 00:00:00 2001 From: Craig Mautner Date: Wed, 18 Sep 2013 11:48:14 -0700 Subject: [PATCH] Move flag for home launching from activity to task. The variable ActivityRecord.mLaunchHomeTaskNext was used to indicate that the home task should be launched when the activity completed. This only mattered when it was at the end of a task. As the activity launched other activities within the same task it needed to be migrated from activity to activity and task to task. This became too complicated and was at the wrong level to begin with. By moving the flag to TaskRecord.mOnTopOfHome the logic is simpler and the results more predictable. Fixes bug 10602256. Change-Id: If0b752522b77be9918f1dba221d0ff670fc01af8 --- .../com/android/server/am/ActivityRecord.java | 14 +++- .../com/android/server/am/ActivityStack.java | 66 ++++++++----------- .../server/am/ActivityStackSupervisor.java | 10 +-- .../com/android/server/am/TaskRecord.java | 8 ++- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 6e50808ae1225..43598954d32c8 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -143,9 +143,6 @@ final class ActivityRecord { 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(); pw.print(prefix); pw.print("packageName="); pw.print(packageName); @@ -243,6 +240,8 @@ final class ActivityRecord { pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy); pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded); pw.print(" forceNewConfig="); pw.println(forceNewConfig); + pw.print(prefix); pw.print("mActivityType="); + pw.println(activityTypeToString(mActivityType)); pw.print(prefix); pw.print("thumbHolder: "); pw.print(Integer.toHexString(System.identityHashCode(thumbHolder))); if (thumbHolder != null) { @@ -1040,6 +1039,15 @@ final class ActivityRecord { return null; } + private String activityTypeToString(int type) { + switch (type) { + case APPLICATION_ACTIVITY_TYPE: return "APPLICATION_ACTIVITY_TYPE"; + case HOME_ACTIVITY_TYPE: return "HOME_ACTIVITY_TYPE"; + case RECENTS_ACTIVITY_TYPE: return "RECENTS_ACTIVITY_TYPE"; + default: return Integer.toString(type); + } + } + @Override public String toString() { if (stringName != null) { diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 1f64101f8445c..c31c213c02a4f 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -1000,7 +1000,8 @@ final class ActivityStack { boolean behindFullscreen = !mStackSupervisor.isFrontStack(this) && !(forceHomeShown && isHomeStack()); for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { - final ArrayList activities = mTaskHistory.get(taskNdx).mActivities; + final TaskRecord task = mTaskHistory.get(taskNdx); + final ArrayList activities = task.mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.finishing) { @@ -1083,7 +1084,7 @@ final class ActivityStack { // At this point, nothing else needs to be shown if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r); behindFullscreen = true; - } else if (r.mLaunchHomeTaskNext) { + } else if (task.mOnTopOfHome) { if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r); showHomeBehindStack = true; behindFullscreen = true; @@ -1224,7 +1225,7 @@ final class ActivityStack { final TaskRecord nextTask = next.task; final TaskRecord prevTask = prev != null ? prev.task : null; - if (prevTask != null && prev.mLaunchHomeTaskNext && prev.finishing && prev.frontOfTask) { + if (prevTask != null && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) { if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); if (prevTask == nextTask) { ArrayList activities = prevTask.mActivities; @@ -1234,7 +1235,6 @@ final class ActivityStack { // r is usually the same as next, but what if two activities were launched // before prev finished? if (!r.finishing) { - r.mLaunchHomeTaskNext = true; r.frontOfTask = true; break; } @@ -1243,7 +1243,7 @@ final class ActivityStack { // This task is going away but it was supposed to return to the home task. // Now the task above it has to return to the home task instead. final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; - mTaskHistory.get(taskNdx).mActivities.get(0).mLaunchHomeTaskNext = true; + mTaskHistory.get(taskNdx).mOnTopOfHome = true; } else { if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Launching home next"); return mStackSupervisor.resumeHomeActivity(prev); @@ -2933,7 +2933,7 @@ final class ActivityStack { if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) { // Caller wants the home activity moved with it. To accomplish this, // we'll just indicate that this task returns to the home task. - task.mActivities.get(0).mLaunchHomeTaskNext = true; + task.mOnTopOfHome = true; } moveTaskToFrontLocked(task, null, options); return true; @@ -2994,17 +2994,17 @@ final class ActivityStack { * If a watcher is installed, the action is preflighted and the watcher has an opportunity * to premeptively cancel the move. * - * @param task The taskId to collect and move to the bottom. + * @param taskId The taskId to collect and move to the bottom. * @return Returns true if the move completed, false if not. */ - final boolean moveTaskToBackLocked(int task, ActivityRecord reason) { - Slog.i(TAG, "moveTaskToBack: " + task); + final boolean moveTaskToBackLocked(int taskId, ActivityRecord reason) { + Slog.i(TAG, "moveTaskToBack: " + taskId); // 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.isFrontStack(this) && mService.mController != null) { - ActivityRecord next = topRunningActivityLocked(null, task); + ActivityRecord next = topRunningActivityLocked(null, taskId); if (next == null) { next = topRunningActivityLocked(null, 0); } @@ -3024,9 +3024,9 @@ final class ActivityStack { } if (DEBUG_TRANSITION) Slog.v(TAG, - "Prepare to back transition: task=" + task); + "Prepare to back transition: task=" + taskId); - final TaskRecord tr = taskForIdLocked(task); + final TaskRecord tr = taskForIdLocked(taskId); if (tr == null) { return false; } @@ -3038,28 +3038,15 @@ final class ActivityStack { // We make sure here that some activity in the stack will launch home. ActivityRecord lastActivity = null; int numTasks = mTaskHistory.size(); - int taskNdx; - for (taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) { - final ArrayList activities = mTaskHistory.get(taskNdx).mActivities; - int activityNdx; - for (activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { - final ActivityRecord r = activities.get(activityNdx); - if (r.mLaunchHomeTaskNext) { - break; - } - if (taskNdx == 1 && activityNdx == 0) { - // Final activity before tr task. - lastActivity = r; - } - } - if (activityNdx >= 0) { - // Early exit, we found an activity that will launchHomeTaskNext. + for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) { + final TaskRecord task = mTaskHistory.get(taskNdx); + if (task.mOnTopOfHome) { break; } - } - if (lastActivity != null) { - // No early exit, we did not find an activity that will launchHomeTaskNext, set one. - lastActivity.mLaunchHomeTaskNext = true; + if (taskNdx == 1) { + // Set the last task before tr to go to home. + task.mOnTopOfHome = true; + } } if (reason != null && @@ -3072,15 +3059,15 @@ final class ActivityStack { } else { mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false); } - mWindowManager.moveTaskToBottom(task); + mWindowManager.moveTaskToBottom(taskId); if (VALIDATE_TOKENS) { validateAppTokensLocked(); } - if (numTasks <= 1 || (mResumedActivity != null && mResumedActivity.task == tr && - mResumedActivity.mLaunchHomeTaskNext)) { - mResumedActivity.mLaunchHomeTaskNext = false; + final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null; + if (task == tr && task.mOnTopOfHome || numTasks <= 1) { + task.mOnTopOfHome = false; return mStackSupervisor.resumeHomeActivity(null); } @@ -3427,7 +3414,7 @@ final class ActivityStack { } final ActivityRecord top = topRunningActivityLocked(null); final boolean launchHomeTaskNext = - top != null && top.app == app && top.mLaunchHomeTaskNext; + top != null && top.app == app && top.task.mOnTopOfHome; // Remove this application's activities from active lists. boolean hasVisibleActivities = removeHistoryRecordsForAppLocked(app); @@ -3534,6 +3521,11 @@ final class ActivityStack { } boolean removeTask(TaskRecord task) { + final int taskNdx = mTaskHistory.indexOf(task); + final int topTaskNdx = mTaskHistory.size() - 1; + if (task.mOnTopOfHome && taskNdx < topTaskNdx) { + mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true; + } mTaskHistory.remove(task); return mTaskHistory.isEmpty(); } diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java index 7756ff9ad6850..8ad29f3dfa103 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/java/com/android/server/am/ActivityStackSupervisor.java @@ -282,7 +282,7 @@ public final class ActivityStackSupervisor { boolean resumeHomeActivity(ActivityRecord prev) { moveHomeStack(true); if (prev != null) { - prev.mLaunchHomeTaskNext = false; + prev.task.mOnTopOfHome = false; } mHomeStack.moveHomeTaskToTop(); ActivityRecord r = mHomeStack.topRunningActivityLocked(null); @@ -304,7 +304,7 @@ public final class ActivityStackSupervisor { r = stack.topRunningActivityLocked(null); } if (r != null && !r.isHomeActivity() && r.isRootActivity()) { - r.mLaunchHomeTaskNext = true; + r.task.mOnTopOfHome = true; } } } @@ -1429,7 +1429,7 @@ public final class ActivityStackSupervisor { (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity. - r.mLaunchHomeTaskNext = true; + intentActivity.task.mOnTopOfHome = true; } targetStack.moveTaskToFrontLocked(intentActivity.task, r, options); options = null; @@ -1543,7 +1543,7 @@ public final class ActivityStackSupervisor { // sure we have correctly resumed the top activity. if (doResume) { // Reset flag so it gets correctly reevaluated. - intentActivity.mLaunchHomeTaskNext = false; + intentActivity.task.mOnTopOfHome = false; setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack); targetStack.resumeTopActivityLocked(null, options); } else { @@ -1640,7 +1640,7 @@ public final class ActivityStackSupervisor { == (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; + r.task.mOnTopOfHome = true; } } } else if (sourceRecord != null) { diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java index 479665c973d3e..f0bba4f99726c 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/java/com/android/server/am/TaskRecord.java @@ -60,6 +60,9 @@ final class TaskRecord extends ThumbnailHolder { /** Takes on same set of values as ActivityRecord.mActivityType */ private int mTaskType; + /** Launch the home activity when leaving this task. */ + boolean mOnTopOfHome = false; + TaskRecord(int _taskId, ActivityInfo info, Intent _intent) { taskId = _taskId; affinity = info.taskAffinity; @@ -411,11 +414,12 @@ final class TaskRecord extends ThumbnailHolder { } void dump(PrintWriter pw, String prefix) { - if (numActivities != 0 || rootWasReset || userId != 0) { + if (numActivities != 0 || rootWasReset || userId != 0 || numFullscreen != 0) { pw.print(prefix); pw.print("numActivities="); pw.print(numActivities); pw.print(" rootWasReset="); pw.print(rootWasReset); pw.print(" userId="); pw.print(userId); - pw.print(" numFullscreen="); pw.println(numFullscreen); + pw.print(" numFullscreen="); pw.print(numFullscreen); + pw.print(" mOnTopOfHome="); pw.println(mOnTopOfHome); } if (affinity != null) { pw.print(prefix); pw.print("affinity="); pw.println(affinity);