From ac6d791c75a1be5d0842416b6909907357bc00a2 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Thu, 10 Dec 2020 00:25:02 +0800 Subject: [PATCH] Reland "Do not add display area features for untrusted display" Untrusted display (e.g. virtual display created by app, a common case is screen recorder) doesn't support system decorations. There is nothing to do with additional features. This saves 31 areas (according to current features) per untrusted display. And also reduce the cost of traversing entire hierarchy. Reland since making DisplayContent#getWindowingLayer() valid by commit 941ad3a. Fixes: 175179353 Test: DisplayAreaPolicyTests#testEmptyFeaturesOnUntrustedDisplay Test: Start Desktop Head Unit (simulation of Auto) Change-Id: I3929d17eab6bed3f1358d6782e363120f0edd385 --- .../android/server/wm/DisplayAreaPolicy.java | 60 ++++++----- .../wm/DisplayAreaPolicyBuilderTest.java | 2 + .../server/wm/DisplayAreaPolicyTests.java | 100 ++++++++++-------- 3 files changed, 94 insertions(+), 68 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java index d4b319a525da5..5952164d65546 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java @@ -99,23 +99,41 @@ public abstract class DisplayAreaPolicy { // Define the features that will be supported under the root of the whole logical // display. The policy will build the DisplayArea hierarchy based on this. - HierarchyBuilder rootHierarchy = new HierarchyBuilder(root) - // WindowedMagnification should be on the top so that there is only one surface - // to be magnified. - .addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification", - FEATURE_WINDOWED_MAGNIFICATION) - .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY) - .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY) - // Make the DA dimmable so that the magnify window also mirrors the dim - // layer - .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new) - .build()) - .addFeature(new Feature.Builder(wmService.mPolicy, "HideDisplayCutout", - FEATURE_HIDE_DISPLAY_CUTOUT) - .all() - .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR, - TYPE_NOTIFICATION_SHADE) - .build()) + final HierarchyBuilder rootHierarchy = new HierarchyBuilder(root); + // Set the essential containers (even if the display doesn't support IME). + rootHierarchy.setImeContainer(imeContainer).setTaskDisplayAreas(tdaList); + if (content.isTrusted()) { + // Only trusted display can have system decorations. + configureTrustedHierarchyBuilder(rootHierarchy, wmService, content); + } + + // Instantiate the policy with the hierarchy defined above. This will create and attach + // all the necessary DisplayAreas to the root. + return new DisplayAreaPolicyBuilder().setRootHierarchy(rootHierarchy).build(wmService); + } + + private void configureTrustedHierarchyBuilder(HierarchyBuilder rootHierarchy, + WindowManagerService wmService, DisplayContent content) { + // WindowedMagnification should be on the top so that there is only one surface + // to be magnified. + rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification", + FEATURE_WINDOWED_MAGNIFICATION) + .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY) + .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY) + // Make the DA dimmable so that the magnify window also mirrors the dim layer. + .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new) + .build()); + if (content.isDefaultDisplay) { + // Only default display can have cutout. + // See LocalDisplayAdapter.LocalDisplayDevice#getDisplayDeviceInfoLocked. + rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "HideDisplayCutout", + FEATURE_HIDE_DISPLAY_CUTOUT) + .all() + .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR, + TYPE_NOTIFICATION_SHADE) + .build()); + } + rootHierarchy .addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded", FEATURE_ONE_HANDED) .all() @@ -131,13 +149,7 @@ public abstract class DisplayAreaPolicy { .addFeature(new Feature.Builder(wmService.mPolicy, "ImePlaceholder", FEATURE_IME_PLACEHOLDER) .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG) - .build()) - .setImeContainer(imeContainer) - .setTaskDisplayAreas(tdaList); - - // Instantiate the policy with the hierarchy defined above. This will create and attach - // all the necessary DisplayAreas to the root. - return new DisplayAreaPolicyBuilder().setRootHierarchy(rootHierarchy).build(wmService); + .build()); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java index b33bb7bcd217d..3306e313f95e0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java @@ -41,6 +41,7 @@ import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.testng.Assert.assertThrows; @@ -101,6 +102,7 @@ public class DisplayAreaPolicyBuilderTest { mRoot = new SurfacelessDisplayAreaRoot(mWms); mImeContainer = new DisplayArea.Tokens(mWms, ABOVE_TASKS, "ImeContainer"); mDisplayContent = mock(DisplayContent.class); + doReturn(true).when(mDisplayContent).isTrusted(); mDefaultTaskDisplayArea = new TaskDisplayArea(mDisplayContent, mWms, "Tasks", FEATURE_DEFAULT_TASK_CONTAINER); mTaskDisplayAreaList = new ArrayList<>(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java index 496b2b7447121..2a5508352691e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java @@ -22,15 +22,19 @@ import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS; import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import android.platform.test.annotations.Presubmit; +import android.util.Pair; +import android.view.Display; +import android.view.DisplayInfo; import androidx.test.filters.SmallTest; @@ -38,9 +42,8 @@ import com.android.server.wm.DisplayAreaPolicyBuilderTest.SurfacelessDisplayArea import com.google.android.collect.Lists; -import org.junit.Before; -import org.junit.Rule; import org.junit.Test; +import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Collections; @@ -54,78 +57,67 @@ import java.util.List; */ @SmallTest @Presubmit -public class DisplayAreaPolicyTests { - - @Rule - public final SystemServicesTestRule mSystemServices = new SystemServicesTestRule(); - - private DisplayAreaPolicyBuilder.Result mPolicy; - private TaskDisplayArea mTaskDisplayArea1; - private TaskDisplayArea mTaskDisplayArea2; - private RootDisplayArea mRoot; - - @Before - public void setUp() throws Exception { - WindowManagerService wms = mSystemServices.getWindowManagerService(); - mRoot = new SurfacelessDisplayAreaRoot(wms); - spyOn(mRoot); - DisplayArea.Tokens ime = new DisplayArea.Tokens(wms, ABOVE_TASKS, "Ime"); - DisplayContent displayContent = mock(DisplayContent.class); - doReturn(true).when(displayContent).isTrusted(); - mTaskDisplayArea1 = new TaskDisplayArea(displayContent, wms, "Tasks1", - FEATURE_DEFAULT_TASK_CONTAINER); - mTaskDisplayArea2 = new TaskDisplayArea(displayContent, wms, "Tasks2", - FEATURE_VENDOR_FIRST); - List taskDisplayAreaList = new ArrayList<>(); - taskDisplayAreaList.add(mTaskDisplayArea1); - taskDisplayAreaList.add(mTaskDisplayArea2); - - mPolicy = new DisplayAreaPolicyBuilder() - .setRootHierarchy(new DisplayAreaPolicyBuilder.HierarchyBuilder(mRoot) - .setImeContainer(ime) - .setTaskDisplayAreas(taskDisplayAreaList)) - .build(wms); - } +@RunWith(WindowTestRunner.class) +public class DisplayAreaPolicyTests extends WindowTestsBase { @Test public void testGetDefaultTaskDisplayArea() { - assertEquals(mTaskDisplayArea1, mPolicy.getDefaultTaskDisplayArea()); + final Pair> result = + createPolicyWith2TaskDisplayAreas(); + final DisplayAreaPolicy policy = result.first; + final TaskDisplayArea taskDisplayArea1 = result.second.get(0); + assertEquals(taskDisplayArea1, policy.getDefaultTaskDisplayArea()); } @Test public void testTaskDisplayArea_taskPositionChanged_updatesTaskDisplayAreaPosition() { - final Task stack1 = mTaskDisplayArea1.createRootTask( + final Pair> result = + createPolicyWith2TaskDisplayAreas(); + final DisplayAreaPolicy policy = result.first; + final TaskDisplayArea taskDisplayArea1 = result.second.get(0); + final TaskDisplayArea taskDisplayArea2 = result.second.get(1); + final Task stack1 = taskDisplayArea1.createRootTask( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); - final Task stack2 = mTaskDisplayArea2.createRootTask( + final Task stack2 = taskDisplayArea2.createRootTask( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); // Initial order - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2); + assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2); // Move stack in tda1 to top stack1.getParent().positionChildAt(POSITION_TOP, stack1, true /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea2, mTaskDisplayArea1); + assertTaskDisplayAreasOrder(policy, taskDisplayArea2, taskDisplayArea1); // Move stack in tda2 to top, but not including parents stack2.getParent().positionChildAt(POSITION_TOP, stack2, false /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea2, mTaskDisplayArea1); + assertTaskDisplayAreasOrder(policy, taskDisplayArea2, taskDisplayArea1); // Move stack in tda1 to bottom stack1.getParent().positionChildAt(POSITION_BOTTOM, stack1, true /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2); + assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2); // Move stack in tda2 to bottom, but not including parents stack2.getParent().positionChildAt(POSITION_BOTTOM, stack2, false /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2); + assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2); + } + + @Test + public void testEmptyFeaturesOnUntrustedDisplay() { + final DisplayInfo info = new DisplayInfo(mDisplayInfo); + info.flags &= ~Display.FLAG_TRUSTED; + final DisplayContent untrustedDisplay = new TestDisplayContent.Builder(mAtm, info).build(); + + assertTrue(untrustedDisplay.mFeatures.isEmpty()); + assertNotNull(untrustedDisplay.getWindowingLayer()); } @Test public void testDisplayAreaGroup_taskPositionChanged_updatesDisplayAreaGroupPosition() { - final WindowManagerService wms = mSystemServices.getWindowManagerService(); + final WindowManagerService wms = mWm; final DisplayContent displayContent = mock(DisplayContent.class); doReturn(true).when(displayContent).isTrusted(); final RootDisplayArea root = new SurfacelessDisplayAreaRoot(wms); @@ -203,4 +195,24 @@ public class DisplayAreaPolicyTests { }, false /* traverseTopToBottom */); assertEquals(expectOrder, actualOrder); } + + private Pair> createPolicyWith2TaskDisplayAreas() { + final SurfacelessDisplayAreaRoot root = new SurfacelessDisplayAreaRoot(mWm); + final DisplayArea.Tokens ime = new DisplayArea.Tokens(mWm, ABOVE_TASKS, "Ime"); + final DisplayContent displayContent = mock(DisplayContent.class); + doReturn(true).when(displayContent).isTrusted(); + final TaskDisplayArea taskDisplayArea1 = new TaskDisplayArea(displayContent, mWm, "Tasks1", + FEATURE_DEFAULT_TASK_CONTAINER); + final TaskDisplayArea taskDisplayArea2 = new TaskDisplayArea(displayContent, mWm, "Tasks2", + FEATURE_VENDOR_FIRST); + final List taskDisplayAreaList = new ArrayList<>(); + taskDisplayAreaList.add(taskDisplayArea1); + taskDisplayAreaList.add(taskDisplayArea2); + + return Pair.create(new DisplayAreaPolicyBuilder() + .setRootHierarchy(new DisplayAreaPolicyBuilder.HierarchyBuilder(root) + .setImeContainer(ime) + .setTaskDisplayAreas(taskDisplayAreaList)) + .build(mWm), taskDisplayAreaList); + } }