From b87dc233af9d01aafa83ca3107f1e12991963440 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Thu, 10 Dec 2020 00:25:02 +0800 Subject: [PATCH] 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 layers (according to current features) per untrusted display. And also reduce the cost of traversing entire hierarchy. Fixes: 175179353 Test: DisplayAreaPolicyTests#testEmptyFeaturesOnUntrustedDisplay Change-Id: Iad45217c9e09f33ef9f3f4503b9db2a8a21995a3 --- .../android/server/wm/DisplayAreaPolicy.java | 60 +++++++----- .../wm/DisplayAreaPolicyBuilderTest.java | 2 + .../server/wm/DisplayAreaPolicyTests.java | 97 ++++++++++--------- 3 files changed, 91 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..f8c375497b7b5 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); + if (content.isTrusted()) { + // Only trusted display can have system decorations. + configureTrustedHierarchyBuilder(rootHierarchy, wmService, content); + } + // Set the essential containers (even the display doesn't support IME). + rootHierarchy.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); + } + + 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 e47913fba7abc..8e78dce39ac7f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java @@ -40,6 +40,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; @@ -100,6 +101,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..d451180c72696 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,18 @@ 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.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 +41,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 +56,65 @@ 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()); } @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 +192,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); + } }