From ee36c77acd3b92c64e53e19c570e2482382db870 Mon Sep 17 00:00:00 2001 From: Craig Mautner Date: Wed, 16 Jul 2014 14:56:05 -0700 Subject: [PATCH] Additional cleanup after stack deletion. - Remove activity from PendingActivityLaunch list when it is removed from stack. This prevents the delayed launch causing IllegalArgumentException in b/16045752. - Move PendingActivityLaunch from ActivityManagerService to ActivityStackSupervisor. - Immediately call onTaskListEmptyLocked() in cases where no activities are found in stack. Fixes bug 16045752. Change-Id: Ia69a449e7f5e08ab6e36157d0fd793c4d2fdaca4 --- .../server/am/ActivityManagerService.java | 38 +------------- .../com/android/server/am/ActivityStack.java | 12 +++-- .../server/am/ActivityStackSupervisor.java | 52 ++++++++++++++++--- 3 files changed, 57 insertions(+), 45 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index b68089c76d858..a6deed54eab34 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -340,28 +340,6 @@ public final class ActivityManagerService extends ActivityManagerNative // devices. private boolean mShowDialogs = true; - /** - * Description of a request to start a new activity, which has been held - * due to app switches being disabled. - */ - static class PendingActivityLaunch { - final ActivityRecord r; - final ActivityRecord sourceRecord; - final int startFlags; - final ActivityStack stack; - - PendingActivityLaunch(ActivityRecord _r, ActivityRecord _sourceRecord, - int _startFlags, ActivityStack _stack) { - r = _r; - sourceRecord = _sourceRecord; - startFlags = _startFlags; - stack = _stack; - } - } - - final ArrayList mPendingActivityLaunches - = new ArrayList(); - BroadcastQueue mFgBroadcastQueue; BroadcastQueue mBgBroadcastQueue; // Convenient for easy iteration over the queues. Foreground is first @@ -1323,7 +1301,7 @@ public final class ActivityManagerService extends ActivityManagerNative } break; case DO_PENDING_ACTIVITY_LAUNCHES_MSG: { synchronized (ActivityManagerService.this) { - doPendingActivityLaunchesLocked(true); + mStackSupervisor.doPendingActivityLaunchesLocked(true); } } break; case KILL_APPLICATION_MSG: { @@ -3034,19 +3012,6 @@ public final class ActivityManagerService extends ActivityManagerNative mProcessObservers.finishBroadcast(); } - final void doPendingActivityLaunchesLocked(boolean doResume) { - final int N = mPendingActivityLaunches.size(); - if (N <= 0) { - return; - } - for (int i=0; i= 0; --taskNdx) { final ArrayList activities = mTaskHistory.get(taskNdx).mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); - if (r.finishing) { + noActivitiesInStack = false; + if (r.finishing && !immediately) { continue; } - Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r); + Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r + " immediately"); finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false); } } + if (noActivitiesInStack) { + mActivityContainer.onTaskListEmptyLocked(); + } } final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode, @@ -2683,6 +2688,7 @@ final class ActivityStack { // down to the max limit while they are still waiting to finish. mStackSupervisor.mFinishingActivities.remove(r); mStackSupervisor.mWaitingVisibleActivities.remove(r); + mStackSupervisor.removePendingActivityLaunchesLocked(r); // Remove any pending results. if (r.finishing && r.pendingResults != null) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index bca215dde51af..cdcccccb3c332 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -88,7 +88,6 @@ import android.view.Surface; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.os.TransferPipe; import com.android.server.LocalServices; -import com.android.server.am.ActivityManagerService.PendingActivityLaunch; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.wm.WindowManagerService; @@ -234,6 +233,28 @@ public final class ActivityStackSupervisor implements DisplayListener { InputManagerInternal mInputManagerInternal; + final ArrayList mPendingActivityLaunches + = new ArrayList(); + + /** + * Description of a request to start a new activity, which has been held + * due to app switches being disabled. + */ + static class PendingActivityLaunch { + final ActivityRecord r; + final ActivityRecord sourceRecord; + final int startFlags; + final ActivityStack stack; + + PendingActivityLaunch(ActivityRecord _r, ActivityRecord _sourceRecord, + int _startFlags, ActivityStack _stack) { + r = _r; + sourceRecord = _sourceRecord; + startFlags = _startFlags; + stack = _stack; + } + } + public ActivityStackSupervisor(ActivityManagerService service) { mService = service; PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE); @@ -1304,7 +1325,7 @@ public final class ActivityStackSupervisor implements DisplayListener { if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) { PendingActivityLaunch pal = new PendingActivityLaunch(r, sourceRecord, startFlags, stack); - mService.mPendingActivityLaunches.add(pal); + mPendingActivityLaunches.add(pal); setDismissKeyguard(false); ActivityOptions.abort(options); return ActivityManager.START_SWITCHES_CANCELED; @@ -1322,7 +1343,7 @@ public final class ActivityStackSupervisor implements DisplayListener { mService.mDidAppSwitch = true; } - mService.doPendingActivityLaunchesLocked(false); + doPendingActivityLaunchesLocked(false); err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options); @@ -1830,6 +1851,23 @@ public final class ActivityStackSupervisor implements DisplayListener { return ActivityManager.START_SUCCESS; } + final void doPendingActivityLaunchesLocked(boolean doResume) { + while (!mPendingActivityLaunches.isEmpty()) { + PendingActivityLaunch pal = mPendingActivityLaunches.remove(0); + startActivityUncheckedLocked(pal.r, pal.sourceRecord, pal.startFlags, + doResume && mPendingActivityLaunches.isEmpty(), null); + } + } + + void removePendingActivityLaunchesLocked(ActivityRecord r) { + for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) { + PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx); + if (pal.r == r) { + mPendingActivityLaunches.remove(palNdx); + } + } + } + void acquireLaunchWakelock() { if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) { throw new IllegalStateException("Calling must be system uid"); @@ -2960,7 +2998,9 @@ public final class ActivityStackSupervisor implements DisplayListener { synchronized (mService) { Slog.w(TAG, "Timeout waiting for all activities in task to finish. " + msg.obj); - ((ActivityContainer) msg.obj).onTaskListEmptyLocked(); + final ActivityContainer container = (ActivityContainer) msg.obj; + container.mStack.finishAllActivitiesLocked(true); + container.onTaskListEmptyLocked(); } } break; } @@ -3054,11 +3094,11 @@ public final class ActivityStackSupervisor implements DisplayListener { final Message msg = mHandler.obtainMessage(CONTAINER_TASK_LIST_EMPTY_TIMEOUT, this); - mHandler.sendMessageDelayed(msg, 1000); + mHandler.sendMessageDelayed(msg, 2000); long origId = Binder.clearCallingIdentity(); try { - mStack.finishAllActivitiesLocked(); + mStack.finishAllActivitiesLocked(false); } finally { Binder.restoreCallingIdentity(origId); }