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

Commit 6acf5436 authored by Andrii Kulian's avatar Andrii Kulian Committed by Android (Google) Code Review
Browse files

Merge "Prevent exception when stack being removed on crash" into pi-dev

parents a24ddf58 8cc92ac6
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -3544,7 +3544,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        mService.updateOomAdjLocked();
    }

    final TaskRecord finishTopRunningActivityLocked(ProcessRecord app, String reason) {
    /**
     * Finish the topmost activity that belongs to the crashed app. We may also finish the activity
     * that requested launch of the crashed one to prevent launch-crash loop.
     * @param app The app that crashed.
     * @param reason Reason to perform this action.
     * @return The task that was finished in this stack, {@code null} if top running activity does
     *         not belong to the crashed app.
     */
    final TaskRecord finishTopCrashedActivityLocked(ProcessRecord app, String reason) {
        ActivityRecord r = topRunningActivityLocked();
        TaskRecord finishedTask = null;
        if (r == null || r.app != app) {
+11 −4
Original line number Diff line number Diff line
@@ -2126,15 +2126,22 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        }
    }

    TaskRecord finishTopRunningActivityLocked(ProcessRecord app, String reason) {
    /**
     * Finish the topmost activities in all stacks that belong to the crashed app.
     * @param app The app that crashed.
     * @param reason Reason to perform this action.
     * @return The task that was finished in this stack, {@code null} if haven't found any.
     */
    TaskRecord finishTopCrashedActivitiesLocked(ProcessRecord app, String reason) {
        TaskRecord finishedTask = null;
        ActivityStack focusedStack = getFocusedStack();
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
            final int numStacks = display.getChildCount();
            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
            // It is possible that request to finish activity might also remove its task and stack,
            // so we need to be careful with indexes in the loop and check child count every time.
            for (int stackNdx = 0; stackNdx < display.getChildCount(); ++stackNdx) {
                final ActivityStack stack = display.getChildAt(stackNdx);
                TaskRecord t = stack.finishTopRunningActivityLocked(app, reason);
                final TaskRecord t = stack.finishTopCrashedActivityLocked(app, reason);
                if (stack == focusedStack || finishedTask == null) {
                    finishedTask = t;
                }
+2 −2
Original line number Diff line number Diff line
@@ -742,8 +742,8 @@ class AppErrors {
            }
            mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
        } else {
            TaskRecord affectedTask =
                    mService.mStackSupervisor.finishTopRunningActivityLocked(app, reason);
            final TaskRecord affectedTask =
                    mService.mStackSupervisor.finishTopCrashedActivitiesLocked(app, reason);
            if (data != null) {
                data.task = affectedTask;
            }
+22 −0
Original line number Diff line number Diff line
@@ -265,4 +265,26 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
        // Supervisor should skip over the non-existent display.
        assertEquals(null, mSupervisor.topRunningActivityLocked());
    }

    /**
     * Verifies that removal of activity with task and stack is done correctly.
     */
    @Test
    public void testRemovingStackOnAppCrash() throws Exception {
        final ActivityDisplay defaultDisplay = mService.mStackSupervisor.getDefaultDisplay();
        final int originalStackCount = defaultDisplay.getChildCount();
        final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
        final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
                .setStack(stack).build();

        assertEquals(originalStackCount + 1, defaultDisplay.getChildCount());

        // Let's pretend that the app has crashed.
        firstActivity.app.thread = null;
        mService.mStackSupervisor.finishTopCrashedActivitiesLocked(firstActivity.app, "test");

        // Verify that the stack was removed.
        assertEquals(originalStackCount, defaultDisplay.getChildCount());
    }
}