Loading core/java/android/hardware/display/DisplayManager.java +65 −0 Original line number Diff line number Diff line Loading @@ -593,6 +593,46 @@ public final class DisplayManager { @TestApi public static final int SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY = 3; /** * Default value for {@link ExternalDisplayConnection}. * No saved connection preference, so always show a dialog to ask the user when connecting this * external display. * @hide */ public static final int EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_ASK = 0; /** * Value for {@link ExternalDisplayConnection}. * Automatically enable desktop mode when connecting this external display. * @hide */ public static final int EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_DESKTOP = 1; /** * Value for {@link ExternalDisplayConnection}. * Automatically enable mirroring when connecting this external display. * @hide */ public static final int EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_MIRROR = 2; /** * Constants representing user options for external display connection. Each display can * have a unique connection preference, so there is no settings key, instead a displays's * unique id is the key, with one of the values below as the value. Default value is * {@link #EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_ASK}, which shows a dialog, allowing users * to then select a preference between desktop, mirroring or continually showing the dialog. * * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_" }, value = { EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_ASK, EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_DESKTOP, EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_MIRROR, }) public @interface ExternalDisplayConnection { } /** * @hide */ Loading Loading @@ -1649,6 +1689,31 @@ public final class DisplayManager { return mGlobal.getMinimumBrightnessCurve(); } /** * Sets the persistent connection preference for a given display. * * @param uniqueId The unique ID of the display. * @param connectionPreference The integer preference value to save. * * @hide */ @RequiresPermission(MANAGE_DISPLAYS) public void setExternalDisplayConnectionPreference(String uniqueId, int connectionPreference) { mGlobal.setExternalDisplayConnectionPreference(uniqueId, connectionPreference); } /** * Gets the persistent connection preference for a given display. * * @param uniqueId The unique ID of the display. * @return The saved integer preference value. * * @hide */ public int getExternalDisplayConnectionPreference(String uniqueId) { return mGlobal.getExternalDisplayConnectionPreference(uniqueId); } /** * Sets the global default {@link Display.Mode}. The display mode includes preference for * resolution and refresh rate. The mode change is applied globally, i.e. to all the connected Loading core/java/android/hardware/display/DisplayManagerGlobal.java +23 −0 Original line number Diff line number Diff line Loading @@ -1453,6 +1453,29 @@ public final class DisplayManagerGlobal { } } /** * @see DisplayManager#setExternalDisplayConnectionPreference(String, int) */ @RequiresPermission(MANAGE_DISPLAYS) public void setExternalDisplayConnectionPreference(String uniqueId, int connectionPreference) { try { mDm.setConnectionPreference(uniqueId, connectionPreference); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * @see DisplayManager#getExternalDisplayConnectionPreference(String) */ public int getExternalDisplayConnectionPreference(String uniqueId) { try { return mDm.getConnectionPreference(uniqueId); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * @see DisplayManager#getDisplayTopology */ Loading core/java/android/hardware/display/DisplayManagerInternal.java +19 −0 Original line number Diff line number Diff line Loading @@ -366,6 +366,25 @@ public abstract class DisplayManagerInternal { */ public abstract void ignoreProximitySensorUntilChanged(); /** * Sets the persistent connection preference for a given display. This preference * determines whether to show a dialog, mirror, or use desktop mode automatically. * * @param uniqueId The unique ID of the display. * @param preference The integer constant for the new preference to save. * @hide */ public abstract void setConnectionPreference(String uniqueId, int preference); /** * Retrieves the saved connection preference for a given display. * * @param uniqueId The unique ID of the display. * @return The integer constant for the saved preference. * @hide */ public abstract int getConnectionPreference(String uniqueId); /** * Returns the refresh rate switching type. */ Loading core/java/android/hardware/display/IDisplayManager.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -253,6 +253,13 @@ interface IDisplayManager { @EnforcePermission("MANAGE_DISPLAYS") boolean requestDisplayPower(int displayId, int state); // Sets the connection preference for external display. @EnforcePermission("MANAGE_DISPLAYS") void setConnectionPreference(String uniqueId, int preference); // Returns the saved connection preference for external display. int getConnectionPreference(String uniqueId); // Restricts display modes to specified modeIds. @EnforcePermission("RESTRICT_DISPLAY_MODES") void requestDisplayModes(in IBinder token, int displayId, in @nullable int[] modeIds); Loading packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt +47 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import androidx.test.filters.SmallTest import com.android.app.displaylib.DisplayDecorationListener import com.android.app.displaylib.DisplayRepository.PendingDisplay import com.android.app.displaylib.DisplaysWithDecorationsRepositoryCompat import com.android.app.displaylib.ExternalDisplayConnectionType import com.android.server.display.feature.flags.Flags.FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.FlowValue Loading Loading @@ -256,6 +257,51 @@ class DisplayRepositoryTest : SysuiTestCase() { verify(displayManager).enableConnectedDisplay(eq(1)) } @Test fun onPendingDisplay_propagatesCorrectConnectionPreference() = testScope.runTest { val testDisplayId = 42 val testConnectionType = ExternalDisplayConnectionType.MIRROR val pendingDisplay by lastPendingDisplay() whenever(displayManager.getExternalDisplayConnectionPreference(any())) .thenReturn(testConnectionType.preference) sendOnDisplayConnected(testDisplayId) assertThat(pendingDisplay).isNotNull() assertThat(pendingDisplay!!.id).isEqualTo(testDisplayId) assertThat(pendingDisplay!!.connectionType).isEqualTo(testConnectionType) } @Test fun onPendingDisplay_displayIdNotCached_findsUsingDisplayManager() = testScope.runTest { val pendingDisplay by lastPendingDisplay() val displayId = 123 val mockDisplay = display(id = displayId, type = TYPE_EXTERNAL) whenever(displayManager.getDisplay(eq(displayId))).thenReturn(mockDisplay) connectedDisplayListener.value.onDisplayConnected(displayId) verify(displayManager, times(2)).getDisplay(displayId) assertThat(pendingDisplay).isNotNull() assertThat(pendingDisplay!!.id).isEqualTo(displayId) } @Test fun onPendingDisplay_displayIdDoesNotExist_returnNull() = testScope.runTest { val pendingDisplay by lastPendingDisplay() val testDisplayId = 99 whenever(displayManager.getDisplay(eq(testDisplayId))).thenReturn(null) connectedDisplayListener.value.onDisplayConnected(testDisplayId) verify(displayManager).getDisplay(testDisplayId) assertThat(pendingDisplay).isNull() } @Test fun onPendingDisplay_enableBySysui_disabledBySomeoneElse_pendingDisplayStillIgnored() = testScope.runTest { Loading Loading @@ -440,7 +486,7 @@ class DisplayRepositoryTest : SysuiTestCase() { val pendingDisplay by lastPendingDisplay() sendOnDisplayConnected(1, TYPE_EXTERNAL) sendOnDisplayConnected(2, Display.TYPE_INTERNAL) sendOnDisplayConnected(2, TYPE_INTERNAL) assertThat(pendingDisplay!!.id).isEqualTo(1) } Loading Loading
core/java/android/hardware/display/DisplayManager.java +65 −0 Original line number Diff line number Diff line Loading @@ -593,6 +593,46 @@ public final class DisplayManager { @TestApi public static final int SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY = 3; /** * Default value for {@link ExternalDisplayConnection}. * No saved connection preference, so always show a dialog to ask the user when connecting this * external display. * @hide */ public static final int EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_ASK = 0; /** * Value for {@link ExternalDisplayConnection}. * Automatically enable desktop mode when connecting this external display. * @hide */ public static final int EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_DESKTOP = 1; /** * Value for {@link ExternalDisplayConnection}. * Automatically enable mirroring when connecting this external display. * @hide */ public static final int EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_MIRROR = 2; /** * Constants representing user options for external display connection. Each display can * have a unique connection preference, so there is no settings key, instead a displays's * unique id is the key, with one of the values below as the value. Default value is * {@link #EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_ASK}, which shows a dialog, allowing users * to then select a preference between desktop, mirroring or continually showing the dialog. * * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_" }, value = { EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_ASK, EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_DESKTOP, EXTERNAL_DISPLAY_CONNECTION_PREFERENCE_MIRROR, }) public @interface ExternalDisplayConnection { } /** * @hide */ Loading Loading @@ -1649,6 +1689,31 @@ public final class DisplayManager { return mGlobal.getMinimumBrightnessCurve(); } /** * Sets the persistent connection preference for a given display. * * @param uniqueId The unique ID of the display. * @param connectionPreference The integer preference value to save. * * @hide */ @RequiresPermission(MANAGE_DISPLAYS) public void setExternalDisplayConnectionPreference(String uniqueId, int connectionPreference) { mGlobal.setExternalDisplayConnectionPreference(uniqueId, connectionPreference); } /** * Gets the persistent connection preference for a given display. * * @param uniqueId The unique ID of the display. * @return The saved integer preference value. * * @hide */ public int getExternalDisplayConnectionPreference(String uniqueId) { return mGlobal.getExternalDisplayConnectionPreference(uniqueId); } /** * Sets the global default {@link Display.Mode}. The display mode includes preference for * resolution and refresh rate. The mode change is applied globally, i.e. to all the connected Loading
core/java/android/hardware/display/DisplayManagerGlobal.java +23 −0 Original line number Diff line number Diff line Loading @@ -1453,6 +1453,29 @@ public final class DisplayManagerGlobal { } } /** * @see DisplayManager#setExternalDisplayConnectionPreference(String, int) */ @RequiresPermission(MANAGE_DISPLAYS) public void setExternalDisplayConnectionPreference(String uniqueId, int connectionPreference) { try { mDm.setConnectionPreference(uniqueId, connectionPreference); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * @see DisplayManager#getExternalDisplayConnectionPreference(String) */ public int getExternalDisplayConnectionPreference(String uniqueId) { try { return mDm.getConnectionPreference(uniqueId); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * @see DisplayManager#getDisplayTopology */ Loading
core/java/android/hardware/display/DisplayManagerInternal.java +19 −0 Original line number Diff line number Diff line Loading @@ -366,6 +366,25 @@ public abstract class DisplayManagerInternal { */ public abstract void ignoreProximitySensorUntilChanged(); /** * Sets the persistent connection preference for a given display. This preference * determines whether to show a dialog, mirror, or use desktop mode automatically. * * @param uniqueId The unique ID of the display. * @param preference The integer constant for the new preference to save. * @hide */ public abstract void setConnectionPreference(String uniqueId, int preference); /** * Retrieves the saved connection preference for a given display. * * @param uniqueId The unique ID of the display. * @return The integer constant for the saved preference. * @hide */ public abstract int getConnectionPreference(String uniqueId); /** * Returns the refresh rate switching type. */ Loading
core/java/android/hardware/display/IDisplayManager.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -253,6 +253,13 @@ interface IDisplayManager { @EnforcePermission("MANAGE_DISPLAYS") boolean requestDisplayPower(int displayId, int state); // Sets the connection preference for external display. @EnforcePermission("MANAGE_DISPLAYS") void setConnectionPreference(String uniqueId, int preference); // Returns the saved connection preference for external display. int getConnectionPreference(String uniqueId); // Restricts display modes to specified modeIds. @EnforcePermission("RESTRICT_DISPLAY_MODES") void requestDisplayModes(in IBinder token, int displayId, in @nullable int[] modeIds); Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt +47 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import androidx.test.filters.SmallTest import com.android.app.displaylib.DisplayDecorationListener import com.android.app.displaylib.DisplayRepository.PendingDisplay import com.android.app.displaylib.DisplaysWithDecorationsRepositoryCompat import com.android.app.displaylib.ExternalDisplayConnectionType import com.android.server.display.feature.flags.Flags.FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.FlowValue Loading Loading @@ -256,6 +257,51 @@ class DisplayRepositoryTest : SysuiTestCase() { verify(displayManager).enableConnectedDisplay(eq(1)) } @Test fun onPendingDisplay_propagatesCorrectConnectionPreference() = testScope.runTest { val testDisplayId = 42 val testConnectionType = ExternalDisplayConnectionType.MIRROR val pendingDisplay by lastPendingDisplay() whenever(displayManager.getExternalDisplayConnectionPreference(any())) .thenReturn(testConnectionType.preference) sendOnDisplayConnected(testDisplayId) assertThat(pendingDisplay).isNotNull() assertThat(pendingDisplay!!.id).isEqualTo(testDisplayId) assertThat(pendingDisplay!!.connectionType).isEqualTo(testConnectionType) } @Test fun onPendingDisplay_displayIdNotCached_findsUsingDisplayManager() = testScope.runTest { val pendingDisplay by lastPendingDisplay() val displayId = 123 val mockDisplay = display(id = displayId, type = TYPE_EXTERNAL) whenever(displayManager.getDisplay(eq(displayId))).thenReturn(mockDisplay) connectedDisplayListener.value.onDisplayConnected(displayId) verify(displayManager, times(2)).getDisplay(displayId) assertThat(pendingDisplay).isNotNull() assertThat(pendingDisplay!!.id).isEqualTo(displayId) } @Test fun onPendingDisplay_displayIdDoesNotExist_returnNull() = testScope.runTest { val pendingDisplay by lastPendingDisplay() val testDisplayId = 99 whenever(displayManager.getDisplay(eq(testDisplayId))).thenReturn(null) connectedDisplayListener.value.onDisplayConnected(testDisplayId) verify(displayManager).getDisplay(testDisplayId) assertThat(pendingDisplay).isNull() } @Test fun onPendingDisplay_enableBySysui_disabledBySomeoneElse_pendingDisplayStillIgnored() = testScope.runTest { Loading Loading @@ -440,7 +486,7 @@ class DisplayRepositoryTest : SysuiTestCase() { val pendingDisplay by lastPendingDisplay() sendOnDisplayConnected(1, TYPE_EXTERNAL) sendOnDisplayConnected(2, Display.TYPE_INTERNAL) sendOnDisplayConnected(2, TYPE_INTERNAL) assertThat(pendingDisplay!!.id).isEqualTo(1) } Loading