diff options
author | Dianne Hackborn <hackbod@google.com> | 2012-02-16 18:01:31 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-02-16 18:01:31 -0800 |
commit | b9ee4f4425612037139dba70d0a7d9a089eeb3d2 (patch) | |
tree | 6c1c96abf2dd35c04fc3ddcc914661173d13ca24 | |
parent | 30e2fbe0d2565952928feaf9d3d9194340113af4 (diff) | |
parent | 621e2fecb559d5afa5e43d58e8a7ee2d71c74430 (diff) | |
download | frameworks_base-b9ee4f4425612037139dba70d0a7d9a089eeb3d2.zip frameworks_base-b9ee4f4425612037139dba70d0a7d9a089eeb3d2.tar.gz frameworks_base-b9ee4f4425612037139dba70d0a7d9a089eeb3d2.tar.bz2 |
Merge "Revert "Don't wait for current activity to pause before resuming next.""
3 files changed, 88 insertions, 139 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 7852123..8a5e7fc 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -138,7 +138,6 @@ import java.io.StringWriter; import java.lang.IllegalStateException; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -2752,7 +2751,13 @@ public final class ActivityManagerService extends ActivityManagerNative } // Just in case... - mMainStack.appDiedLocked(app); + if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) { + if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity); + mMainStack.mPausingActivity = null; + } + if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) { + mMainStack.mLastPausedActivity = null; + } // Remove this application's activities from active lists. mMainStack.removeHistoryRecordsForAppLocked(app); @@ -6488,7 +6493,7 @@ public final class ActivityManagerService extends ActivityManagerNative mMainStack.stopIfSleepingLocked(); final long endTime = System.currentTimeMillis() + timeout; while (mMainStack.mResumedActivity != null - || mMainStack.mPausingActivities.size() > 0) { + || mMainStack.mPausingActivity != null) { long delay = endTime - System.currentTimeMillis(); if (delay <= 0) { Slog.w(TAG, "Activity manager shutdown timed out"); @@ -8295,13 +8300,8 @@ public final class ActivityManagerService extends ActivityManagerNative } pw.println(" "); - if (mMainStack.mPausingActivities.size() > 0) { - pw.println(" mPausingActivities: " + Arrays.toString( - mMainStack.mPausingActivities.toArray())); - } - if (mMainStack.mInputPausedActivities.size() > 0) { - pw.println(" mInputPausedActivities: " + Arrays.toString( - mMainStack.mInputPausedActivities.toArray())); + if (mMainStack.mPausingActivity != null) { + pw.println(" mPausingActivity: " + mMainStack.mPausingActivity); } pw.println(" mResumedActivity: " + mMainStack.mResumedActivity); pw.println(" mFocusedActivity: " + mFocusedActivity); @@ -13876,13 +13876,7 @@ public final class ActivityManagerService extends ActivityManagerNative private final ActivityRecord resumedAppLocked() { ActivityRecord resumedActivity = mMainStack.mResumedActivity; if (resumedActivity == null || resumedActivity.app == null) { - for (int i=mMainStack.mPausingActivities.size()-1; i>=0; i--) { - ActivityRecord r = mMainStack.mPausingActivities.get(i); - if (r.app != null) { - resumedActivity = r; - break; - } - } + resumedActivity = mMainStack.mPausingActivity; if (resumedActivity == null || resumedActivity.app == null) { resumedActivity = mMainStack.topRunningActivityLocked(null); } diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 977ee84..cdab6c6 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -602,7 +602,6 @@ final class ActivityRecord { public void windowsDrawn() { synchronized(service) { - stack.reportActivityDrawnLocked(this); if (launchTime != 0) { final long curTime = SystemClock.uptimeMillis(); final long thisTime = curTime - launchTime; @@ -691,9 +690,7 @@ final class ActivityRecord { // Hmmm, who might we be waiting for? r = stack.mResumedActivity; if (r == null) { - if (stack.mPausingActivities.size() > 0) { - r = stack.mPausingActivities.get(stack.mPausingActivities.size()-1); - } + r = stack.mPausingActivity; } // Both of those null? Fall back to 'this' again if (r == null) { diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index e8c8275..7b8bc26 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -227,13 +227,7 @@ final class ActivityStack { * When we are in the process of pausing an activity, before starting the * next one, this variable holds the activity that is currently being paused. */ - final ArrayList<ActivityRecord> mPausingActivities = new ArrayList<ActivityRecord>(); - - /** - * These activities currently have their input paused, as they want for - * the next top activity to have its windows visible. - */ - final ArrayList<ActivityRecord> mInputPausedActivities = new ArrayList<ActivityRecord>(); + ActivityRecord mPausingActivity = null; /** * This is the last activity that we put into the paused state. This is @@ -813,9 +807,9 @@ final class ActivityStack { startPausingLocked(false, true); return; } - if (mPausingActivities.size() > 0) { + if (mPausingActivity != null) { // Still waiting for something to pause; can't sleep yet. - if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivities); + if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity); return; } @@ -878,6 +872,11 @@ final class ActivityStack { } private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) { + if (mPausingActivity != null) { + RuntimeException e = new RuntimeException(); + Slog.e(TAG, "Trying to pause when pause is already pending for " + + mPausingActivity, e); + } ActivityRecord prev = mResumedActivity; if (prev == null) { RuntimeException e = new RuntimeException(); @@ -885,25 +884,19 @@ final class ActivityStack { resumeTopActivityLocked(null); return; } - if (mPausingActivities.contains(prev)) { - RuntimeException e = new RuntimeException(); - Slog.e(TAG, "Trying to pause when pause when already pausing " + prev, e); - } if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev); else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev); mResumedActivity = null; - mPausingActivities.add(prev); + mPausingActivity = prev; mLastPausedActivity = prev; prev.state = ActivityState.PAUSING; prev.task.touchActiveTime(); prev.updateThumbnail(screenshotActivities(prev), null); mService.updateCpuStats(); - ActivityRecord pausing; if (prev.app != null && prev.app.thread != null) { if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev); - pausing = prev; try { EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY, System.identityHashCode(prev), @@ -916,14 +909,12 @@ final class ActivityStack { } catch (Exception e) { // Ignore exception, if process died other code will cleanup. Slog.w(TAG, "Exception thrown during pause", e); - mPausingActivities.remove(prev); + mPausingActivity = null; mLastPausedActivity = null; - pausing = null; } } else { - mPausingActivities.remove(prev); + mPausingActivity = null; mLastPausedActivity = null; - pausing = null; } // If we are not going to sleep, we want to ensure the device is @@ -937,28 +928,18 @@ final class ActivityStack { } } - if (pausing != null) { + + if (mPausingActivity != null) { // Have the window manager pause its key dispatching until the new // activity has started. If we're pausing the activity just because // the screen is being turned off and the UI is sleeping, don't interrupt // key dispatch; the same activity will pick it up again on wakeup. if (!uiSleeping) { - pausing.pauseKeyDispatchingLocked(); - mInputPausedActivities.add(prev); + prev.pauseKeyDispatchingLocked(); } else { if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off"); } - if (pausing.configDestroy) { - // The previous is being paused because the configuration - // is changing, which means it is actually stopping... - // To juggle the fact that we are also starting a new - // instance right now, we need to first completely stop - // the current instance before starting the new one. - if (DEBUG_PAUSE) Slog.v(TAG, "Destroying at pause: " + prev); - destroyActivityLocked(pausing, true, false, "pause-config"); - } - // Schedule a pause timeout in case the app doesn't respond. // We don't give it much time because this directly impacts the // responsiveness seen by the user. @@ -970,10 +951,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."); - } - - if (!mService.isSleeping()) { - resumeTopActivityLocked(pausing); + resumeTopActivityLocked(null); } } @@ -988,17 +966,16 @@ final class ActivityStack { if (index >= 0) { r = mHistory.get(index); mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); - if (mPausingActivities.contains(r)) { + if (mPausingActivity == r) { if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r + (timeout ? " (due to timeout)" : " (pause complete)")); r.state = ActivityState.PAUSED; - completePauseLocked(r); + completePauseLocked(); } else { - ActivityRecord old = mPausingActivities.size() > 0 - ? mPausingActivities.get(0) : null; EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE, System.identityHashCode(r), r.shortComponentName, - old != null ? old.shortComponentName : "(none)"); + mPausingActivity != null + ? mPausingActivity.shortComponentName : "(none)"); } } } @@ -1024,14 +1001,8 @@ final class ActivityStack { ProcessRecord fgApp = null; if (mResumedActivity != null) { fgApp = mResumedActivity.app; - } else { - for (int i=mPausingActivities.size()-1; i>=0; i--) { - ActivityRecord pausing = mPausingActivities.get(i); - if (pausing.app == r.app) { - fgApp = pausing.app; - break; - } - } + } else if (mPausingActivity != null) { + fgApp = mPausingActivity.app; } if (r.app != null && fgApp != null && r.app != fgApp && r.lastVisibleTime > mService.mPreviousProcessVisibleTime @@ -1043,49 +1014,58 @@ final class ActivityStack { } } - private final void completePauseLocked(ActivityRecord prev) { + private final void completePauseLocked() { + ActivityRecord prev = mPausingActivity; if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev); - if (prev.finishing) { - if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev); - prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE); - } else if (prev.app != null) { - if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev); - if (prev.waitingVisible) { - prev.waitingVisible = false; - mWaitingVisibleActivities.remove(prev); - if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v( - TAG, "Complete pause, no longer waiting: " + prev); - } - if (prev.configDestroy) { - // The previous is being paused because the configuration - // is changing, which means it is actually stopping... - // To juggle the fact that we are also starting a new - // instance right now, we need to first completely stop - // the current instance before starting the new one. - if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev); - destroyActivityLocked(prev, true, false, "pause-config"); - } else { - mStoppingActivities.add(prev); - if (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. - if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle"); - scheduleIdleLocked(); + if (prev != null) { + if (prev.finishing) { + if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev); + prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE); + } else if (prev.app != null) { + if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev); + if (prev.waitingVisible) { + prev.waitingVisible = false; + mWaitingVisibleActivities.remove(prev); + if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v( + TAG, "Complete pause, no longer waiting: " + prev); + } + if (prev.configDestroy) { + // The previous is being paused because the configuration + // is changing, which means it is actually stopping... + // To juggle the fact that we are also starting a new + // instance right now, we need to first completely stop + // the current instance before starting the new one. + if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev); + destroyActivityLocked(prev, true, false, "pause-config"); } else { - checkReadyForSleepLocked(); + mStoppingActivities.add(prev); + if (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. + if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle"); + scheduleIdleLocked(); + } else { + checkReadyForSleepLocked(); + } } + } else { + if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev); + prev = null; } - } else { - if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev); - prev = null; + mPausingActivity = null; } - mPausingActivities.remove(prev); - if (mService.isSleeping()) { + if (!mService.isSleeping()) { + resumeTopActivityLocked(prev); + } else { checkReadyForSleepLocked(); } + + if (prev != null) { + prev.resumeKeyDispatchingLocked(); + } if (prev.app != null && prev.cpuTimeAtResume > 0 && mService.mBatteryStatsService.isOnBattery()) { @@ -1142,9 +1122,7 @@ final class ActivityStack { if (mMainStack) { mService.setFocusedActivityLocked(next); } - if (mInputPausedActivities.remove(next)) { - next.resumeKeyDispatchingLocked(); - } + next.resumeKeyDispatchingLocked(); ensureActivitiesVisibleLocked(null, 0); mService.mWindowManager.executeAppTransition(); mNoAnimActivities.clear(); @@ -1374,6 +1352,13 @@ final class ActivityStack { if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next); + // If we are currently pausing an activity, then don't do anything + // until that is done. + if (mPausingActivity != null) { + if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity); + return false; + } + // Okay we are now going to start a switch, to 'next'. We may first // have to pause the current activity, but this is an important point // where we have decided to go to 'next' so keep track of that. @@ -2455,7 +2440,7 @@ final class ActivityStack { err = startActivityUncheckedLocked(r, sourceRecord, grantedUriPermissions, grantedMode, onlyIfNeeded, true); - if (mDismissKeyguardOnNextActivity && mPausingActivities.size() == 0) { + if (mDismissKeyguardOnNextActivity && 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 @@ -3126,18 +3111,7 @@ final class ActivityStack { } mService.notifyAll(); } - - void reportActivityDrawnLocked(ActivityRecord r) { - if (mResumedActivity == r) { - // Once the resumed activity has been drawn, we can stop - // pausing input on all other activities. - for (int i=mInputPausedActivities.size()-1; i>=0; i--) { - mInputPausedActivities.get(i).resumeKeyDispatchingLocked(); - } - mInputPausedActivities.clear(); - } - } - + void reportActivityVisibleLocked(ActivityRecord r) { for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) { WaitResult w = mWaitingActivityVisible.get(i); @@ -3196,9 +3170,7 @@ final class ActivityStack { mService.setFocusedActivityLocked(topRunningActivityLocked(null)); } } - if (mInputPausedActivities.remove(r)) { - r.resumeKeyDispatchingLocked(); - } + r.resumeKeyDispatchingLocked(); try { r.stopped = false; if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r @@ -3524,7 +3496,7 @@ final class ActivityStack { // Tell window manager to prepare for this one to be removed. mService.mWindowManager.setAppVisibility(r.appToken, false); - if (!mPausingActivities.contains(r)) { + if (mPausingActivity == null) { if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r); if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false"); startPausingLocked(false, false); @@ -3608,20 +3580,6 @@ final class ActivityStack { return r; } - final void appDiedLocked(ProcessRecord app) { - for (int i=mPausingActivities.size()-1; i>=0; i--) { - ActivityRecord r = mPausingActivities.get(i); - if (r.app == app) { - if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + r); - mPausingActivities.remove(i); - mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); - } - } - if (mLastPausedActivity != null && mLastPausedActivity.app == app) { - mLastPausedActivity = null; - } - } - /** * Perform the common clean-up of an activity record. This is called both * as part of destroyActivityLocked() (when destroying the client-side |