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

Commit b109bcf4 authored by Piotr Wilczyński's avatar Piotr Wilczyński
Browse files

Fix adding displays to topology

- display should be internal, external or overlay
- if internal, it has to be the default display
- if external or overlay, extended displays need to be enabled
- display should be in default display group

Bug: 384013689
Test: DisplayManagerServiceTest, DisplayTopologyCoordinatorTest
Flag: com.android.server.display.feature.flags.display_topology
Change-Id: I05250c7a3a91bb0df54c17f5fa9db2860963549b
parent 9fa76bd1
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -250,8 +250,29 @@ class DisplayTopologyCoordinator {
    }

    private boolean isDisplayAllowedInTopology(DisplayInfo info) {
        return mIsExtendedDisplayEnabled.getAsBoolean()
                && info.displayGroupId == Display.DEFAULT_DISPLAY_GROUP;
        if (info.type != Display.TYPE_INTERNAL && info.type != Display.TYPE_EXTERNAL
                && info.type != Display.TYPE_OVERLAY) {
            Slog.d(TAG, "Display " + info.displayId + " not allowed in topology because "
                    + "type is not INTERNAL, EXTERNAL or OVERLAY");
            return false;
        }
        if (info.type == Display.TYPE_INTERNAL && info.displayId != Display.DEFAULT_DISPLAY) {
            Slog.d(TAG, "Display " + info.displayId + " not allowed in topology because "
                    + "it is a non-default internal display");
            return false;
        }
        if ((info.type == Display.TYPE_EXTERNAL || info.type == Display.TYPE_OVERLAY)
                && !mIsExtendedDisplayEnabled.getAsBoolean()) {
            Slog.d(TAG, "Display " + info.displayId + " not allowed in topology because "
                    + "type is EXTERNAL or OVERLAY and !mIsExtendedDisplayEnabled");
            return false;
        }
        if (info.displayGroupId != Display.DEFAULT_DISPLAY_GROUP) {
            Slog.d(TAG, "Display " + info.displayId + " not allowed in topology because "
                    + "it is not in the default display group");
            return false;
        }
        return true;
    }

    /**
+162 −8
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ class DisplayTopologyCoordinatorTest {
            info.logicalWidth = i * 300
            info.logicalHeight = i * 200
            info.logicalDensityDpi = i * 100
            info.type = Display.TYPE_EXTERNAL
            return@map info
        }

@@ -115,7 +116,98 @@ class DisplayTopologyCoordinatorTest {
    }

    @Test
    fun addDisplay_extendedDisplaysDisabled() {
    fun addDisplay_internal() {
        displayInfos[0].displayId = Display.DEFAULT_DISPLAY
        displayInfos[0].type = Display.TYPE_INTERNAL
        coordinator.onDisplayAdded(displayInfos[0])

        val widthDp =
            pxToDp(displayInfos[0].logicalWidth.toFloat(), displayInfos[0].logicalDensityDpi)
        val heightDp =
            pxToDp(displayInfos[0].logicalHeight.toFloat(), displayInfos[0].logicalDensityDpi)
        verify(mockTopology).addDisplay(displayInfos[0].displayId, widthDp, heightDp)
        verify(mockTopologyChangedCallback).invoke(
            android.util.Pair(
                mockTopologyCopy,
                mockTopologyGraph
            )
        )
    }

    @Test
    fun addDisplay_overlay() {
        displayInfos[0].type = Display.TYPE_OVERLAY
        coordinator.onDisplayAdded(displayInfos[0])

        val widthDp =
            pxToDp(displayInfos[0].logicalWidth.toFloat(), displayInfos[0].logicalDensityDpi)
        val heightDp =
            pxToDp(displayInfos[0].logicalHeight.toFloat(), displayInfos[0].logicalDensityDpi)
        verify(mockTopology).addDisplay(displayInfos[0].displayId, widthDp, heightDp)
        verify(mockTopologyChangedCallback).invoke(
            android.util.Pair(
                mockTopologyCopy,
                mockTopologyGraph
            )
        )
    }

    @Test
    fun addDisplay_typeUnknown() {
        displayInfos[0].type = Display.TYPE_UNKNOWN

        coordinator.onDisplayAdded(displayInfos[0])

        verify(mockTopology, never()).addDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyChangedCallback, never()).invoke(any())
    }

    @Test
    fun addDisplay_wifi() {
        displayInfos[0].type = Display.TYPE_WIFI

        coordinator.onDisplayAdded(displayInfos[0])

        verify(mockTopology, never()).addDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyChangedCallback, never()).invoke(any())
    }

    @Test
    fun addDisplay_virtual() {
        displayInfos[0].type = Display.TYPE_VIRTUAL

        coordinator.onDisplayAdded(displayInfos[0])

        verify(mockTopology, never()).addDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyChangedCallback, never()).invoke(any())
    }

    @Test
    fun addDisplay_internal_nonDefault() {
        displayInfos[0].displayId = 2
        displayInfos[0].type = Display.TYPE_INTERNAL

        coordinator.onDisplayAdded(displayInfos[0])

        verify(mockTopology, never()).addDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyChangedCallback, never()).invoke(any())
    }

    @Test
    fun addDisplay_external_extendedDisplaysDisabled() {
        whenever(mockIsExtendedDisplayEnabled()).thenReturn(false)

        for (displayInfo in displayInfos) {
            coordinator.onDisplayAdded(displayInfo)
        }

        verify(mockTopology, never()).addDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyChangedCallback, never()).invoke(any())
    }

    @Test
    fun addDisplay_overlay_extendedDisplaysDisabled() {
        displayInfos[0].type = Display.TYPE_OVERLAY
        whenever(mockIsExtendedDisplayEnabled()).thenReturn(false)

        for (displayInfo in displayInfos) {
@@ -144,9 +236,16 @@ class DisplayTopologyCoordinatorTest {
            .thenReturn(true)
        addDisplay()

        displayInfos[0].logicalDensityDpi += 10
        displayInfos[0].logicalWidth += 100
        displayInfos[0].logicalHeight += 100
        coordinator.onDisplayChanged(displayInfos[0])

        val widthDp =
            pxToDp(displayInfos[0].logicalWidth.toFloat(), displayInfos[0].logicalDensityDpi)
        val heightDp =
            pxToDp(displayInfos[0].logicalHeight.toFloat(), displayInfos[0].logicalDensityDpi)
        verify(mockTopology).updateDisplay(displayInfos[0].displayId, widthDp, heightDp)

        val captor = ArgumentCaptor.forClass(SparseIntArray::class.java)
        verify(mockTopologyCopy).getGraph(captor.capture())
        val densities = captor.value
@@ -180,11 +279,56 @@ class DisplayTopologyCoordinatorTest {
    }

    @Test
    fun updateDisplay_extendedDisplaysDisabled() {
    fun updateDisplay_typeUnknown() {
        displayInfos[0].type = Display.TYPE_UNKNOWN

        coordinator.onDisplayChanged(displayInfos[0])

        verify(mockTopology, never()).updateDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyCopy, never()).getGraph(any())
        verify(mockTopologyChangedCallback, never()).invoke(any())
    }

    @Test
    fun updateDisplay_wifi() {
        displayInfos[0].type = Display.TYPE_WIFI

        coordinator.onDisplayChanged(displayInfos[0])

        verify(mockTopology, never()).updateDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyCopy, never()).getGraph(any())
        verify(mockTopologyChangedCallback, never()).invoke(any())
    }

    @Test
    fun updateDisplay_virtual() {
        displayInfos[0].type = Display.TYPE_VIRTUAL

        coordinator.onDisplayChanged(displayInfos[0])

        verify(mockTopology, never()).updateDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyCopy, never()).getGraph(any())
        verify(mockTopologyChangedCallback, never()).invoke(any())
    }

    @Test
    fun updateDisplay_internal_nonDefault() {
        displayInfos[0].displayId = 2
        displayInfos[0].type = Display.TYPE_INTERNAL

        coordinator.onDisplayChanged(displayInfos[0])

        verify(mockTopology, never()).updateDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyCopy, never()).getGraph(any())
        verify(mockTopologyChangedCallback, never()).invoke(any())
    }

    @Test
    fun updateDisplay_external_extendedDisplaysDisabled() {
        whenever(mockIsExtendedDisplayEnabled()).thenReturn(false)

        for (displayInfo in displayInfos) {
            coordinator.onDisplayAdded(displayInfo)
            coordinator.onDisplayChanged(displayInfo)
        }

        verify(mockTopology, never()).updateDisplay(anyInt(), anyFloat(), anyFloat())
@@ -192,11 +336,23 @@ class DisplayTopologyCoordinatorTest {
        verify(mockTopologyChangedCallback, never()).invoke(any())
    }

    @Test
    fun updateDisplay_overlay_extendedDisplaysDisabled() {
        displayInfos[0].type = Display.TYPE_OVERLAY
        whenever(mockIsExtendedDisplayEnabled()).thenReturn(false)

        coordinator.onDisplayChanged(displayInfos[0])

        verify(mockTopology, never()).updateDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyChangedCallback, never()).invoke(any())
        verify(mockTopologyStore, never()).restoreTopology(any())
    }

    @Test
    fun updateDisplay_notInDefaultDisplayGroup() {
        displayInfos[0].displayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1

        coordinator.onDisplayAdded(displayInfos[0])
        coordinator.onDisplayChanged(displayInfos[0])

        verify(mockTopology, never()).updateDisplay(anyInt(), anyFloat(), anyFloat())
        verify(mockTopologyCopy, never()).getGraph(any())
@@ -233,9 +389,7 @@ class DisplayTopologyCoordinatorTest {

    @Test
    fun removeDisplay_notChanged() {
        for (displayInfo in displayInfos) {
            coordinator.onDisplayRemoved(displayInfo.displayId)
        }
        coordinator.onDisplayRemoved(100)

        verify(mockTopologyChangedCallback, never()).invoke(any())
        verify(mockTopologyStore, never()).restoreTopology(any())