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

Commit b182d2ed authored by Daniel Akinola's avatar Daniel Akinola Committed by Android (Google) Code Review
Browse files

Merge "[3/n] Update DisplayManager to persist display connection preference" into main

parents 83c614ab c06bf77b
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -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
     */
@@ -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
+23 −0
Original line number Diff line number Diff line
@@ -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
     */
+19 −0
Original line number Diff line number Diff line
@@ -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.
     */
+7 −0
Original line number Diff line number Diff line
@@ -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);
+47 −1
Original line number Diff line number Diff line
@@ -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
@@ -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 {
@@ -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