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

Commit 2c3fa218 authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Simplify handling process died for activity"

parents aa57b291 7fce3393
Loading
Loading
Loading
Loading
+69 −4
Original line number Diff line number Diff line
@@ -2865,7 +2865,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

        if (hasProcess()) {
            if (removeFromApp) {
                app.removeActivity(this);
                app.removeActivity(this, true /* keepAssociation */);
                if (!app.hasActivities()) {
                    mAtmService.clearHeavyWeightProcessIfEquals(app);
                    // Update any services we are bound to that might care about whether
@@ -2914,7 +2914,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                setState(DESTROYED,
                        "destroyActivityLocked. not finishing or skipping destroy");
                if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this);
                app = null;
                detachFromProcess();
            }
        } else {
            // Remove this record from the history.
@@ -2963,13 +2963,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
        setState(DESTROYED, "removeFromHistory");
        if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
        app = null;
        detachFromProcess();
        removeAppTokenFromDisplay();

        cleanUpActivityServices();
        removeUriPermissionsLocked();
    }

    void detachFromProcess() {
        if (app != null) {
            app.removeActivity(this, false /* keepAssociation */);
        }
        app = null;
    }

    void makeFinishingLocked() {
        if (finishing) {
            return;
@@ -3019,7 +3026,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (setState) {
            setState(DESTROYED, "cleanUp");
            if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + this);
            app = null;
            detachFromProcess();
        }

        // Inform supervisor the activity has been removed.
@@ -3160,6 +3167,64 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        mServiceConnectionsHolder = null;
    }

    /**
     * Detach this activity from process and clear the references to it. If the activity is
     * finishing or has no saved state or crashed many times, it will also be removed from history.
     */
    void handleAppDied() {
        final boolean remove;
        if ((mRelaunchReason == RELAUNCH_REASON_WINDOWING_MODE_RESIZE
                || mRelaunchReason == RELAUNCH_REASON_FREE_RESIZE)
                && launchCount < 3 && !finishing) {
            // If the process crashed during a resize, always try to relaunch it, unless it has
            // failed more than twice. Skip activities that's already finishing cleanly by itself.
            remove = false;
        } else if ((!mHaveState && !stateNotNeeded
                && !isState(ActivityState.RESTARTING_PROCESS)) || finishing) {
            // Don't currently have state for the activity, or it is finishing -- always remove it.
            remove = true;
        } else if (!mVisibleRequested && launchCount > 2
                && lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
            // We have launched this activity too many times since it was able to run, so give up
            // and remove it. (Note if the activity is visible, we don't remove the record. We leave
            // the dead window on the screen but the process will not be restarted unless user
            // explicitly tap on it.)
            remove = true;
        } else {
            // The process may be gone, but the activity lives on!
            remove = false;
        }
        if (remove) {
            if (ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
                Slog.i(TAG_ADD_REMOVE, "Removing activity " + this
                        + " hasSavedState=" + mHaveState + " stateNotNeeded=" + stateNotNeeded
                        + " finishing=" + finishing + " state=" + mState
                        + " callers=" + Debug.getCallers(5));
            }
            if (!finishing || (app != null && app.isRemoved())) {
                Slog.w(TAG, "Force removing " + this + ": app died, no saved state");
                EventLogTags.writeWmFinishActivity(mUserId, System.identityHashCode(this),
                        task != null ? task.mTaskId : -1, shortComponentName,
                        "proc died without state saved");
            }
        } else {
            // We have the current state for this activity, so it can be restarted later
            // when needed.
            if (DEBUG_APP) {
                Slog.v(TAG_APP, "Keeping entry during removeHistory for activity " + this);
            }
            // Set nowVisible to previous visible state. If the app was visible while it died, we
            // leave the dead window on screen so it's basically visible. This is needed when user
            // later tap on the dead window, we need to stop other apps when user transfers focus
            // to the restarted activity.
            nowVisible = mVisibleRequested;
        }
        cleanUp(true /* cleanServices */, true /* setState */);
        if (remove) {
            removeFromHistory("appDied");
        }
    }

    @Override
    void removeImmediately() {
        onRemovedFromDisplay();
+1 −1
Original line number Diff line number Diff line
@@ -891,7 +891,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
                // This is the first time we failed -- restart process and
                // retry.
                r.launchFailed = true;
                proc.removeActivity(r);
                proc.removeActivity(r, true /* keepAssociation */);
                throw e;
            }
        } finally {
+8 −5
Original line number Diff line number Diff line
@@ -6789,11 +6789,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        public void handleAppDied(WindowProcessController wpc, boolean restarting,
                Runnable finishInstrumentationCallback) {
            synchronized (mGlobalLockWithoutBoost) {
                mStackSupervisor.beginDeferResume();
                final boolean hasVisibleActivities;
                try {
                    // Remove this application's activities from active lists.
                boolean hasVisibleActivities = mRootWindowContainer.handleAppDied(wpc);

                wpc.clearRecentTasks();
                wpc.clearActivities();
                    hasVisibleActivities = wpc.handleAppDied();
                } finally {
                    mStackSupervisor.endDeferResume();
                }

                if (wpc.isInstrumenting()) {
                    finishInstrumentationCallback.run();
+1 −17
Original line number Diff line number Diff line
@@ -2751,7 +2751,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
        if (r.app != app) return;
        Slog.w(TAG, "  Force finishing activity "
                + r.intent.getComponent().flattenToShortString());
        r.app = null;
        r.detachFromProcess();
        r.getDisplay().mDisplayContent.prepareAppTransition(
                TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
        r.destroyIfPossible("handleAppCrashed");
@@ -3104,22 +3104,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
        return null;
    }

    boolean handleAppDied(WindowProcessController app) {
        if (app.isRemoved()) {
            // The package of the died process should be force-stopped, so make its activities as
            // finishing to prevent the process from being started again if the next top (or being
            // visible) activity also resides in the same process.
            app.makeFinishingForProcessRemoved();
        }
        return reduceOnAllTaskDisplayAreas((taskDisplayArea, result) -> {
            for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
                final Task stack = taskDisplayArea.getStackAt(sNdx);
                result |= stack.handleAppDied(app);
            }
            return result;
        }, false /* initValue */);
    }

    void closeSystemDialogActivities(String reason) {
        forAllActivities((r) -> {
            if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0
+1 −114
Original line number Diff line number Diff line
@@ -86,8 +86,6 @@ import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
@@ -115,8 +113,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIB
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
@@ -746,111 +742,6 @@ class Task extends WindowContainer<WindowContainer> {
        }
    }

    // TODO: Can we just loop through WindowProcessController#mActivities instead of doing this?
    private final RemoveHistoryRecordsForApp mRemoveHistoryRecordsForApp =
            new RemoveHistoryRecordsForApp();
    private class RemoveHistoryRecordsForApp {
        private boolean mHasVisibleActivities;
        private boolean mIsProcessRemoved;
        private WindowProcessController mApp;
        private ArrayList<ActivityRecord> mToRemove = new ArrayList<>();

        boolean process(WindowProcessController app) {
            mToRemove.clear();
            mHasVisibleActivities = false;
            mApp = app;
            mIsProcessRemoved = app.isRemoved();

            final PooledConsumer c = PooledLambda.obtainConsumer(
                    RemoveHistoryRecordsForApp::addActivityToRemove, this,
                    PooledLambda.__(ActivityRecord.class));
            forAllActivities(c);
            c.recycle();

            while (!mToRemove.isEmpty()) {
                processActivity(mToRemove.remove(0));
            }

            mApp = null;
            return mHasVisibleActivities;
        }

        private void addActivityToRemove(ActivityRecord r) {
            if (r.app == mApp) {
                mToRemove.add(r);
            }
        }

        private void processActivity(ActivityRecord r) {
            if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record " + r + ": app=" + r.app);

            if (r.app != mApp) {
                return;
            }
            if (r.isVisible() || r.mVisibleRequested) {
                // While an activity launches a new activity, it's possible that the old
                // activity is already requested to be hidden (mVisibleRequested=false), but
                // this visibility is not yet committed, so isVisible()=true.
                mHasVisibleActivities = true;
            }
            final boolean remove;
            if ((r.mRelaunchReason == RELAUNCH_REASON_WINDOWING_MODE_RESIZE
                    || r.mRelaunchReason == RELAUNCH_REASON_FREE_RESIZE)
                    && r.launchCount < 3 && !r.finishing) {
                // If the process crashed during a resize, always try to relaunch it, unless
                // it has failed more than twice. Skip activities that's already finishing
                // cleanly by itself.
                remove = false;
            } else if ((!r.hasSavedState() && !r.stateNotNeeded
                    && !r.isState(ActivityState.RESTARTING_PROCESS)) || r.finishing) {
                // Don't currently have state for the activity, or
                // it is finishing -- always remove it.
                remove = true;
            } else if (!r.mVisibleRequested && 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.
                // (Note if the activity is visible, we don't remove the record.
                // We leave the dead window on the screen but the process will
                // not be restarted unless user explicitly tap on it.)
                remove = true;
            } else {
                // The process may be gone, but the activity lives on!
                remove = false;
            }
            if (remove) {
                if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE,
                        "Removing activity " + r + " from stack "
                                + ": hasSavedState=" + r.hasSavedState()
                                + " stateNotNeeded=" + r.stateNotNeeded
                                + " finishing=" + r.finishing
                                + " state=" + r.getState() + " callers=" + Debug.getCallers(5));
                if (!r.finishing || mIsProcessRemoved) {
                    Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
                    EventLogTags.writeWmFinishActivity(r.mUserId,
                            System.identityHashCode(r), r.getTask().mTaskId,
                            r.shortComponentName, "proc died without state saved");
                }
            } else {
                // We have the current state for this activity, so
                // it can be restarted later when needed.
                if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null");
                if (DEBUG_APP) Slog.v(TAG_APP,
                        "Clearing app during removeHistory for activity " + r);
                r.app = null;
                // Set nowVisible to previous visible state. If the app was visible while
                // it died, we leave the dead window on screen so it's basically visible.
                // This is needed when user later tap on the dead window, we need to stop
                // other apps when user transfers focus to the restarted activity.
                r.nowVisible = r.mVisibleRequested;
            }
            r.cleanUp(true /* cleanServices */, true /* setState */);
            if (remove) {
                r.removeFromHistory("appDied");
            }
        }
    }

    private final FindRootHelper mFindRootHelper = new FindRootHelper();
    private class FindRootHelper {
        private ActivityRecord mRoot;
@@ -7167,9 +7058,8 @@ class Task extends WindowContainer<WindowContainer> {
    /**
     * Reset local parameters because an app's activity died.
     * @param app The app of the activity that died.
     * @return result from removeHistoryRecordsForAppLocked.
     */
    boolean handleAppDied(WindowProcessController app) {
    void handleAppDied(WindowProcessController app) {
        if (mPausingActivity != null && mPausingActivity.app == app) {
            if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
                    "App died while pausing: " + mPausingActivity);
@@ -7179,9 +7069,6 @@ class Task extends WindowContainer<WindowContainer> {
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }

        mStackSupervisor.removeHistoryRecords(app);
        return mRemoveHistoryRecordsForApp.process(app);
    }

    boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
Loading