From 0214ed9b119cdbc87cfc12908635deaf16603fe5 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Tue, 16 May 2017 13:44:05 -0700 Subject: [PATCH] Don't report displays that are going to be removed When display is removed from system, it is immediately removed from AM, but removal can be deferred in WM if there is an active animation on that display. If AM then requests display ids in focus order from WM, it might get a display that was already deleted in AM. This CL skips displays marked for deferred removal. Bug: 38166277 Test: DisplayContentTests#testDontReportDeferredRemoval Change-Id: I49544963f476fc58a609094781ed46541af8a238 --- .../com/android/server/wm/DisplayContent.java | 5 +++++ .../server/wm/RootWindowContainer.java | 7 ++++++- .../server/wm/DisplayContentTests.java | 21 ++++++++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 257f2856213e2..5ace9a02b6c92 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1892,6 +1892,11 @@ class DisplayContent extends WindowContainer { final int size = mChildren.size(); for (int i = 0; i < size; ++i) { - displaysInFocusOrder.put(i, mChildren.get(i).getDisplayId()); + final DisplayContent displayContent = mChildren.get(i); + if (displayContent.isRemovalDeferred()) { + // Don't report displays that are going to be removed soon. + continue; + } + displaysInFocusOrder.put(i, displayContent.getDisplayId()); } } diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java index f9254ad8180b2..856e94055ed51 100644 --- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java @@ -34,6 +34,7 @@ import android.content.res.Configuration; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; +import android.util.SparseIntArray; import java.util.Arrays; import java.util.LinkedList; @@ -239,7 +240,7 @@ public class DisplayContentTests extends WindowTestsBase { @Test @Ignore public void testFocusedWindowMultipleDisplays() throws Exception { - // Create a focusable window and check that focus is calcualted correctly + // Create a focusable window and check that focus is calculated correctly final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1"); assertEquals(window1, sWm.mRoot.computeFocusedWindow()); @@ -310,6 +311,24 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(afterStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID)); } + /** + * Test that WM does not report displays to AM that are pending to be removed. + */ + @Test + public void testDontReportDeferredRemoval() { + // Create a display and add an animating window to it. + final DisplayContent dc = createNewDisplay(); + final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w"); + window.mAnimatingExit = true; + // Request display removal, it should be deferred. + dc.removeIfPossible(); + // Request ordered display ids from WM. + final SparseIntArray orderedDisplayIds = new SparseIntArray(); + sWm.getDisplaysInFocusOrder(orderedDisplayIds); + // Make sure that display that is marked for removal is not reported. + assertEquals(-1, orderedDisplayIds.indexOfValue(dc.getDisplayId())); + } + private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth, int expectedBaseHeight, int expectedBaseDensity) { assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);