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

Commit 96127463 authored by Marin Shalamanov's avatar Marin Shalamanov Committed by Automerger Merge Worker
Browse files

Merge "Invalidate desiredDisplayModeSpecs when SF specs are invalid" into sc-dev am: 82dae092

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13563465

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: If133b1b7025444f5f9d3ce78682ee3f8ba2b8d6e
parents 5f48b7a8 82dae092
Loading
Loading
Loading
Loading
+96 −30
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ import android.view.DisplayEventReceiver;
import android.view.RoundedCorners;
import android.view.RoundedCorners;
import android.view.SurfaceControl;
import android.view.SurfaceControl;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledLambda;
@@ -72,6 +73,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {


    private final Injector mInjector;
    private final Injector mInjector;


    private final SurfaceControlProxy mSurfaceControlProxy;


    // Called with SyncRoot lock held.
    // Called with SyncRoot lock held.
    public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
    public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
@@ -79,10 +81,12 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        this(syncRoot, context, handler, listener, new Injector());
        this(syncRoot, context, handler, listener, new Injector());
    }
    }


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


    @Override
    @Override
@@ -92,22 +96,23 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        mInjector.setDisplayEventListenerLocked(getHandler().getLooper(),
        mInjector.setDisplayEventListenerLocked(getHandler().getLooper(),
                new LocalDisplayEventListener());
                new LocalDisplayEventListener());


        for (long physicalDisplayId : SurfaceControl.getPhysicalDisplayIds()) {
        for (long physicalDisplayId : mSurfaceControlProxy.getPhysicalDisplayIds()) {
            tryConnectDisplayLocked(physicalDisplayId);
            tryConnectDisplayLocked(physicalDisplayId);
        }
        }
    }
    }


    private void tryConnectDisplayLocked(long physicalDisplayId) {
    private void tryConnectDisplayLocked(long physicalDisplayId) {
        final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(physicalDisplayId);
        final IBinder displayToken =
                mSurfaceControlProxy.getPhysicalDisplayToken(physicalDisplayId);
        if (displayToken != null) {
        if (displayToken != null) {
            SurfaceControl.StaticDisplayInfo staticInfo =
            SurfaceControl.StaticDisplayInfo staticInfo =
                    SurfaceControl.getStaticDisplayInfo(displayToken);
                    mSurfaceControlProxy.getStaticDisplayInfo(displayToken);
            if (staticInfo == null) {
            if (staticInfo == null) {
                Slog.w(TAG, "No valid static info found for display device " + physicalDisplayId);
                Slog.w(TAG, "No valid static info found for display device " + physicalDisplayId);
                return;
                return;
            }
            }
            SurfaceControl.DynamicDisplayInfo dynamicInfo =
            SurfaceControl.DynamicDisplayInfo dynamicInfo =
                    SurfaceControl.getDynamicDisplayInfo(displayToken);
                    mSurfaceControlProxy.getDynamicDisplayInfo(displayToken);
            if (dynamicInfo == null) {
            if (dynamicInfo == null) {
                Slog.w(TAG, "No valid dynamic info found for display device " + physicalDisplayId);
                Slog.w(TAG, "No valid dynamic info found for display device " + physicalDisplayId);
                return;
                return;
@@ -131,7 +136,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                dynamicInfo.activeColorMode = Display.COLOR_MODE_INVALID;
                dynamicInfo.activeColorMode = Display.COLOR_MODE_INVALID;
            }
            }
            SurfaceControl.DesiredDisplayModeSpecs modeSpecs =
            SurfaceControl.DesiredDisplayModeSpecs modeSpecs =
                    SurfaceControl.getDesiredDisplayModeSpecs(displayToken);
                    mSurfaceControlProxy.getDesiredDisplayModeSpecs(displayToken);
            LocalDisplayDevice device = mDevices.get(physicalDisplayId);
            LocalDisplayDevice device = mDevices.get(physicalDisplayId);
            if (device == null) {
            if (device == null) {
                // Display was added.
                // Display was added.
@@ -222,7 +227,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            mIsDefaultDisplay = isDefaultDisplay;
            mIsDefaultDisplay = isDefaultDisplay;
            updateDisplayPropertiesLocked(staticDisplayInfo, dynamicInfo, modeSpecs);
            updateDisplayPropertiesLocked(staticDisplayInfo, dynamicInfo, modeSpecs);
            mSidekickInternal = LocalServices.getService(SidekickInternal.class);
            mSidekickInternal = LocalServices.getService(SidekickInternal.class);
            mBacklightAdapter = new BacklightAdapter(displayToken, isDefaultDisplay);
            mBacklightAdapter = new BacklightAdapter(displayToken, isDefaultDisplay,
                    mSurfaceControlProxy);
            mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
            mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
            mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken);
            mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken);
            mDisplayDeviceConfig = null;
            mDisplayDeviceConfig = null;
@@ -338,8 +344,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                // If we can't map the defaultMode index to a mode, then the physical display
                // If we can't map the defaultMode index to a mode, then the physical display
                // modes must have changed, and the code below for handling changes to the
                // modes must have changed, and the code below for handling changes to the
                // list of available modes will take care of updating display mode specs.
                // list of available modes will take care of updating display mode specs.
                if (activeBaseMode != NO_DISPLAY_MODE_ID) {
                if (activeBaseMode == NO_DISPLAY_MODE_ID
                    if (mDisplayModeSpecs.baseModeId != activeBaseMode
                        || mDisplayModeSpecs.baseModeId != activeBaseMode
                        || mDisplayModeSpecs.primaryRefreshRateRange.min
                        || mDisplayModeSpecs.primaryRefreshRateRange.min
                                != modeSpecs.primaryRefreshRateMin
                                != modeSpecs.primaryRefreshRateMin
                        || mDisplayModeSpecs.primaryRefreshRateRange.max
                        || mDisplayModeSpecs.primaryRefreshRateRange.max
@@ -352,7 +358,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                    sendTraversalRequestLocked();
                    sendTraversalRequestLocked();
                }
                }
            }
            }
            }


            boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
            boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
            // If the records haven't changed then we're done here.
            // If the records haven't changed then we're done here.
@@ -757,7 +762,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                                + "id=" + physicalDisplayId
                                + "id=" + physicalDisplayId
                                + ", state=" + Display.stateToString(state) + ")");
                                + ", state=" + Display.stateToString(state) + ")");
                        try {
                        try {
                            SurfaceControl.setDisplayPowerMode(token, mode);
                            mSurfaceControlProxy.setDisplayPowerMode(token, mode);
                            Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
                            Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
                        } finally {
                        } finally {
                            Trace.traceEnd(Trace.TRACE_TAG_POWER);
                            Trace.traceEnd(Trace.TRACE_TAG_POWER);
@@ -885,9 +890,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
                SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
            // Do not lock when calling these SurfaceControl methods because they are sync
            // Do not lock when calling these SurfaceControl methods because they are sync
            // operations that may block for a while when setting display power mode.
            // operations that may block for a while when setting display power mode.
            SurfaceControl.setDesiredDisplayModeSpecs(displayToken, modeSpecs);
            mSurfaceControlProxy.setDesiredDisplayModeSpecs(displayToken, modeSpecs);
            final int sfActiveModeId =

                    SurfaceControl.getDynamicDisplayInfo(displayToken).activeDisplayModeId;
            final int sfActiveModeId = mSurfaceControlProxy
                    .getDynamicDisplayInfo(displayToken).activeDisplayModeId;
            synchronized (getSyncRoot()) {
            synchronized (getSyncRoot()) {
                if (updateActiveModeLocked(sfActiveModeId)) {
                if (updateActiveModeLocked(sfActiveModeId)) {
                    updateDeviceInfoLocked();
                    updateDeviceInfoLocked();
@@ -955,7 +961,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        private void requestColorModeAsync(IBinder displayToken, int colorMode) {
        private void requestColorModeAsync(IBinder displayToken, int colorMode) {
            // Do not lock when calling this SurfaceControl method because it is a sync operation
            // Do not lock when calling this SurfaceControl method because it is a sync operation
            // that may block for a while when setting display power mode.
            // that may block for a while when setting display power mode.
            SurfaceControl.setActiveColorMode(displayToken, colorMode);
            mSurfaceControlProxy.setActiveColorMode(displayToken, colorMode);
            synchronized (getSyncRoot()) {
            synchronized (getSyncRoot()) {
                updateDeviceInfoLocked();
                updateDeviceInfoLocked();
            }
            }
@@ -975,7 +981,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                return;
                return;
            }
            }


            SurfaceControl.setAutoLowLatencyMode(getDisplayTokenLocked(), on);
            mSurfaceControlProxy.setAutoLowLatencyMode(getDisplayTokenLocked(), on);
        }
        }


        @Override
        @Override
@@ -992,7 +998,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                return;
                return;
            }
            }


            SurfaceControl.setGameContentType(getDisplayTokenLocked(), on);
            mSurfaceControlProxy.setGameContentType(getDisplayTokenLocked(), on);
        }
        }


        @Override
        @Override
@@ -1136,6 +1142,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        public void setDisplayEventListenerLocked(Looper looper, DisplayEventListener listener) {
        public void setDisplayEventListenerLocked(Looper looper, DisplayEventListener listener) {
            mReceiver = new ProxyDisplayEventReceiver(looper, listener);
            mReceiver = new ProxyDisplayEventReceiver(looper, listener);
        }
        }
        public SurfaceControlProxy getSurfaceControlProxy() {
            return new SurfaceControlProxy();
        }
    }
    }


    public interface DisplayEventListener {
    public interface DisplayEventListener {
@@ -1227,10 +1236,65 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        }
        }
    }
    }


    @VisibleForTesting
    static class SurfaceControlProxy {
        public SurfaceControl.DynamicDisplayInfo getDynamicDisplayInfo(IBinder token) {
            return SurfaceControl.getDynamicDisplayInfo(token);
        }

        public long[] getPhysicalDisplayIds() {
            return SurfaceControl.getPhysicalDisplayIds();
        }

        public IBinder getPhysicalDisplayToken(long physicalDisplayId) {
            return SurfaceControl.getPhysicalDisplayToken(physicalDisplayId);
        }

        public SurfaceControl.StaticDisplayInfo getStaticDisplayInfo(IBinder displayToken) {
            return SurfaceControl.getStaticDisplayInfo(displayToken);
        }

        public SurfaceControl.DesiredDisplayModeSpecs getDesiredDisplayModeSpecs(
                IBinder displayToken) {
            return SurfaceControl.getDesiredDisplayModeSpecs(displayToken);
        }

        public boolean setDesiredDisplayModeSpecs(IBinder token,
                SurfaceControl.DesiredDisplayModeSpecs specs) {
            return SurfaceControl.setDesiredDisplayModeSpecs(token, specs);
        }

        public void setDisplayPowerMode(IBinder displayToken, int mode) {
            SurfaceControl.setDisplayPowerMode(displayToken, mode);
        }

        public boolean setActiveColorMode(IBinder displayToken, int colorMode) {
            return SurfaceControl.setActiveColorMode(displayToken, colorMode);
        }

        public void setAutoLowLatencyMode(IBinder displayToken, boolean on) {
            SurfaceControl.setAutoLowLatencyMode(displayToken, on);

        }

        public void setGameContentType(IBinder displayToken, boolean on) {
            SurfaceControl.setGameContentType(displayToken, on);
        }

        public boolean getDisplayBrightnessSupport(IBinder displayToken) {
            return SurfaceControl.getDisplayBrightnessSupport(displayToken);
        }

        public boolean setDisplayBrightness(IBinder displayToken, float brightness) {
            return SurfaceControl.setDisplayBrightness(displayToken, brightness);
        }
    }

    static class BacklightAdapter {
    static class BacklightAdapter {
        private final IBinder mDisplayToken;
        private final IBinder mDisplayToken;
        private final LogicalLight mBacklight;
        private final LogicalLight mBacklight;
        private final boolean mUseSurfaceControlBrightness;
        private final boolean mUseSurfaceControlBrightness;
        private final SurfaceControlProxy mSurfaceControlProxy;


        private boolean mForceSurfaceControl = false;
        private boolean mForceSurfaceControl = false;


@@ -1238,11 +1302,13 @@ final class LocalDisplayAdapter extends DisplayAdapter {
         * @param displayToken Token for display associated with this backlight.
         * @param displayToken Token for display associated with this backlight.
         * @param isDefaultDisplay {@code true} if it is the default display.
         * @param isDefaultDisplay {@code true} if it is the default display.
         */
         */
        BacklightAdapter(IBinder displayToken, boolean isDefaultDisplay) {
        BacklightAdapter(IBinder displayToken, boolean isDefaultDisplay,
                SurfaceControlProxy surfaceControlProxy) {
            mDisplayToken = displayToken;
            mDisplayToken = displayToken;
            mSurfaceControlProxy = surfaceControlProxy;


            mUseSurfaceControlBrightness =
            mUseSurfaceControlBrightness = mSurfaceControlProxy
                    SurfaceControl.getDisplayBrightnessSupport(mDisplayToken);
                    .getDisplayBrightnessSupport(mDisplayToken);


            if (!mUseSurfaceControlBrightness && isDefaultDisplay) {
            if (!mUseSurfaceControlBrightness && isDefaultDisplay) {
                LightsManager lights = LocalServices.getService(LightsManager.class);
                LightsManager lights = LocalServices.getService(LightsManager.class);
@@ -1254,7 +1320,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {


        void setBrightness(float brightness) {
        void setBrightness(float brightness) {
            if (mUseSurfaceControlBrightness || mForceSurfaceControl) {
            if (mUseSurfaceControlBrightness || mForceSurfaceControl) {
                SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
                mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, brightness);
            } else if (mBacklight != null) {
            } else if (mBacklight != null) {
                mBacklight.setBrightness(brightness);
                mBacklight.setBrightness(brightness);
            }
            }
+93 −21
Original line number Original line Diff line number Diff line
@@ -25,8 +25,10 @@ import static com.google.common.truth.Truth.assertThat;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.when;


import android.content.Context;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources;
@@ -94,11 +96,13 @@ public class LocalDisplayAdapterTest {


    private Injector mInjector;
    private Injector mInjector;


    @Mock
    private LocalDisplayAdapter.SurfaceControlProxy mSurfaceControlProxy;

    @Before
    @Before
    public void setUp() throws Exception {
    public void setUp() throws Exception {
        mMockitoSession = mockitoSession()
        mMockitoSession = mockitoSession()
                .initMocks(this)
                .initMocks(this)
                .mockStatic(SurfaceControl.class)
                .strictness(Strictness.LENIENT)
                .strictness(Strictness.LENIENT)
                .startMocking();
                .startMocking();
        mHandler = new Handler(Looper.getMainLooper());
        mHandler = new Handler(Looper.getMainLooper());
@@ -227,6 +231,7 @@ public class LocalDisplayAdapterTest {
        setUpDisplay(display);
        setUpDisplay(display);
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        assertTrue(mListener.traversalRequested);
        assertThat(mListener.changedDisplays.size()).isGreaterThan(0);
        assertThat(mListener.changedDisplays.size()).isGreaterThan(0);


        // Verify the supported modes are updated accordingly.
        // Verify the supported modes are updated accordingly.
@@ -333,6 +338,7 @@ public class LocalDisplayAdapterTest {
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);


        assertTrue(mListener.traversalRequested);
        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        assertThat(mListener.changedDisplays.size()).isEqualTo(1);
        assertThat(mListener.changedDisplays.size()).isEqualTo(1);


@@ -380,6 +386,7 @@ public class LocalDisplayAdapterTest {
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);


        assertTrue(mListener.traversalRequested);
        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        assertThat(mListener.changedDisplays.size()).isEqualTo(1);
        assertThat(mListener.changedDisplays.size()).isEqualTo(1);


@@ -418,6 +425,7 @@ public class LocalDisplayAdapterTest {
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);


        assertTrue(mListener.traversalRequested);
        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        assertThat(mListener.changedDisplays.size()).isEqualTo(1);
        assertThat(mListener.changedDisplays.size()).isEqualTo(1);


@@ -454,6 +462,7 @@ public class LocalDisplayAdapterTest {
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);


        assertTrue(mListener.traversalRequested);
        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        assertThat(mListener.changedDisplays.size()).isEqualTo(1);
        assertThat(mListener.changedDisplays.size()).isEqualTo(1);


@@ -480,6 +489,30 @@ public class LocalDisplayAdapterTest {
        mAdapter.registerLocked();
        mAdapter.registerLocked();
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);


        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        DisplayDevice displayDevice = mListener.addedDisplays.get(0);

        int baseModeId = Arrays.stream(displayDevice.getDisplayDeviceInfoLocked().supportedModes)
                .filter(mode -> mode.getRefreshRate() == 60f)
                .findFirst()
                .get()
                .getModeId();

        displayDevice.setDesiredDisplayModeSpecsLocked(
                new DisplayModeDirector.DesiredDisplayModeSpecs(
                        /*baseModeId*/ baseModeId,
                        /*allowGroupSwitching*/ false,
                        new DisplayModeDirector.RefreshRateRange(60f, 60f),
                        new DisplayModeDirector.RefreshRateRange(60f, 60f)
                ));
        verify(mSurfaceControlProxy).setDesiredDisplayModeSpecs(display.token,
                new SurfaceControl.DesiredDisplayModeSpecs(
                        /* baseModeId */ 0,
                        /* allowGroupSwitching */ false,
                        /* primaryRange */ 60f, 60f,
                        /* appRange */ 60f, 60f
                ));

        // Change the display
        // Change the display
        display.dynamicInfo.supportedDisplayModes = new SurfaceControl.DisplayMode[]{
        display.dynamicInfo.supportedDisplayModes = new SurfaceControl.DisplayMode[]{
                createFakeDisplayMode(2, 1920, 1080, 60f)
                createFakeDisplayMode(2, 1920, 1080, 60f)
@@ -489,36 +522,64 @@ public class LocalDisplayAdapterTest {
        display.desiredDisplayModeSpecs.defaultMode = 1;
        display.desiredDisplayModeSpecs.defaultMode = 1;


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

        assertTrue(mListener.traversalRequested);

        displayDevice.applyPendingDisplayDeviceInfoChangesLocked();

        baseModeId = displayDevice.getDisplayDeviceInfoLocked().supportedModes[0].getModeId();

        // The traversal request will call setDesiredDisplayModeSpecsLocked on the display device
        displayDevice.setDesiredDisplayModeSpecsLocked(
                new DisplayModeDirector.DesiredDisplayModeSpecs(
                        /*baseModeId*/ baseModeId,
                        /*allowGroupSwitching*/ false,
                        new DisplayModeDirector.RefreshRateRange(60f, 60f),
                        new DisplayModeDirector.RefreshRateRange(60f, 60f)
                ));

        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);

        // Verify that this will reapply the desired modes.
        verify(mSurfaceControlProxy).setDesiredDisplayModeSpecs(display.token,
                new SurfaceControl.DesiredDisplayModeSpecs(
                        /* baseModeId */ 2,
                        /* allowGroupSwitching */ false,
                        /* primaryRange */ 60f, 60f,
                        /* appRange */ 60f, 60f
                ));
    }
    }


    @Test
    @Test
    public void testBacklightAdapter_withSurfaceControlSupport() {
    public void testBacklightAdapter_withSurfaceControlSupport() {
        final Binder displayToken = new Binder();
        final Binder displayToken = new Binder();
        doReturn(true).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));

        when(mSurfaceControlProxy.getDisplayBrightnessSupport(displayToken)).thenReturn(true);


        // Test as default display
        // Test as default display
        BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/);
        BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
                mSurfaceControlProxy);
        ba.setBrightness(0.514f);
        ba.setBrightness(0.514f);
        verify(() -> SurfaceControl.setDisplayBrightness(displayToken, 0.514f));
        verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.514f);


        // Test as not default display
        // Test as not default display
        BacklightAdapter ba2 = new BacklightAdapter(displayToken,
        BacklightAdapter ba2 = new BacklightAdapter(displayToken, false /*isDefault*/,
                false /*isDefault*/);
                mSurfaceControlProxy);
        ba2.setBrightness(0.323f);
        ba2.setBrightness(0.323f);
        verify(() -> SurfaceControl.setDisplayBrightness(displayToken, 0.323f));
        verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.323f);
    }
    }


    @Test
    @Test
    public void testBacklightAdapter_withoutSourceControlSupport_defaultDisplay() {
    public void testBacklightAdapter_withoutSourceControlSupport_defaultDisplay() {
        final Binder displayToken = new Binder();
        final Binder displayToken = new Binder();
        doReturn(false).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
        when(mSurfaceControlProxy.getDisplayBrightnessSupport(displayToken)).thenReturn(false);
        doReturn(mMockedBacklight).when(mMockedLightsManager)
        doReturn(mMockedBacklight).when(mMockedLightsManager)
                .getLight(LightsManager.LIGHT_ID_BACKLIGHT);
                .getLight(LightsManager.LIGHT_ID_BACKLIGHT);


        BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/);
        BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
                mSurfaceControlProxy);
        ba.setBrightness(0.123f);
        ba.setBrightness(0.123f);
        verify(mMockedBacklight).setBrightness(0.123f);
        verify(mMockedBacklight).setBrightness(0.123f);
    }
    }
@@ -526,11 +587,12 @@ public class LocalDisplayAdapterTest {
    @Test
    @Test
    public void testBacklightAdapter_withoutSourceControlSupport_nonDefaultDisplay() {
    public void testBacklightAdapter_withoutSourceControlSupport_nonDefaultDisplay() {
        final Binder displayToken = new Binder();
        final Binder displayToken = new Binder();
        doReturn(false).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
        when(mSurfaceControlProxy.getDisplayBrightnessSupport(displayToken)).thenReturn(false);
        doReturn(mMockedBacklight).when(mMockedLightsManager)
        doReturn(mMockedBacklight).when(mMockedLightsManager)
                .getLight(LightsManager.LIGHT_ID_BACKLIGHT);
                .getLight(LightsManager.LIGHT_ID_BACKLIGHT);


        BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/);
        BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/,
                mSurfaceControlProxy);
        ba.setBrightness(0.456f);
        ba.setBrightness(0.456f);


        // Adapter does not forward any brightness in this case.
        // Adapter does not forward any brightness in this case.
@@ -618,13 +680,14 @@ public class LocalDisplayAdapterTest {


    private void setUpDisplay(FakeDisplay display) {
    private void setUpDisplay(FakeDisplay display) {
        mAddresses.add(display.address);
        mAddresses.add(display.address);
        doReturn(display.token).when(() ->
        when(mSurfaceControlProxy.getPhysicalDisplayToken(display.address.getPhysicalDisplayId()))
                SurfaceControl.getPhysicalDisplayToken(display.address.getPhysicalDisplayId()));
                .thenReturn(display.token);
        doReturn(display.info).when(() -> SurfaceControl.getStaticDisplayInfo(display.token));
        when(mSurfaceControlProxy.getStaticDisplayInfo(display.token))
        doReturn(display.dynamicInfo).when(
                .thenReturn(display.info);
                () -> SurfaceControl.getDynamicDisplayInfo(display.token));
        when(mSurfaceControlProxy.getDynamicDisplayInfo(display.token))
        doReturn(display.desiredDisplayModeSpecs)
                .thenReturn(display.dynamicInfo);
                .when(() -> SurfaceControl.getDesiredDisplayModeSpecs(display.token));
        when(mSurfaceControlProxy.getDesiredDisplayModeSpecs(display.token))
                .thenReturn(display.desiredDisplayModeSpecs);
    }
    }


    private void updateAvailableDisplays() {
    private void updateAvailableDisplays() {
@@ -634,7 +697,7 @@ public class LocalDisplayAdapterTest {
            ids[i] = address.getPhysicalDisplayId();
            ids[i] = address.getPhysicalDisplayId();
            i++;
            i++;
        }
        }
        doReturn(ids).when(() -> SurfaceControl.getPhysicalDisplayIds());
        when(mSurfaceControlProxy.getPhysicalDisplayIds()).thenReturn(ids);
    }
    }


    private static DisplayAddress.Physical createDisplayAddress(int port) {
    private static DisplayAddress.Physical createDisplayAddress(int port) {
@@ -649,7 +712,7 @@ public class LocalDisplayAdapterTest {


    private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
    private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
            float refreshRate) {
            float refreshRate) {
        return createFakeDisplayMode(id, width, height, refreshRate, 0);
        return createFakeDisplayMode(id, width, height, refreshRate, /* group */ 0);
    }
    }


    private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
    private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
@@ -702,14 +765,21 @@ public class LocalDisplayAdapterTest {
                LocalDisplayAdapter.DisplayEventListener listener) {
                LocalDisplayAdapter.DisplayEventListener listener) {
            mTransmitter = new HotplugTransmitter(looper, listener);
            mTransmitter = new HotplugTransmitter(looper, listener);
        }
        }

        public HotplugTransmitter getTransmitter() {
        public HotplugTransmitter getTransmitter() {
            return mTransmitter;
            return mTransmitter;
        }
        }

        @Override
        public LocalDisplayAdapter.SurfaceControlProxy getSurfaceControlProxy() {
            return mSurfaceControlProxy;
        }
    }
    }


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


        @Override
        @Override
        public void onDisplayDeviceEvent(DisplayDevice device, int event) {
        public void onDisplayDeviceEvent(DisplayDevice device, int event) {
@@ -722,6 +792,8 @@ public class LocalDisplayAdapterTest {


        @Override
        @Override
        public void onTraversalRequested() {
        public void onTraversalRequested() {
            traversalRequested = true;
        }
        }
    }
    }

}
}