diff options
| author | 2013-05-07 14:01:50 -0700 | |
|---|---|---|
| committer | 2013-05-07 15:01:46 -0700 | |
| commit | 525f3d9df632e485d1f75d8336e28a266eb7d96c (patch) | |
| tree | cae3e2ffeb089df25c815189ae85161aaca099d0 | |
| parent | 2ae118d1077bcec1c407b6ecb9acf14e2152fe93 (diff) | |
Do not launch home task if activities remain
When a root activity is finishing and it is supposed to return to
home make sure there are only lower activities waiting to start before
going home.
Fixes bug 8632206.
Various other refactorings for efficiency.
Change-Id: I8bbb9de78d0ea9f45a504cf4bad72c698e9cc3d8
4 files changed, 85 insertions, 90 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 2040491e0146..fad1bc57b51a 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -4467,7 +4467,8 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { ActivityStack stack = ActivityRecord.getStackLocked(token); if (stack != null) { - ActivityRecord r = stack.activityIdleInternalLocked(token, false, config); + ActivityRecord r = + mStackSupervisor.activityIdleInternalLocked(token, false, config); if (stopProfiling) { if ((mProfileProc == r.app) && (mProfileFd != null)) { try { diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index ba14b3baafb7..e39ea4ac3041 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -971,28 +971,28 @@ final class ActivityStack { if (prev != null) { prev.resumeKeyDispatchingLocked(); - } - if (prev.app != null && prev.cpuTimeAtResume > 0 - && mService.mBatteryStatsService.isOnBattery()) { - long diff = 0; - synchronized (mService.mProcessStatsThread) { - diff = mService.mProcessStats.getCpuTimeForPid(prev.app.pid) - - prev.cpuTimeAtResume; - } - if (diff > 0) { - BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics(); - synchronized (bsi) { - BatteryStatsImpl.Uid.Proc ps = - bsi.getProcessStatsLocked(prev.info.applicationInfo.uid, - prev.info.packageName); - if (ps != null) { - ps.addForegroundTimeLocked(diff); + if (prev.app != null && prev.cpuTimeAtResume > 0 + && mService.mBatteryStatsService.isOnBattery()) { + long diff; + synchronized (mService.mProcessStatsThread) { + diff = mService.mProcessStats.getCpuTimeForPid(prev.app.pid) + - prev.cpuTimeAtResume; + } + if (diff > 0) { + BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics(); + synchronized (bsi) { + BatteryStatsImpl.Uid.Proc ps = + bsi.getProcessStatsLocked(prev.info.applicationInfo.uid, + prev.info.packageName); + if (ps != null) { + ps.addForegroundTimeLocked(diff); + } } } } + prev.cpuTimeAtResume = 0; // reset it } - prev.cpuTimeAtResume = 0; // reset it } /** @@ -1000,7 +1000,7 @@ final class ActivityStack { * the resumed state (either by launching it or explicitly telling it), * this function updates the rest of our state to match that fact. */ - private final void completeResumeLocked(ActivityRecord next) { + private void completeResumeLocked(ActivityRecord next) { next.idle = false; next.results = null; next.newIntents = null; @@ -1035,10 +1035,8 @@ final class ActivityStack { final boolean ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean forceHomeShown) { ActivityRecord r = topRunningActivityLocked(null); - if (r != null) { - return ensureActivitiesVisibleLocked(r, starting, null, configChanges, forceHomeShown); - } - return false; + return r != null && + ensureActivitiesVisibleLocked(r, starting, null, configChanges, forceHomeShown); } /** @@ -1220,13 +1218,27 @@ final class ActivityStack { return false; } - if (prev != null && prev.mLaunchHomeTaskNext && prev.finishing && prev.frontOfTask) { + final TaskRecord nextTask = next.task; + final TaskRecord prevTask = prev != null ? prev.task : null; + if (prevTask != null && prev.mLaunchHomeTaskNext && prev.finishing && prev.frontOfTask) { if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); - final TaskRecord task = prev.task; - if (topTask() != task) { + if (prevTask == nextTask) { + ArrayList<ActivityRecord> activities = prevTask.mActivities; + final int numActivities = activities.size(); + for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { + final ActivityRecord r = activities.get(activityNdx); + // 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; + } + } + } else if (prevTask != topTask()) { // 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(task) + 1; + final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; mTaskHistory.get(taskNdx).mActivities.get(0).mLaunchHomeTaskNext = true; } else { return mStackSupervisor.resumeHomeActivity(prev); @@ -1386,13 +1398,13 @@ final class ActivityStack { // We are starting up the next activity, so tell the window manager // that the previous one will be hidden soon. This way it can know // to ignore it when computing the desired screen orientation. - boolean noAnim = false; + boolean anim = true; if (prev != null) { if (prev.finishing) { if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare close transition: prev=" + prev); if (mNoAnimActivities.contains(prev)) { - noAnim = true; + anim = false; mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); } else { mWindowManager.prepareAppTransition(prev.task == next.task @@ -1404,7 +1416,7 @@ final class ActivityStack { } else { if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev); if (mNoAnimActivities.contains(next)) { - noAnim = true; + anim = false; mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); } else { mWindowManager.prepareAppTransition(prev.task == next.task @@ -1419,13 +1431,13 @@ final class ActivityStack { } else { if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous"); if (mNoAnimActivities.contains(next)) { - noAnim = true; + anim = false; mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); } else { mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false); } } - if (!noAnim) { + if (anim) { next.applyOptionsLocked(); } else { next.clearOptionsLocked(); @@ -1457,7 +1469,7 @@ final class ActivityStack { // Have the window manager re-evaluate the orientation of // the screen based on the new activity order. - boolean updated = false; + boolean notUpdated = true; if (mStackSupervisor.isFrontStack(this)) { Configuration config = mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, @@ -1465,10 +1477,10 @@ final class ActivityStack { if (config != null) { next.frozenBeforeDestroy = true; } - updated = mService.updateConfigurationLocked(config, next, false, false); + notUpdated = !mService.updateConfigurationLocked(config, next, false, false); } - if (!updated) { + if (notUpdated) { // The configuration update wasn't able to keep the existing // instance of the activity, and instead started a new one. // We should be all done, but let's just make sure our activity @@ -1586,7 +1598,6 @@ final class ActivityStack { final void startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition, Bundle options) { - TaskRecord task = null; TaskRecord rTask = r.task; final int taskId = rTask.taskId; if (taskForIdLocked(taskId) == null || newTask) { @@ -1598,6 +1609,7 @@ final class ActivityStack { mTaskHistory.add(rTask); mWindowManager.moveTaskToTop(taskId); } + TaskRecord task = null; if (!newTask) { // If starting in an existing task, find where that is... boolean startIt = true; @@ -1830,9 +1842,7 @@ final class ActivityStack { final int targetTaskId = targetTask.taskId; mWindowManager.setAppGroupId(target.appToken, targetTaskId); - ThumbnailHolder curThumbHolder = target.thumbHolder; - boolean gotOptions = !canMoveOptions; - + boolean noOptions = canMoveOptions; final int start = replyChainEnd < 0 ? i : replyChainEnd; for (int srcPos = start; srcPos >= i; --srcPos) { p = activities.get(srcPos); @@ -1840,12 +1850,12 @@ final class ActivityStack { continue; } - curThumbHolder = p.thumbHolder; + ThumbnailHolder curThumbHolder = p.thumbHolder; canMoveOptions = false; - if (!gotOptions && topOptions == null) { + if (noOptions && topOptions == null) { topOptions = p.takeOptionsLocked(); if (topOptions != null) { - gotOptions = true; + noOptions = false; } } if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing activity " + p + " from task=" @@ -1881,18 +1891,17 @@ final class ActivityStack { } else { end = replyChainEnd; } - ActivityRecord p = null; - boolean gotOptions = !canMoveOptions; + boolean noOptions = canMoveOptions; for (int srcPos = i; srcPos <= end; srcPos++) { - p = activities.get(srcPos); + ActivityRecord p = activities.get(srcPos); if (p.finishing) { continue; } canMoveOptions = false; - if (!gotOptions && topOptions == null) { + if (noOptions && topOptions == null) { topOptions = p.takeOptionsLocked(); if (topOptions != null) { - gotOptions = true; + noOptions = false; } } if (DEBUG_TASKS) Slog.w(TAG, @@ -1922,7 +1931,7 @@ final class ActivityStack { * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked. * @param forceReset Flag passed in to resetTaskIfNeededLocked. */ - private final int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task, + private int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task, boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) { int replyChainEnd = -1; final int taskId = task.taskId; @@ -2004,7 +2013,6 @@ final class ActivityStack { // below so it remains singleTop. if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) { ArrayList<ActivityRecord> taskActivities = task.mActivities; - boolean found = false; int targetNdx = taskActivities.indexOf(target); if (targetNdx > 0) { ActivityRecord p = taskActivities.get(targetNdx - 1); @@ -2075,25 +2083,6 @@ final class ActivityStack { return taskTop; } - /** - * Find the activity in the history stack within the given task. Returns - * the index within the history at which it's found, or < 0 if not found. - */ - final ActivityRecord findActivityInHistoryLocked(ActivityRecord r, TaskRecord task) { - final ComponentName realActivity = r.realActivity; - ArrayList<ActivityRecord> activities = task.mActivities; - for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { - ActivityRecord candidate = activities.get(activityNdx); - if (candidate.finishing) { - continue; - } - if (candidate.realActivity.equals(realActivity)) { - return candidate; - } - } - return null; - } - void sendActivityResultLocked(int callingUid, ActivityRecord r, String resultWho, int requestCode, int resultCode, Intent data) { @@ -2178,24 +2167,11 @@ final class ActivityStack { } } - final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, - Configuration config) { + final ActivityRecord activityIdleInternalLocked(final IBinder token) { if (localLOGV) Slog.v(TAG, "Activity idle: " + token); - ActivityRecord res = null; - - ArrayList<ActivityRecord> stops = null; - ArrayList<ActivityRecord> finishes = null; - ArrayList<UserStartedState> startingUsers = null; - int NS = 0; - int NF = 0; - IApplicationThread sendThumbnail = null; - boolean booting = false; - boolean enableScreen = false; - boolean activityRemoved = false; - // Get the activity record. - res = isInStackLocked(token); + ActivityRecord res = isInStackLocked(token); if (res != null) { // No longer need to keep the device awake. if (mResumedActivity == res && mLaunchingActivity.isHeld()) { diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java index 69e9f7623875..f7f081200bcd 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/java/com/android/server/am/ActivityStackSupervisor.java @@ -1254,7 +1254,7 @@ public class ActivityStackSupervisor { } final ActivityStack sourceStack; - final TaskRecord sourceTask; + TaskRecord sourceTask; if (sourceRecord != null) { sourceTask = sourceRecord.task; sourceStack = sourceTask.stack; @@ -1540,14 +1540,15 @@ public class ActivityStackSupervisor { } } } else if (sourceRecord != null) { - targetStack = sourceRecord.task.stack; + sourceTask = sourceRecord.task; + targetStack = sourceTask.stack; moveHomeStack(targetStack.isHomeStack()); if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { // In this case, we are adding the activity to an existing // task, but the caller has asked to clear that task if the // activity is already running. - ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags); + ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags); keepCurTransition = true; if (top != null) { ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); @@ -1569,8 +1570,7 @@ public class ActivityStackSupervisor { // In this case, we are launching an activity in our own task // that may already be running somewhere in the history, and // we want to shuffle it to the front of the stack if so. - final ActivityRecord top = - targetStack.findActivityInHistoryLocked(r, sourceRecord.task); + final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r); if (top != null) { final TaskRecord task = top.task; task.moveActivityToFrontLocked(top); @@ -1590,7 +1590,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. - r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false); + r.setTask(sourceTask, sourceRecord.thumbHolder, false); if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in existing task " + r.task); @@ -1644,7 +1644,7 @@ public class ActivityStackSupervisor { Debug.getCallers(4)); mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); r.finishLaunchTickingLocked(); - res = r.task.stack.activityIdleInternalLocked(token, fromTimeout, config); + res = r.task.stack.activityIdleInternalLocked(token); if (res != null) { if (fromTimeout) { reportActivityLaunchedLocked(fromTimeout, r, -1, -1); diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java index dda82ecd7e93..a01b882b6dc7 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/java/com/android/server/am/TaskRecord.java @@ -383,6 +383,24 @@ class TaskRecord extends ThumbnailHolder { return thumbs; } + /** + * Find the activity in the history stack within the given task. Returns + * the index within the history at which it's found, or < 0 if not found. + */ + final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) { + final ComponentName realActivity = r.realActivity; + for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) { + ActivityRecord candidate = mActivities.get(activityNdx); + if (candidate.finishing) { + continue; + } + if (candidate.realActivity.equals(realActivity)) { + return candidate; + } + } + return null; + } + void dump(PrintWriter pw, String prefix) { if (numActivities != 0 || rootWasReset || userId != 0) { pw.print(prefix); pw.print("numActivities="); pw.print(numActivities); |