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

Commit ed592f8b authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Destroy activity if task is removed directly

Otherwise the activity is unreachable from hierarchy but
WindowProcessController still references to the activity.

- Task#removeImmediately will go super.removeImmediately so
  its children's removeImmediately will also be called. That
  is the place to destroy activity.
- Avoid reentrant of Task#removeImmediately because it is
  confusing to see multiple wm_task_removed with different
  reasons, e.g. [deleteRootTask, setTaskOrganizer] and
  [removeTask, cleanUpResourcesForDestroy]. And it also
  eliminates duplicated invocation of super.removeImmediately.
- Add validation for setLaunchRoot.

Bug: 177633638
Test: ActivityRecordTests#testRemoveImmediately

Change-Id: I762f0a720d1709bb72deaacd857d5e79ce48d1b2
parent 839c1cd5
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -3244,6 +3244,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

    @Override
    void removeImmediately() {
        if (!finishing) {
            // If Task#removeImmediately is called directly with alive activities, ensure that the
            // activities are destroyed and detached from process.
            destroyImmediately("removeImmediately");
        }
        onRemovedFromDisplay();
        super.removeImmediately();
    }
+9 −0
Original line number Diff line number Diff line
@@ -424,6 +424,9 @@ class Task extends WindowContainer<WindowContainer> {
    /** If original intent did not allow relinquishing task identity, save that information */
    private boolean mNeverRelinquishIdentity = true;

    /** Avoid reentrant of {@link #removeImmediately(String)}. */
    private boolean mRemoving;

    // Used in the unique case where we are clearing the task in order to reuse it. In that case we
    // do not want to delete the stack when the task goes empty.
    private boolean mReuseTask = false;
@@ -3223,12 +3226,18 @@ class Task extends WindowContainer<WindowContainer> {

    void removeImmediately(String reason) {
        if (DEBUG_ROOT_TASK) Slog.i(TAG, "removeTask:" + reason + " removing taskId=" + mTaskId);
        if (mRemoving) {
            return;
        }
        mRemoving = true;

        EventLogTags.writeWmTaskRemoved(mTaskId, reason);

        // If applicable let the TaskOrganizer know the Task is vanishing.
        setTaskOrganizer(null);

        super.removeImmediately();
        mRemoving = false;
    }

    // TODO: Consolidate this with Task.reparent()
+3 −3
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.server.wm;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -60,6 +59,7 @@ import com.android.internal.util.function.pooled.PooledPredicate;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
@@ -1937,8 +1937,8 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
            for (int i = mLaunchRootTasks.size() - 1; i >= 0; --i) {
                final LaunchRootTaskDef def = mLaunchRootTasks.get(i);
                pw.println(triplePrefix
                        + def.activityTypes + " "
                        + def.windowingModes + " "
                        + Arrays.toString(def.activityTypes) + " "
                        + Arrays.toString(def.windowingModes) + " "
                        + " task=" + def.task);
            }
        }
+9 −2
Original line number Diff line number Diff line
@@ -264,11 +264,18 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
            for (int i = 0, n = hops.size(); i < n; ++i) {
                final WindowContainerTransaction.HierarchyOp hop = hops.get(i);
                switch (hop.getType()) {
                    case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT:
                        final Task task = WindowContainer.fromBinder(hop.getContainer()).asTask();
                    case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT: {
                        final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
                        final Task task = wc != null ? wc.asTask() : null;
                        if (task != null) {
                            task.getDisplayArea().setLaunchRootTask(task,
                                    hop.getWindowingModes(), hop.getActivityTypes());
                        } else {
                            throw new IllegalArgumentException(
                                    "Cannot set non-task as launch root: " + wc);
                        }
                        break;
                    }
                    case HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT:
                        effects |= reparentChildrenTasksHierarchyOp(hop, transition, syncId);
                        break;
+14 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.app.servertransaction.ActivityConfigurationChangeItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.DestroyActivityItem;
import android.app.servertransaction.PauseActivityItem;
import android.content.ComponentName;
import android.content.Intent;
@@ -1448,6 +1449,19 @@ public class ActivityRecordTests extends WindowTestsBase {
        verify(activity).destroyImmediately(anyString());
    }

    @Test
    public void testRemoveImmediately() throws RemoteException {
        final ActivityRecord activity = createActivityWithTask();
        final WindowProcessController wpc = activity.app;
        activity.getTask().removeImmediately("test");

        verify(mAtm.getLifecycleManager()).scheduleTransaction(any(), eq(activity.appToken),
                isA(DestroyActivityItem.class));
        assertNull(activity.app);
        assertEquals(DESTROYED, activity.getState());
        assertFalse(wpc.hasActivities());
    }

    @Test
    public void testRemoveFromHistory() {
        final ActivityRecord activity = createActivityWithTask();