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

Commit 915c2ade authored by Chris Li's avatar Chris Li
Browse files

Allow creating customized DA for Feature

(3/n DisplayArea Sibling Roots)

By creating customized DA for Feature, we can modify DA of different
Feature. Before, the DA.Root was dimmable, which caused the magnify
window not mirror the dim layer. Now, we make the DA of
FEATURE_WINDOWED_MAGNIFICATION dimmable, so that magnify window also
mirrors that.

Bug: 156425461
Test: atest WmTests:DisplayAreaPolicyBuilderTest
Test: verify the magnify window also mirrors dim layer.
Change-Id: Id0ec4acb2fe302bbcc2c222c5da94f99cb425324
parent 44a80126
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -266,11 +266,20 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
     * Top-most DisplayArea under DisplayContent.
     */
    public static class Root extends DisplayArea<DisplayArea> {
        Root(WindowManagerService wms) {
            super(wms, Type.ANY, "DisplayArea.Root", FEATURE_ROOT);
        }
    }

    /**
     * DisplayArea that can be dimmed.
     */
    static class Dimmable extends DisplayArea<DisplayArea> {
        private final Dimmer mDimmer = new Dimmer(this);
        private final Rect mTmpDimBoundsRect = new Rect();

        Root(WindowManagerService wms) {
            super(wms, Type.ANY, "DisplayArea.Root", FEATURE_ROOT);
        Dimmable(WindowManagerService wms, Type type, String name, int featureId) {
            super(wms, type, name, featureId);
        }

        @Override
+3 −0
Original line number Diff line number Diff line
@@ -124,6 +124,9 @@ public abstract class DisplayAreaPolicy {
                            "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 DisplayAreaPolicyBuilder.Feature.Builder(wmService.mPolicy,
                            "OneHanded", FEATURE_ONE_HANDED)
+23 −4
Original line number Diff line number Diff line
@@ -68,6 +68,12 @@ class DisplayAreaPolicyBuilder {

    private final ArrayList<Feature> mFeatures = new ArrayList<>();

    /** Supplier interface to provide a new created {@link DisplayArea}. */
    interface NewDisplayAreaSupplier {
        DisplayArea create(WindowManagerService wms, DisplayArea.Type type, String name,
                int featureId);
    }

    /**
     * A feature that requires {@link DisplayArea DisplayArea(s)}.
     */
@@ -75,11 +81,14 @@ class DisplayAreaPolicyBuilder {
        private final String mName;
        private final int mId;
        private final boolean[] mWindowLayers;
        private final NewDisplayAreaSupplier mNewDisplayAreaSupplier;

        private Feature(String name, int id, boolean[] windowLayers) {
        private Feature(String name, int id, boolean[] windowLayers,
                NewDisplayAreaSupplier newDisplayAreaSupplier) {
            mName = name;
            mId = id;
            mWindowLayers = windowLayers;
            mNewDisplayAreaSupplier = newDisplayAreaSupplier;
        }

        /**
@@ -104,6 +113,7 @@ class DisplayAreaPolicyBuilder {
            private final String mName;
            private final int mId;
            private final boolean[] mLayers;
            private NewDisplayAreaSupplier mNewDisplayAreaSupplier = DisplayArea::new;

            /**
             * Build a new feature that applies to a set of window types as specified by the builder
@@ -168,8 +178,17 @@ class DisplayAreaPolicyBuilder {
                return this;
            }

            /**
             * Sets the function to create new {@link DisplayArea} for this feature. By default, it
             * uses {@link DisplayArea}'s constructor.
             */
            Builder setNewDisplayAreaSupplier(NewDisplayAreaSupplier newDisplayAreaSupplier) {
                mNewDisplayAreaSupplier = newDisplayAreaSupplier;
                return this;
            }

            Feature build() {
                return new Feature(mName, mId, mLayers.clone());
                return new Feature(mName, mId, mLayers.clone(), mNewDisplayAreaSupplier);
            }

            private void set(int type, boolean value) {
@@ -416,8 +435,8 @@ class DisplayAreaPolicyBuilder {
                }
                return leaf;
            } else {
                return new DisplayArea(parent.mWmService, type, mFeature.mName + ":"
                        + mMinLayer + ":" + mMaxLayer, mFeature.mId);
                return mFeature.mNewDisplayAreaSupplier.create(parent.mWmService, type,
                        mFeature.mName + ":" + mMinLayer + ":" + mMaxLayer, mFeature.mId);
            }
        }
    }
+64 −28
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.wm;

import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -32,10 +33,12 @@ import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertFalse;

import static java.util.stream.Collectors.toList;

@@ -48,6 +51,7 @@ import androidx.test.filters.FlakyTest;
import org.hamcrest.CustomTypeSafeMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

@@ -61,6 +65,10 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Build/Install/Run:
 *  atest WmTests:DisplayAreaPolicyBuilderTest
 */
@Presubmit
public class DisplayAreaPolicyBuilderTest {

@@ -68,19 +76,28 @@ public class DisplayAreaPolicyBuilderTest {
    public final SystemServicesTestRule mSystemServices = new SystemServicesTestRule();

    private TestWindowManagerPolicy mPolicy = new TestWindowManagerPolicy(null, null);
    private WindowManagerService mWms;
    private DisplayArea.Root mRoot;
    private DisplayArea<WindowContainer> mImeContainer;
    private DisplayContent mDisplayContent;
    private TaskDisplayArea mDefaultTaskDisplayArea;
    private List<TaskDisplayArea> mTaskDisplayAreaList;

    @Before
    public void setup() {
        mWms = mSystemServices.getWindowManagerService();
        mRoot = new SurfacelessDisplayAreaRoot(mWms);
        mImeContainer = new DisplayArea<>(mWms, ABOVE_TASKS, "Ime");
        mDisplayContent = mock(DisplayContent.class);
        mDefaultTaskDisplayArea = new TaskDisplayArea(mDisplayContent, mWms, "Tasks",
                FEATURE_DEFAULT_TASK_CONTAINER);
        mTaskDisplayAreaList = new ArrayList<>();
        mTaskDisplayAreaList.add(mDefaultTaskDisplayArea);
    }

    @Test
    @FlakyTest(bugId = 149760939)
    public void testBuilder() {
        WindowManagerService wms = mSystemServices.getWindowManagerService();
        DisplayArea.Root root = new SurfacelessDisplayAreaRoot(wms);
        DisplayArea<WindowContainer> ime = new DisplayArea<>(wms, ABOVE_TASKS, "Ime");
        DisplayContent displayContent = mock(DisplayContent.class);
        TaskDisplayArea taskDisplayArea = new TaskDisplayArea(displayContent, wms, "Tasks",
                FEATURE_DEFAULT_TASK_CONTAINER);
        List<TaskDisplayArea> taskDisplayAreaList = new ArrayList<>();
        taskDisplayAreaList.add(taskDisplayArea);

        final Feature foo;
        final Feature bar;

@@ -93,7 +110,7 @@ public class DisplayAreaPolicyBuilderTest {
                        .all()
                        .except(TYPE_STATUS_BAR)
                        .build())
                .build(wms, displayContent, root, ime, taskDisplayAreaList);
                .build(mWms, mDisplayContent, mRoot, mImeContainer, mTaskDisplayAreaList);

        policy.attachDisplayAreas();

@@ -105,19 +122,19 @@ public class DisplayAreaPolicyBuilderTest {
        assertThat(policy.findAreaForToken(tokenOfType(TYPE_STATUS_BAR)),
                is(not(decendantOfOneOf(policy.getDisplayAreas(bar)))));

        assertThat(taskDisplayArea,
        assertThat(mDefaultTaskDisplayArea,
                is(decendantOfOneOf(policy.getDisplayAreas(foo))));
        assertThat(taskDisplayArea,
        assertThat(mDefaultTaskDisplayArea,
                is(decendantOfOneOf(policy.getDisplayAreas(bar))));

        assertThat(ime,
        assertThat(mImeContainer,
                is(decendantOfOneOf(policy.getDisplayAreas(foo))));
        assertThat(ime,
        assertThat(mImeContainer,
                is(decendantOfOneOf(policy.getDisplayAreas(bar))));

        List<DisplayArea<?>> actualOrder = collectLeafAreas(root);
        Map<DisplayArea<?>, Set<Integer>> zSets = calculateZSets(policy, root, ime,
                taskDisplayArea);
        List<DisplayArea<?>> actualOrder = collectLeafAreas(mRoot);
        Map<DisplayArea<?>, Set<Integer>> zSets = calculateZSets(policy, mRoot, mImeContainer,
                mDefaultTaskDisplayArea);
        actualOrder = actualOrder.stream().filter(zSets::containsKey).collect(toList());

        Map<DisplayArea<?>, Integer> expectedByMinLayer = mapValues(zSets,
@@ -131,20 +148,11 @@ public class DisplayAreaPolicyBuilderTest {

    @Test
    public void testBuilder_defaultPolicy_hasOneHandedFeature() {
        WindowManagerService wms = mSystemServices.getWindowManagerService();
        DisplayArea.Root root = new SurfacelessDisplayAreaRoot(wms);
        DisplayArea<WindowContainer> ime = new DisplayArea<>(wms, ABOVE_TASKS, "Ime");
        DisplayContent displayContent = mock(DisplayContent.class);
        TaskDisplayArea taskDisplayArea = new TaskDisplayArea(displayContent, wms, "Tasks",
                FEATURE_DEFAULT_TASK_CONTAINER);
        List<TaskDisplayArea> taskDisplayAreaList = new ArrayList<>();
        taskDisplayAreaList.add(taskDisplayArea);

        final DisplayAreaPolicy.Provider defaultProvider = DisplayAreaPolicy.Provider.fromResources(
                resourcesWithProvider(""));
        final DisplayAreaPolicyBuilder.Result defaultPolicy =
                (DisplayAreaPolicyBuilder.Result) defaultProvider.instantiate(wms, displayContent,
                        root, ime);
                (DisplayAreaPolicyBuilder.Result) defaultProvider.instantiate(mWms, mDisplayContent,
                        mRoot, mImeContainer);
        final List<Feature> features = defaultPolicy.getFeatures();
        boolean hasOneHandedFeature = false;
        for (int i = 0; i < features.size(); i++) {
@@ -154,6 +162,34 @@ public class DisplayAreaPolicyBuilderTest {
        assertTrue(hasOneHandedFeature);
    }

    @Test
    public void testBuilder_createCustomizedDisplayAreaForFeature() {
        final Feature dimmable;
        final Feature other;
        DisplayAreaPolicyBuilder.Result policy = new DisplayAreaPolicyBuilder()
                .addFeature(dimmable = new Feature.Builder(mPolicy, "Dimmable", 0)
                        .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
                        .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
                        .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new)
                        .build())
                .addFeature(other = new Feature.Builder(mPolicy, "Other", 1)
                        .all()
                        .build())
                .build(mWms, mDisplayContent, mRoot, mImeContainer, mTaskDisplayAreaList);

        policy.attachDisplayAreas();

        List<DisplayArea<? extends WindowContainer>> dimmableDAs =
                policy.getDisplayAreas(dimmable.getId());
        List<DisplayArea<? extends WindowContainer>> otherDAs =
                policy.getDisplayAreas(other.getId());
        assertEquals(1, dimmableDAs.size());
        assertTrue(dimmableDAs.get(0) instanceof DisplayArea.Dimmable);
        for (DisplayArea otherDA : otherDAs) {
            assertFalse(otherDA instanceof DisplayArea.Dimmable);
        }
    }

    private static Resources resourcesWithProvider(String provider) {
        Resources mock = mock(Resources.class);
        when(mock.getString(