From 9adc55fdc6ab44dbe2b02de72f84280857565bfe Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 28 Apr 2020 17:07:33 +0800 Subject: [PATCH] Fix stack reference is not updated if the task is organized There is an additional stack level for split-screen mode, the child of the organizer may be the instance referenced by task display area. So if the child is removed, the stack reference should also be updated. The corresponding operations of removeChild should be put in the redirected implementation method, otherwise it will be missed when propagating the removal to parent, that may cause reusing a detached task and then crash because it does not have parent and display. Bug: 154679904 Test: ActivityStackTests#testRemoveOrganizedTask_UpdateStackReference Change-Id: I9c4032409345c772baa055e32da9eaba9a274b53 --- .../core/java/com/android/server/wm/Task.java | 10 +++++----- .../android/server/wm/ActivityStackTests.java | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 2115a591a6b77..d14f5824b0125 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -1431,15 +1431,15 @@ class Task extends WindowContainer { @Override void removeChild(WindowContainer child) { - // A rootable child task that is now being removed from an organized task. Making sure - // the stack references is keep updated. - if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) { - getDisplayArea().removeStackReferenceIfNeeded((ActivityStack) child); - } removeChild(child, "removeChild"); } void removeChild(WindowContainer r, String reason) { + // A rootable child task that is now being removed from an organized task. Making sure + // the stack references is keep updated. + if (mTaskOrganizer != null && mCreatedByOrganizer && r.asTask() != null) { + getDisplayArea().removeStackReferenceIfNeeded((ActivityStack) r); + } if (!mChildren.contains(r)) { Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this); return; diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index 6c209e496cf61..5227f3c885baf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -233,6 +233,25 @@ public class ActivityStackTests extends ActivityTestsBase { assertEquals(homeRoot.getParent(), secondaryTask.getParent()); } + @Test + public void testRemoveOrganizedTask_UpdateStackReference() { + final ActivityStack rootHomeTask = mDefaultTaskDisplayArea.getRootHomeTask(); + final ActivityRecord homeActivity = new ActivityBuilder(mService) + .setStack(rootHomeTask) + .setCreateTask(true) + .build(); + final ActivityStack secondaryStack = (ActivityStack) WindowContainer.fromBinder( + mService.mTaskOrganizerController.createRootTask(rootHomeTask.getDisplayId(), + WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token.asBinder()); + + rootHomeTask.reparent(secondaryStack, POSITION_TOP); + assertEquals(secondaryStack, rootHomeTask.getParent()); + + // This should call to {@link TaskDisplayArea#removeStackReferenceIfNeeded}. + homeActivity.removeImmediately(); + assertNull(mDefaultTaskDisplayArea.getRootHomeTask()); + } + @Test public void testStackInheritsDisplayWindowingMode() { final ActivityStack primarySplitScreen = mDefaultTaskDisplayArea.createStack(