diff options
4 files changed, 95 insertions, 0 deletions
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index c01a8a95e021..c735b2712aed 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3183,6 +3183,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 diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a3d5be79cad2..cbdf5a1ecb1b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -425,6 +425,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" /> diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 0570b2ab510b..34d59d86bead 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -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)) { @@ -1395,6 +1400,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) { diff --git a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java index 120cc84193cd..0dd645587cc7 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -250,6 +250,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 { @@ -314,6 +342,42 @@ public class LocalDisplayAdapterTest { } /** + * 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. */ @Test |