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

Commit f55a43e0 authored by Orhan Uysal's avatar Orhan Uysal
Browse files

Create sysprop to disable connected display dialog.

Add a system property to enable an external display on connection
instead of disabling it. This will cause the UI dialog to not show up
when an external display is connected.

Test: Manual
Test: atest DisplayManagerServiceTest
Bug: 306178462
Change-Id: I06187462287566a9f4e5a1296b511577014d843f
parent 6a482df3
Loading
Loading
Loading
Loading
+11 −2
Original line number Original line Diff line number Diff line
@@ -102,6 +102,7 @@ import android.media.projection.IMediaProjection;
import android.media.projection.IMediaProjectionManager;
import android.media.projection.IMediaProjectionManager;
import android.net.Uri;
import android.net.Uri;
import android.os.Binder;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.IBinder;
@@ -239,6 +240,10 @@ public final class DisplayManagerService extends SystemService {
    private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
    private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";


    private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top";
    private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top";

    @VisibleForTesting
    static final String ENABLE_ON_CONNECT =
            "persist.sys.display.enable_on_connect.external";
    private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
    private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
    // This value needs to be in sync with the threshold
    // This value needs to be in sync with the threshold
    // in RefreshRateConfigs::getFrameRateDivisor.
    // in RefreshRateConfigs::getFrameRateDivisor.
@@ -1942,11 +1947,15 @@ public final class DisplayManagerService extends SystemService {
        }
        }


        setupLogicalDisplay(display);
        setupLogicalDisplay(display);

        // TODO(b/292196201) Remove when the display can be disabled before DPC is created.
        // TODO(b/292196201) Remove when the display can be disabled before DPC is created.
        if (display.getDisplayInfoLocked().type == Display.TYPE_EXTERNAL) {
        if (display.getDisplayInfoLocked().type == Display.TYPE_EXTERNAL) {
            if ((Build.IS_ENG || Build.IS_USERDEBUG)
                    && SystemProperties.getBoolean(ENABLE_ON_CONNECT, false)) {
                Slog.w(TAG, "External display is enabled by default, bypassing user consent.");
            } else {
                display.setEnabledLocked(false);
                display.setEnabledLocked(false);
            }
            }
        }


        sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED);
        sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED);


+47 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,8 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESE
import static android.view.ContentRecordingSession.RECORD_CONTENT_DISPLAY;
import static android.view.ContentRecordingSession.RECORD_CONTENT_DISPLAY;
import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK;
import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK;


import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.server.display.DisplayManagerService.ENABLE_ON_CONNECT;
import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;


import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertThat;
@@ -90,12 +92,14 @@ import android.hardware.display.VirtualDisplayConfig;
import android.media.projection.IMediaProjection;
import android.media.projection.IMediaProjection;
import android.media.projection.IMediaProjectionManager;
import android.media.projection.IMediaProjectionManager;
import android.os.Binder;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Looper;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.MessageQueue;
import android.os.Process;
import android.os.Process;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.platform.test.flag.junit.SetFlagsRule;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.ContentRecordingSession;
import android.view.ContentRecordingSession;
import android.view.Display;
import android.view.Display;
@@ -113,6 +117,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.runner.AndroidJUnit4;


import com.android.internal.R;
import com.android.internal.R;
import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.server.LocalServices;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemService;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
@@ -130,6 +135,7 @@ import com.google.common.truth.Expect;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;


import org.junit.Assume;
import org.junit.Before;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Test;
@@ -141,6 +147,8 @@ import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations;
import org.mockito.quality.Strictness;
import org.mockito.stubbing.Answer;


import java.time.Duration;
import java.time.Duration;
import java.util.ArrayList;
import java.util.ArrayList;
@@ -322,6 +330,12 @@ public class DisplayManagerServiceTest {
    @Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
    @Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
    @Mock DisplayManagerFlags mMockFlags;
    @Mock DisplayManagerFlags mMockFlags;


    @Rule
    public final ExtendedMockitoRule mExtendedMockitoRule =
            new ExtendedMockitoRule.Builder(this)
                    .setStrictness(Strictness.LENIENT)
                    .spyStatic(SystemProperties.class)
                    .build();
    @Before
    @Before
    public void setUp() throws Exception {
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        MockitoAnnotations.initMocks(this);
@@ -2405,6 +2419,39 @@ public class DisplayManagerServiceTest {
                EVENT_DISPLAY_CONNECTED).inOrder();
                EVENT_DISPLAY_CONNECTED).inOrder();
    }
    }


    @Test
    public void testConnectExternalDisplay_withDisplayManagementAndSysprop_shouldEnableDisplay() {
        Assume.assumeTrue(Build.IS_ENG || Build.IS_USERDEBUG);
        when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
        doAnswer((Answer<Boolean>) invocationOnMock -> true)
                .when(() -> SystemProperties.getBoolean(ENABLE_ON_CONNECT, false));
        manageDisplaysPermission(/* granted= */ true);
        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
        DisplayManagerInternal localService = displayManager.new LocalService();
        DisplayManagerService.BinderService bs = displayManager.new BinderService();
        LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
        FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
        bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
        localService.registerDisplayGroupListener(callback);
        callback.expectsEvent(EVENT_DISPLAY_ADDED);

        // Create default display device
        createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
        callback.waitForExpectedEvent();
        callback.clear();

        callback.expectsEvent(EVENT_DISPLAY_CONNECTED);
        FakeDisplayDevice displayDevice =
                createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
        callback.waitForExpectedEvent();

        LogicalDisplay display =
                logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ false);
        assertThat(display.isEnabledLocked()).isTrue();
        assertThat(callback.receivedEvents()).containsExactly(DISPLAY_GROUP_EVENT_ADDED,
                EVENT_DISPLAY_CONNECTED, EVENT_DISPLAY_ADDED).inOrder();
    }

    @Test
    @Test
    public void testConnectInternalDisplay_withDisplayManagement_shouldConnectAndAddDisplay() {
    public void testConnectInternalDisplay_withDisplayManagement_shouldConnectAndAddDisplay() {
        when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
        when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);