diff options
author | Dianne Hackborn <hackbod@google.com> | 2011-10-18 13:17:33 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2011-10-18 13:41:10 -0700 |
commit | 98cfebc6e871937e296fc1c6b89e07cdc8d5ba28 (patch) | |
tree | 40fc7beaa94d0f646a0d126fc37ae14e2c7d6be3 /services | |
parent | 07848843b23e10e4728fa779cc79fc38a341cf6b (diff) | |
download | frameworks_base-98cfebc6e871937e296fc1c6b89e07cdc8d5ba28.zip frameworks_base-98cfebc6e871937e296fc1c6b89e07cdc8d5ba28.tar.gz frameworks_base-98cfebc6e871937e296fc1c6b89e07cdc8d5ba28.tar.bz2 |
Fix issue #5461497: Landed on Welcome screen after a tap on 'Next' in Screen 500
The basic problem was that at some points during setup wizard, this would
happen:
1. The app's process is killed.
2. The app's process is restarted, but not to actually resume the
setup wizard activity, just to put it in the stopped state.
When doing this, the saved state is cleared but the app will
never provide a new one.
3. The app's process is killed again. At this point, because the
saved state is cleared, the activity is completely removed.
4. Eventually the entire activity stack becomes empty, and a new
setup wizard activity needs to be created as the home app.
There is a combination of bad stuff going on here.
First, why is the process being killed? At this point the setup
wizard is the home app, so it shouldn't be killed. There were two
reasons why this was happening:
- CryptKeeper still was not completely cleanly going away. To fix
this, I removed the check in the activity manager to not allow
an activity to finish if it is the only activity on the stack and
maybe-kindof looks like the home app. This really wasn't necessary
(we always take care of starting a new home activity if we find the
stack is empty), and outright dangerous with all of these things
purporting to be home but not.
- There was an issue in computing the oom_adj where the home app
would not be marked as "not hidden", and if we had to re-compute
its oom adj in the current sequence would then give it an
adjustment as a background process... and with all the processes
we spin through during boot, it quickly got down to background
#16 and killed.
Second, what is going on with the state? This is easier, the code
in the activity manager to create a new activity but put it in the
stopped state was still clearing the saved state. The saved state
should only be cleared when going in to the resumed state. When
going in to the stopped state, we can just keep holding the same
saved state.
Change-Id: I7d21cdcfa082d98ca70c79d9923e29605ee4353e
Diffstat (limited to 'services')
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 48 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityStack.java | 82 |
2 files changed, 90 insertions, 40 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 55fb371..0d6f405 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -165,7 +165,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final boolean DEBUG_URI_PERMISSION = localLOGV || false; static final boolean DEBUG_USER_LEAVING = localLOGV || false; static final boolean DEBUG_RESULTS = localLOGV || false; - static final boolean DEBUG_BACKUP = localLOGV || true; + static final boolean DEBUG_BACKUP = localLOGV || false; static final boolean DEBUG_CONFIGURATION = localLOGV || false; static final boolean DEBUG_POWER = localLOGV || false; static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false; @@ -2607,9 +2607,18 @@ public final class ActivityManagerService extends ActivityManagerNative TAG, "Record #" + i + " " + r + ": app=" + r.app); if (r.app == app) { if ((!r.haveState && !r.stateNotNeeded) || r.finishing) { - if (localLOGV) Slog.v( - TAG, "Removing this entry! frozen=" + r.haveState - + " finishing=" + r.finishing); + if (ActivityStack.DEBUG_ADD_REMOVE) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Removing activity " + r + " from stack at " + i + + ": haveState=" + r.haveState + + " stateNotNeeded=" + r.stateNotNeeded + + " finishing=" + r.finishing + + " state=" + r.state, here); + } + if (!r.finishing) { + Slog.w(TAG, "Force removing " + r + ": app died, no saved state"); + } r.makeFinishing(); mMainStack.mHistory.remove(i); r.takeFromHistory(); @@ -2630,6 +2639,8 @@ public final class ActivityManagerService extends ActivityManagerNative r.app = null; r.nowVisible = false; if (!r.haveState) { + if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG, + "App died, clearing saved state of " + r); r.icicle = null; } } @@ -4479,7 +4490,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } if (pi == null) { - Slog.w(TAG, "No content provider found for: " + name); + Slog.w(TAG, "No content provider found for permission check: " + uri.toSafeString()); return -1; } @@ -4735,7 +4746,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } if (pi == null) { - Slog.w(TAG, "No content provider found for: " + authority); + Slog.w(TAG, "No content provider found for permission revoke: " + uri.toSafeString()); return; } @@ -4829,7 +4840,8 @@ public final class ActivityManagerService extends ActivityManagerNative } } if (pi == null) { - Slog.w(TAG, "No content provider found for: " + authority); + Slog.w(TAG, "No content provider found for permission revoke: " + + uri.toSafeString()); return; } @@ -13054,11 +13066,13 @@ public final class ActivityManagerService extends ActivityManagerNative if (app.foregroundServices) { // The user is aware of this app, so make it visible. adj = ProcessList.PERCEPTIBLE_APP_ADJ; + app.hidden = false; app.adjType = "foreground-service"; schedGroup = Process.THREAD_GROUP_DEFAULT; } else if (app.forcingToForeground != null) { // The user is aware of this app, so make it visible. adj = ProcessList.PERCEPTIBLE_APP_ADJ; + app.hidden = false; app.adjType = "force-foreground"; app.adjSource = app.forcingToForeground; schedGroup = Process.THREAD_GROUP_DEFAULT; @@ -13069,6 +13083,7 @@ public final class ActivityManagerService extends ActivityManagerNative // We don't want to kill the current heavy-weight process. adj = ProcessList.HEAVY_WEIGHT_APP_ADJ; schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; + app.hidden = false; app.adjType = "heavy"; } @@ -13077,11 +13092,13 @@ public final class ActivityManagerService extends ActivityManagerNative // home app, so we don't want to let it go into the background. adj = ProcessList.HOME_APP_ADJ; schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; + app.hidden = false; app.adjType = "home"; } - - //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj); - + + if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj + + " reason=" + app.adjType); + // By default, we use the computed adjustment. It may be changed if // there are applications dependent on our services or providers, but // this gives us a baseline and makes sure we don't get into an @@ -13108,7 +13125,7 @@ public final class ActivityManagerService extends ActivityManagerNative while (jt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) { ServiceRecord s = jt.next(); if (s.startRequested) { - if (app.hasShownUi) { + if (app.hasShownUi && app != mHomeProcess) { // If this process has shown some UI, let it immediately // go to the LRU list because it may be pretty heavy with // UI stuff. We'll tag it with a label just to help @@ -13169,7 +13186,7 @@ public final class ActivityManagerService extends ActivityManagerNative if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) { // Not doing bind OOM management, so treat // this guy more like a started service. - if (app.hasShownUi) { + if (app.hasShownUi && app != mHomeProcess) { // If this process has shown some UI, let it immediately // go to the LRU list because it may be pretty heavy with // UI stuff. We'll tag it with a label just to help @@ -13177,6 +13194,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (adj > clientAdj) { adjType = "bound-bg-ui-services"; } + app.hidden = false; clientAdj = adj; } else { if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) { @@ -13200,7 +13218,8 @@ public final class ActivityManagerService extends ActivityManagerNative // about letting this process get into the LRU // list to be killed and restarted if needed for // memory. - if (app.hasShownUi && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) { + if (app.hasShownUi && app != mHomeProcess + && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) { adjType = "bound-bg-ui-services"; } else { if ((cr.flags&(Context.BIND_ABOVE_CLIENT @@ -13294,7 +13313,8 @@ public final class ActivityManagerService extends ActivityManagerNative int clientAdj = computeOomAdjLocked( client, myHiddenAdj, TOP_APP, true); if (adj > clientAdj) { - if (app.hasShownUi && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) { + if (app.hasShownUi && app != mHomeProcess + && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) { app.adjType = "bg-ui-provider"; } else { adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 1aed7fe..28c3bae 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -87,6 +87,8 @@ final class ActivityStack { static final boolean DEBUG_TASKS = ActivityManagerService.DEBUG_TASKS; static final boolean DEBUG_STATES = false; + static final boolean DEBUG_ADD_REMOVE = false; + static final boolean DEBUG_SAVED_STATE = false; static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS; @@ -653,6 +655,9 @@ final class ActivityStack { } completeResumeLocked(r); checkReadyForSleepLocked(); + if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle); + r.icicle = null; + r.haveState = false; } else { // This activity is not starting in the resumed state... which // should look like we asked it to pause+stop (but remain visible), @@ -664,9 +669,6 @@ final class ActivityStack { r.stopped = true; } - r.icicle = null; - r.haveState = false; - // Launch the new version setup screen if needed. We do this -after- // launching the initial activity (that is, home), so that it can have // a chance to initialize itself while in the background, making the @@ -936,6 +938,7 @@ final class ActivityStack { final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail, CharSequence description) { + if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle); r.icicle = icicle; r.haveState = true; r.updateThumbnail(thumbnail, description); @@ -1544,6 +1547,7 @@ final class ActivityStack { } // Didn't need to use the icicle, and it is now out of date. + if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; didn't need icicle of: " + next); next.icicle = null; next.haveState = false; next.stopped = false; @@ -1590,6 +1594,12 @@ final class ActivityStack { // get started when the user navigates back to it. addPos = i+1; if (!startIt) { + if (DEBUG_ADD_REMOVE) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, + here); + } mHistory.add(addPos, r); r.putInHistory(); mService.mWindowManager.addAppToken(addPos, r, r.task.taskId, @@ -1622,6 +1632,11 @@ final class ActivityStack { } // Slot the activity into the history stack and proceed + if (DEBUG_ADD_REMOVE) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here); + } mHistory.add(addPos, r); r.putInHistory(); r.frontOfTask = newTask; @@ -1818,6 +1833,12 @@ final class ActivityStack { + " out to target's task " + target.task); p.setTask(target.task, curThumbHolder, false); curThumbHolder = p.thumbHolder; + if (DEBUG_ADD_REMOVE) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Removing and adding activity " + p + " to stack at " + + dstPos, here); + } mHistory.remove(srcPos); mHistory.add(dstPos, p); mService.mWindowManager.moveAppToken(dstPos, p); @@ -1945,6 +1966,12 @@ final class ActivityStack { } else { lastReparentPos--; } + if (DEBUG_ADD_REMOVE) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Removing and adding activity " + p + " to stack at " + + lastReparentPos, here); + } mHistory.remove(srcPos); p.setTask(task, null, false); mHistory.add(lastReparentPos, p); @@ -2143,6 +2170,12 @@ final class ActivityStack { ActivityRecord newTop = mHistory.remove(where); int top = mHistory.size(); ActivityRecord oldTop = mHistory.get(top-1); + if (DEBUG_ADD_REMOVE) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Removing and adding activity " + newTop + " to stack at " + + top, here); + } mHistory.add(top, newTop); oldTop.frontOfTask = false; newTop.frontOfTask = true; @@ -2183,7 +2216,7 @@ final class ActivityStack { if (resultTo != null) { int index = indexOfTokenLocked(resultTo); if (DEBUG_RESULTS) Slog.v( - TAG, "Sending result to " + resultTo + " (index " + index + ")"); + TAG, "Will send result to " + resultTo + " (index " + index + ")"); if (index >= 0) { sourceRecord = mHistory.get(index); if (requestCode >= 0 && !sourceRecord.finishing) { @@ -3279,34 +3312,15 @@ final class ActivityStack { */ final boolean requestFinishActivityLocked(IBinder token, int resultCode, Intent resultData, String reason) { - if (DEBUG_RESULTS) Slog.v( - TAG, "Finishing activity: token=" + token - + ", result=" + resultCode + ", data=" + resultData); - int index = indexOfTokenLocked(token); + if (DEBUG_RESULTS) Slog.v( + TAG, "Finishing activity @" + index + ": token=" + token + + ", result=" + resultCode + ", data=" + resultData); if (index < 0) { return false; } ActivityRecord r = mHistory.get(index); - // Is this the last activity left? - boolean lastActivity = true; - for (int i=mHistory.size()-1; i>=0; i--) { - ActivityRecord p = mHistory.get(i); - if (!p.finishing && p != r) { - lastActivity = false; - break; - } - } - - // If this is the last activity, but it is the home activity, then - // just don't finish it. - if (lastActivity) { - if (r.intent.hasCategory(Intent.CATEGORY_HOME)) { - return false; - } - } - finishActivityLocked(r, index, resultCode, resultData, reason); return true; } @@ -3538,6 +3552,11 @@ final class ActivityStack { private final void removeActivityFromHistoryLocked(ActivityRecord r) { if (r.state != ActivityState.DESTROYED) { r.makeFinishing(); + if (DEBUG_ADD_REMOVE) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Removing activity " + r + " from stack"); + } mHistory.remove(r); r.takeFromHistory(); if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r @@ -3769,6 +3788,11 @@ final class ActivityStack { TAG, "At " + pos + " ckp " + r.task + ": " + r); if (r.task.taskId == task) { if (localLOGV) Slog.v(TAG, "Removing and adding at " + top); + if (DEBUG_ADD_REMOVE) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Removing and adding activity " + r + " to stack at " + top, here); + } mHistory.remove(pos); mHistory.add(top, r); moved.add(0, r); @@ -3858,6 +3882,12 @@ final class ActivityStack { TAG, "At " + pos + " ckp " + r.task + ": " + r); if (r.task.taskId == task) { if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1)); + if (DEBUG_ADD_REMOVE) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Removing and adding activity " + r + " to stack at " + + bottom, here); + } mHistory.remove(pos); mHistory.add(bottom, r); moved.add(r); |