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

Commit 55d4d2e8 authored by Marin Shalamanov's avatar Marin Shalamanov Committed by Android (Google) Code Review
Browse files

Merge "LocalDisplayAdapter test for stale DesiredDisplayConfigSpecs"

parents e1833c6c 2fb51ba0
Loading
Loading
Loading
Loading
+33 −8
Original line number Diff line number Diff line
@@ -69,21 +69,27 @@ final class LocalDisplayAdapter extends DisplayAdapter {

    private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();

    @SuppressWarnings("unused")  // Becomes active at instantiation time.
    private PhysicalDisplayEventReceiver mPhysicalDisplayEventReceiver;
    private final Injector mInjector;


    // Called with SyncRoot lock held.
    public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
            Context context, Handler handler, Listener listener) {
        this(syncRoot, context, handler, listener, new Injector());
    }

    LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
            Context context, Handler handler, Listener listener, Injector injector) {
        super(syncRoot, context, handler, listener, TAG);
        mInjector = injector;
    }

    @Override
    public void registerLocked() {
        super.registerLocked();

        mPhysicalDisplayEventReceiver = new PhysicalDisplayEventReceiver(getHandler().getLooper());
        mInjector.setDisplayEventListenerLocked(getHandler().getLooper(),
                new LocalDisplayEventListener());

        for (long physicalDisplayId : SurfaceControl.getPhysicalDisplayIds()) {
            tryConnectDisplayLocked(physicalDisplayId);
@@ -1052,12 +1058,33 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        }
    }

    private final class PhysicalDisplayEventReceiver extends DisplayEventReceiver {
        PhysicalDisplayEventReceiver(Looper looper) {
    public static class Injector {
        private ProxyDisplayEventReceiver mReceiver;
        public void setDisplayEventListenerLocked(Looper looper, DisplayEventListener listener) {
            mReceiver = new ProxyDisplayEventReceiver(looper, listener);
        }
    }

    public interface DisplayEventListener {
        void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected);
        void onConfigChanged(long timestampNanos, long physicalDisplayId, int configId);
    }

    public static final class ProxyDisplayEventReceiver extends DisplayEventReceiver {
        private final DisplayEventListener mListener;
        ProxyDisplayEventReceiver(Looper looper, DisplayEventListener listener) {
            super(looper, VSYNC_SOURCE_APP, CONFIG_CHANGED_EVENT_DISPATCH);
            mListener = listener;
        }
        public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
            mListener.onHotplug(timestampNanos, physicalDisplayId, connected);
        }
        public void onConfigChanged(long timestampNanos, long physicalDisplayId, int configId) {
            mListener.onConfigChanged(timestampNanos, physicalDisplayId, configId);
        }
    }

        @Override
    private final class LocalDisplayEventListener implements DisplayEventListener {
        public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
            synchronized (getSyncRoot()) {
                if (connected) {
@@ -1067,8 +1094,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                }
            }
        }

        @Override
        public void onConfigChanged(long timestampNanos, long physicalDisplayId, int configId) {
            if (DEBUG) {
                Slog.d(TAG, "onConfigChanged("
+69 −6
Original line number Diff line number Diff line
@@ -83,6 +83,8 @@ public class LocalDisplayAdapterTest {

    private LinkedList<DisplayAddress.Physical> mAddresses = new LinkedList<>();

    private Injector mInjector;

    @Before
    public void setUp() throws Exception {
        mMockitoSession = mockitoSession()
@@ -94,8 +96,9 @@ public class LocalDisplayAdapterTest {
        doReturn(mMockedResources).when(mMockedContext).getResources();
        LocalServices.removeServiceForTest(LightsManager.class);
        LocalServices.addService(LightsManager.class, mMockedLightsManager);
        mInjector = new Injector();
        mAdapter = new LocalDisplayAdapter(mMockedSyncRoot, mMockedContext, mHandler,
                mListener);
                mListener, mInjector);
        spyOn(mAdapter);
        doReturn(mMockedContext).when(mAdapter).getOverlayContext();
    }
@@ -222,7 +225,7 @@ public class LocalDisplayAdapterTest {
        display.configs = configs;
        display.activeConfig = 1;
        setUpDisplay(display);
        mAdapter.registerLocked();
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);

        assertThat(SurfaceControl.getActiveConfig(display.token)).isEqualTo(1);
@@ -272,7 +275,7 @@ public class LocalDisplayAdapterTest {
                new int[Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS], 1000, 1000, 0);
        display.hdrCapabilities = changedHdrCapabilities;
        setUpDisplay(display);
        mAdapter.registerLocked();
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);

        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
@@ -308,7 +311,7 @@ public class LocalDisplayAdapterTest {
        final int[] changedColorModes = new int[]{Display.COLOR_MODE_DEFAULT};
        display.colorModes = changedColorModes;
        setUpDisplay(display);
        mAdapter.registerLocked();
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);

        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
@@ -322,6 +325,35 @@ public class LocalDisplayAdapterTest {
        assertThat(displayDeviceInfo.supportedColorModes).isEqualTo(changedColorModes);
    }

    @Test
    public void testDisplayChange_withStaleDesiredDisplayConfigSpecs() throws Exception {
        SurfaceControl.DisplayConfig[] configs = new SurfaceControl.DisplayConfig[]{
                createFakeDisplayConfig(1920, 1080, 60f),
                createFakeDisplayConfig(1920, 1080, 50f)
        };
        final int activeConfig = 0;
        FakeDisplay display = new FakeDisplay(PORT_A, configs, activeConfig);
        display.desiredDisplayConfigSpecs.defaultConfig = 1;

        setUpDisplay(display);
        updateAvailableDisplays();
        mAdapter.registerLocked();
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);

        // Change the display
        display.configs = new SurfaceControl.DisplayConfig[]{
                createFakeDisplayConfig(1920, 1080, 60f)
        };
        // SurfaceFlinger can return a stale defaultConfig. Make sure this doesn't
        // trigger ArrayOutOfBoundsException.
        display.desiredDisplayConfigSpecs.defaultConfig = 1;

        setUpDisplay(display);
        updateAvailableDisplays();
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
    }

    private void assertDisplayDpi(DisplayDeviceInfo info, int expectedPort,
                                  float expectedXdpi,
                                  float expectedYDpi,
@@ -356,6 +388,8 @@ public class LocalDisplayAdapterTest {
        public int[] colorModes = new int[]{ Display.COLOR_MODE_DEFAULT };
        public Display.HdrCapabilities hdrCapabilities = new Display.HdrCapabilities(new int[0],
                1000, 1000, 0);
        public SurfaceControl.DesiredDisplayConfigSpecs desiredDisplayConfigSpecs =
                new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f, 60.f, 60.f);

        private FakeDisplay(int port) {
            this.address = createDisplayAddress(port);
@@ -387,7 +421,7 @@ public class LocalDisplayAdapterTest {
                () -> SurfaceControl.getDisplayColorModes(display.token));
        doReturn(display.hdrCapabilities).when(
                () -> SurfaceControl.getHdrCapabilities(display.token));
        doReturn(new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f, 60.f, 60.f))
        doReturn(display.desiredDisplayConfigSpecs)
                .when(() -> SurfaceControl.getDesiredDisplayConfigSpecs(display.token));
    }

@@ -422,7 +456,7 @@ public class LocalDisplayAdapterTest {
        return config;
    }

    private void waitForHandlerToComplete(Handler handler, long waitTimeMs)
    private static void waitForHandlerToComplete(Handler handler, long waitTimeMs)
            throws InterruptedException {
        final Object lock = new Object();
        synchronized (lock) {
@@ -435,6 +469,35 @@ public class LocalDisplayAdapterTest {
        }
    }

    private class HotplugTransmitter {
        private final Handler mHandler;
        private final LocalDisplayAdapter.DisplayEventListener mListener;

        HotplugTransmitter(Looper looper, LocalDisplayAdapter.DisplayEventListener listener) {
            mHandler = new Handler(looper);
            mListener = listener;
        }

        public void sendHotplug(FakeDisplay display, boolean connected)
                throws InterruptedException {
            mHandler.post(() -> mListener.onHotplug(/* timestampNanos = */ 0,
                    display.address.getPhysicalDisplayId(), connected));
            waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        }
    }

    private class Injector extends LocalDisplayAdapter.Injector {
        private HotplugTransmitter mTransmitter;
        @Override
        public void setDisplayEventListenerLocked(Looper looper,
                LocalDisplayAdapter.DisplayEventListener listener) {
            mTransmitter = new HotplugTransmitter(looper, listener);
        }
        public HotplugTransmitter getTransmitter() {
            return mTransmitter;
        }
    }

    private class TestListener implements DisplayAdapter.Listener {
        public ArrayList<DisplayDevice> addedDisplays = new ArrayList<>();
        public ArrayList<DisplayDevice> changedDisplays = new ArrayList<>();