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

Commit 48fb9161 authored by Carsten Rohn's avatar Carsten Rohn
Browse files

allow configuring no focus steal for local display



The FLAG_STEAL_TOP_FOCUS_DISABLED flag prevents secondary displays
to steal focus from other displays. This flag can currently be only
set to virtual displays.

This flag replaces and extends the perDisplayFocus flag since A14,
which before was responsible to set a focus per display and prevented
the display to get focus on directed key input - this has been
removed with A14.

As an OEM developer I want to enable local physical displays to
get the FLAG_STEAL_TOP_FOCUS_DISABLED as well to be able to replace
the former perDisplayFocus functionality and to prevent it from
ever getting top focus.

Bug: 374954685
Test: DisplayServiceTests_server_display
Change-Id: I4ca9dc2af7eae08c4642b34c89deec56ed1f3d58
Signed-off-by: default avatarCarsten Rohn <carsten.rohn@bmw.de>
parent 485c0d62
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -3180,6 +3180,14 @@
         as private. {@see android.view.Display#FLAG_PRIVATE} -->
    <integer-array translatable="false" name="config_localPrivateDisplayPorts"></integer-array>

    <!-- Controls if local secondary displays should be able to steal focus and become top display.
         Value specified in the array represents physical port address of each display and displays
         in this list due to flag dependencies will be marked with the following flags:
         {@see android.view.Display#FLAG_STEAL_TOP_FOCUS_DISABLED}
         {@see android.view.Display#FLAG_OWN_FOCUS} -->
    <integer-array translatable="false" name="config_localNotStealTopFocusDisplayPorts">
    </integer-array>

    <!-- The default mode for the default display. One of the following values (See Display.java):
             0 - COLOR_MODE_DEFAULT
             7 - COLOR_MODE_SRGB
+1 −0
Original line number Diff line number Diff line
@@ -424,6 +424,7 @@
  <java-symbol type="bool" name="config_enableProximityService" />
  <java-symbol type="bool" name="config_enableVirtualDeviceManager" />
  <java-symbol type="array" name="config_localPrivateDisplayPorts" />
  <java-symbol type="array" name="config_localNotStealTopFocusDisplayPorts" />
  <java-symbol type="integer" name="config_defaultDisplayDefaultColorMode" />
  <java-symbol type="bool" name="config_enableAppWidgetService" />
  <java-symbol type="dimen" name="config_pictureInPictureMinAspectRatio" />
+22 −0
Original line number Diff line number Diff line
@@ -725,6 +725,11 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                    if (isDisplayPrivate(physicalAddress)) {
                        mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE;
                    }

                    if (isDisplayStealTopFocusDisabled(physicalAddress)) {
                        mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_FOCUS;
                        mInfo.flags |= DisplayDeviceInfo.FLAG_STEAL_TOP_FOCUS_DISABLED;
                    }
                }

                if (DisplayCutout.getMaskBuiltInDisplayCutout(res, mInfo.uniqueId)) {
@@ -1392,6 +1397,23 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            }
            return false;
        }

        private boolean isDisplayStealTopFocusDisabled(DisplayAddress.Physical physicalAddress) {
            if (physicalAddress == null) {
                return false;
            }
            final Resources res = getOverlayContext().getResources();
            int[] ports = res.getIntArray(R.array.config_localNotStealTopFocusDisplayPorts);
            if (ports != null) {
                int port = physicalAddress.getPort();
                for (int p : ports) {
                    if (p == port) {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    private boolean hdrTypesEqual(int[] modeHdrTypes, int[] recordHdrTypes) {
+64 −0
Original line number Diff line number Diff line
@@ -252,6 +252,34 @@ public class LocalDisplayAdapterTest {
                PORT_C, false);
    }

    /**
     * Confirm that display is marked as trusted, has own focus, disables steal top focus when it
     * is listed in com.android.internal.R.array.config_localNotStealTopFocusDisplayPorts.
     */
    @Test
    public void testStealTopFocusDisabledDisplay() throws Exception {
        setUpDisplay(new FakeDisplay(PORT_A));
        setUpDisplay(new FakeDisplay(PORT_B));
        setUpDisplay(new FakeDisplay(PORT_C));
        updateAvailableDisplays();

        doReturn(new int[]{ PORT_B }).when(mMockedResources).getIntArray(
                com.android.internal.R.array.config_localNotStealTopFocusDisplayPorts);
        mAdapter.registerLocked();

        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);

        // This should not have the flags
        assertNotStealTopFocusFlag(mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked(),
                PORT_A, false);
        // This should have the flags
        assertNotStealTopFocusFlag(mListener.addedDisplays.get(1).getDisplayDeviceInfoLocked(),
                PORT_B, true);
        // This should not have the flags
        assertNotStealTopFocusFlag(mListener.addedDisplays.get(2).getDisplayDeviceInfoLocked(),
                PORT_C, false);
    }

    @Test
    public void testSupportedDisplayModesGetOverriddenWhenDisplayIsUpdated()
            throws InterruptedException {
@@ -315,6 +343,42 @@ public class LocalDisplayAdapterTest {
        assertEquals(shouldBePrivate, (info.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0);
    }

    /**
     * Confirm that all local displays are not trusted, do not have their own focus, and do not
     * steal top focus when config_localNotStealTopFocusDisplayPorts is empty:
     */
    @Test
    public void testDisplayFlagsForNoConfigLocalNotStealTopFocusDisplayPorts() throws Exception {
        setUpDisplay(new FakeDisplay(PORT_A));
        setUpDisplay(new FakeDisplay(PORT_C));
        updateAvailableDisplays();

        // config_localNotStealTopFocusDisplayPorts is null
        mAdapter.registerLocked();

        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);

        // This should not have the flags
        assertNotStealTopFocusFlag(mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked(),
                PORT_A, false);
        // This should not have the flags
        assertNotStealTopFocusFlag(mListener.addedDisplays.get(1).getDisplayDeviceInfoLocked(),
                PORT_C, false);
    }

    private static void assertNotStealTopFocusFlag(
            DisplayDeviceInfo info, int expectedPort, boolean shouldHaveFlags) {
        final DisplayAddress.Physical address = (DisplayAddress.Physical) info.address;
        assertNotNull(address);
        assertEquals(expectedPort, address.getPort());
        assertEquals(DISPLAY_MODEL, address.getModel());
        assertEquals(shouldHaveFlags,
                (info.flags & DisplayDeviceInfo.FLAG_STEAL_TOP_FOCUS_DISABLED) != 0);
        assertEquals(shouldHaveFlags, (info.flags & DisplayDeviceInfo.FLAG_OWN_FOCUS) != 0);
        // display is always trusted since it is created by the system
        assertEquals(true, (info.flags & DisplayDeviceInfo.FLAG_TRUSTED) != 0);
    }

    /**
     * Confirm that external display uses physical density.
     */