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

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

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
parent 0f3b7c08
Loading
Loading
Loading
Loading
+36 −24
Original line number Diff line number Diff line
@@ -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)
            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.
                    .addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification",
            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
                    // 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",
                    .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())
                        .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());
        }
    }

+2 −0
Original line number Diff line number Diff line
@@ -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<>();
+53 −44
Original line number Diff line number Diff line
@@ -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<TaskDisplayArea> 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<DisplayAreaPolicy, List<TaskDisplayArea>> 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<DisplayAreaPolicy, List<TaskDisplayArea>> 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<DisplayAreaPolicy, List<TaskDisplayArea>> 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<TaskDisplayArea> 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);
    }
}