Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07981490 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix bug where we could get stuck repeatedly launching an activity.

A previous change to avoid losing activities if their process
happens to be gone at the point of launch (by counting that
activity as having its state saved) has resulted in a problem
where an activity that crashes during launch will be repeatedly
relaunched.

This is fixed here by explicitly keeping track of our attempts
to launch the activity since it was last able to save its state,
and not keeping it around if it looks like the launch is
repeatedly failing.

Change-Id: Icefd952443b7eb1222f233db95e0157fc3dd72d1
parent b9781fe0
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -123,6 +123,8 @@ final class ActivityRecord {
    boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
    boolean immersive;      // immersive mode (don't interrupt if possible)
    boolean forceNewConfig; // force re-create with new config next time
    int launchCount;        // count of launches since last state
    long lastLaunchTime;    // time of last lauch of this activity

    String stringName;      // for caching of toString().
    
@@ -201,7 +203,12 @@ final class ActivityRecord {
            }
        }
        pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
                pw.print(" haveState="); pw.print(haveState);
                pw.print(" launchCount="); pw.print(launchCount);
                pw.print(" lastLaunchTime=");
                if (lastLaunchTime == 0) pw.print("0");
                else TimeUtils.formatDuration(lastLaunchTime, now, pw);
                pw.println();
        pw.print(prefix); pw.print(" haveState="); pw.print(haveState);
                pw.print(" icicle="); pw.println(icicle);
        pw.print(prefix); pw.print("state="); pw.print(state);
                pw.print(" stopped="); pw.print(stopped);
+25 −1
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ final class ActivityStack {
    static final boolean DEBUG_STATES = false;
    static final boolean DEBUG_ADD_REMOVE = false;
    static final boolean DEBUG_SAVED_STATE = false;
    static final boolean DEBUG_APP = false;

    static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS;
    
@@ -653,6 +654,8 @@ final class ActivityStack {

        r.app = app;
        app.waitingToKill = null;
        r.launchCount++;
        r.lastLaunchTime = SystemClock.uptimeMillis();

        if (localLOGV) Slog.v(TAG, "Launching: " + r);

@@ -1091,6 +1094,7 @@ final class ActivityStack {
            // haven't really saved the state.
            r.icicle = icicle;
            r.haveState = true;
            r.launchCount = 0;
            r.updateThumbnail(thumbnail, description);
        }
        if (!r.stopped) {
@@ -3931,6 +3935,7 @@ final class ActivityStack {
        if (setState) {
            if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
            r.state = ActivityState.DESTROYED;
            if (DEBUG_APP) Slog.v(TAG, "Clearing app during cleanUp for activity " + r);
            r.app = null;
        }

@@ -3988,6 +3993,7 @@ final class ActivityStack {
        if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
                + " (removed from history)");
        r.state = ActivityState.DESTROYED;
        if (DEBUG_APP) Slog.v(TAG, "Clearing app during remove for activity " + r);
        r.app = null;
        mService.mWindowManager.removeAppToken(r.appToken);
        if (VALIDATE_TOKENS) {
@@ -4130,6 +4136,7 @@ final class ActivityStack {
                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
                        + " (destroy skipped)");
                r.state = ActivityState.DESTROYED;
                if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
                r.app = null;
            }
        } else {
@@ -4141,6 +4148,7 @@ final class ActivityStack {
                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
                        + " (no app)");
                r.state = ActivityState.DESTROYED;
                if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
                r.app = null;
            }
        }
@@ -4215,7 +4223,21 @@ final class ActivityStack {
            if (DEBUG_CLEANUP) Slog.v(
                TAG, "Record #" + i + " " + r + ": app=" + r.app);
            if (r.app == app) {
                boolean remove;
                if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
                    // Don't currently have state for the activity, or
                    // it is finishing -- always remove it.
                    remove = true;
                } else if (r.launchCount > 2 &&
                        r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) {
                    // We have launched this activity too many times since it was
                    // able to run, so give up and remove it.
                    remove = true;
                } else {
                    // The process may be gone, but the activity lives on!
                    remove = false;
                }
                if (remove) {
                    if (ActivityStack.DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
                        RuntimeException here = new RuntimeException("here");
                        here.fillInStackTrace();
@@ -4242,6 +4264,8 @@ final class ActivityStack {
                    if (r.visible) {
                        hasVisibleActivities = true;
                    }
                    if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity "
                            + r);
                    r.app = null;
                    r.nowVisible = false;
                    if (!r.haveState) {