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

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

Merge "Update default and active mode when new modes are added."

parents 0e2e3d80 cdf7bb6c
Loading
Loading
Loading
Loading
+4 −14
Original line number Diff line number Diff line
@@ -109,24 +109,14 @@ abstract class DisplayAdapter {
     */
    protected final void sendDisplayDeviceEventLocked(
            final DisplayDevice device, final int event) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mListener.onDisplayDeviceEvent(device, event);
            }
        });
        mHandler.post(() -> mListener.onDisplayDeviceEvent(device, event));
    }

    /**
     * Sends a request to perform traversals.
     */
    protected final void sendTraversalRequestLocked() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mListener.onTraversalRequested();
            }
        });
        mHandler.post(() -> mListener.onTraversalRequested());
    }

    public static Display.Mode createMode(int width, int height, float refreshRate) {
@@ -135,7 +125,7 @@ abstract class DisplayAdapter {
    }

    public interface Listener {
        public void onDisplayDeviceEvent(DisplayDevice device, int event);
        public void onTraversalRequested();
        void onDisplayDeviceEvent(DisplayDevice device, int event);
        void onTraversalRequested();
    }
}
+39 −28
Original line number Diff line number Diff line
@@ -65,8 +65,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {

    private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";

    private final LongSparseArray<LocalDisplayDevice> mDevices =
            new LongSparseArray<LocalDisplayDevice>();
    private static final int NO_DISPLAY_MODE_ID = 0;

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

    @SuppressWarnings("unused")  // Becomes active at instantiation time.
    private PhysicalDisplayEventReceiver mPhysicalDisplayEventReceiver;
@@ -133,15 +134,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                        hdrCapabilities, isInternal);
                mDevices.put(physicalDisplayId, device);
                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
            } else {
                boolean changed = device.updateDisplayConfigsLocked(configs, activeConfig,
                        configSpecs);
                changed |= device.updateColorModesLocked(colorModes, activeColorMode);
                changed |= device.updateHdrCapabilitiesLocked(hdrCapabilities);
                if (changed) {
            } else if (device.updateDisplayProperties(configs, activeConfig,
                    configSpecs, colorModes, activeColorMode, hdrCapabilities)) {
                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
            }
            }
        } else {
            // The display is no longer available. Ignore the attempt to add it.
            // If it was connected but has already been disconnected, we'll get a
@@ -215,10 +211,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            mPhysicalDisplayId = physicalDisplayId;
            mIsInternal = isInternal;
            mDisplayInfo = info;

            updateDisplayConfigsLocked(configs, activeConfigId, configSpecs);
            updateColorModesLocked(colorModes, activeColorMode);
            updateHdrCapabilitiesLocked(hdrCapabilities);
            updateDisplayProperties(configs, activeConfigId, configSpecs, colorModes,
                    activeColorMode, hdrCapabilities);
            mSidekickInternal = LocalServices.getService(SidekickInternal.class);
            if (mIsInternal) {
                LightsManager lights = LocalServices.getService(LightsManager.class);
@@ -240,13 +234,25 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            return true;
        }

        /**
         * Returns true if there is a change.
         **/
        public boolean updateDisplayProperties(SurfaceControl.DisplayConfig[] configs,
                int activeConfigId, SurfaceControl.DesiredDisplayConfigSpecs configSpecs,
                int[] colorModes, int activeColorMode, Display.HdrCapabilities hdrCapabilities) {
            boolean changed = updateDisplayConfigsLocked(configs, activeConfigId, configSpecs);
            changed |= updateColorModesLocked(colorModes, activeColorMode);
            changed |= updateHdrCapabilitiesLocked(hdrCapabilities);
            return changed;
        }

        public boolean updateDisplayConfigsLocked(
                SurfaceControl.DisplayConfig[] configs, int activeConfigId,
                SurfaceControl.DesiredDisplayConfigSpecs configSpecs) {
            mDisplayConfigs = Arrays.copyOf(configs, configs.length);
            mActiveConfigId = activeConfigId;
            // Build an updated list of all existing modes.
            ArrayList<DisplayModeRecord> records = new ArrayList<DisplayModeRecord>();
            ArrayList<DisplayModeRecord> records = new ArrayList<>();
            boolean modesAdded = false;
            for (int i = 0; i < configs.length; i++) {
                SurfaceControl.DisplayConfig config = configs[i];
@@ -286,7 +292,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {

            // Check whether surface flinger spontaneously changed modes out from under us.
            // Schedule traversals to ensure that the correct state is reapplied if necessary.
            if (mActiveModeId != 0
            if (mActiveModeId != NO_DISPLAY_MODE_ID
                    && mActiveModeId != activeRecord.mMode.getModeId()) {
                mActiveModeInvalid = true;
                sendTraversalRequestLocked();
@@ -294,12 +300,12 @@ final class LocalDisplayAdapter extends DisplayAdapter {

            // Check whether surface flinger spontaneously changed display config specs out from
            // under us. If so, schedule a traversal to reapply our display config specs.
            if (mDisplayModeSpecs.baseModeId != 0) {
            if (mDisplayModeSpecs.baseModeId != NO_DISPLAY_MODE_ID) {
                int activeBaseMode = findMatchingModeIdLocked(configSpecs.defaultConfig);
                // If we can't map the defaultConfig index to a mode, then the physical display
                // configs must have changed, and the code below for handling changes to the
                // list of available modes will take care of updating display config specs.
                if (activeBaseMode != 0) {
                if (activeBaseMode != NO_DISPLAY_MODE_ID) {
                    if (mDisplayModeSpecs.baseModeId != activeBaseMode
                            || mDisplayModeSpecs.refreshRateRange.min != configSpecs.minRefreshRate
                            || mDisplayModeSpecs.refreshRateRange.max
@@ -323,18 +329,23 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                mSupportedModes.put(record.mMode.getModeId(), record);
            }

            // Update the default mode, if needed.
            if (findDisplayConfigIdLocked(mDefaultModeId) < 0) {
                if (mDefaultModeId != 0) {
            // For a new display, we need to initialize the default mode ID.
            if (mDefaultModeId == NO_DISPLAY_MODE_ID) {
                mDefaultModeId = activeRecord.mMode.getModeId();
            } else if (modesAdded && mActiveModeId != activeRecord.mMode.getModeId()) {
                Slog.d(TAG, "New display modes are added and the active mode has changed, "
                        + "use active mode as default mode.");
                mActiveModeId = activeRecord.mMode.getModeId();
                mDefaultModeId = activeRecord.mMode.getModeId();
            } else if (findDisplayConfigIdLocked(mDefaultModeId) < 0) {
                Slog.w(TAG, "Default display mode no longer available, using currently"
                        + " active mode as default.");
                }
                mDefaultModeId = activeRecord.mMode.getModeId();
            }

            // Determine whether the display mode specs' base mode is still there.
            if (mSupportedModes.indexOfKey(mDisplayModeSpecs.baseModeId) < 0) {
                if (mDisplayModeSpecs.baseModeId != 0) {
                if (mDisplayModeSpecs.baseModeId != NO_DISPLAY_MODE_ID) {
                    Slog.w(TAG,
                            "DisplayModeSpecs base mode no longer available, using currently"
                                    + " active mode.");
@@ -345,7 +356,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {

            // Determine whether the active mode is still there.
            if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
                if (mActiveModeId != 0) {
                if (mActiveModeId != NO_DISPLAY_MODE_ID) {
                    Slog.w(TAG, "Active display mode no longer available, reverting to default"
                            + " mode.");
                }
@@ -797,7 +808,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            }
            mActiveConfigId = activeConfigId;
            mActiveModeId = findMatchingModeIdLocked(activeConfigId);
            mActiveModeInvalid = mActiveModeId == 0;
            mActiveModeInvalid = mActiveModeId == NO_DISPLAY_MODE_ID;
            if (mActiveModeInvalid) {
                Slog.w(TAG, "In unknown mode after setting allowed configs"
                        + ", activeConfigId=" + mActiveConfigId);
@@ -922,7 +933,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                    return record.mMode.getModeId();
                }
            }
            return 0;
            return NO_DISPLAY_MODE_ID;
        }

        private void updateDeviceInfoLocked() {
+102 −8
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

@@ -29,6 +31,7 @@ import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.view.Display;
import android.view.DisplayAddress;
import android.view.SurfaceControl;

@@ -47,6 +50,7 @@ import org.mockito.Mock;
import org.mockito.quality.Strictness;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;


@@ -167,6 +171,7 @@ public class LocalDisplayAdapterTest {
     */
    @Test
    public void testDpiValues() throws Exception {
        // needs default one always
        setUpDisplay(new FakeDisplay(PORT_A));
        setUpDisplay(new FakeDisplay(PORT_B));
        updateAvailableDisplays();
@@ -182,6 +187,67 @@ public class LocalDisplayAdapterTest {
                16000);
    }

    @Test
    public void testAfterDisplayChange_ModesAreUpdated() throws Exception {
        SurfaceControl.DisplayConfig displayInfo = createFakeDisplayConfig(1920, 1080, 60f);
        SurfaceControl.DisplayConfig[] configs =
                new SurfaceControl.DisplayConfig[]{displayInfo};
        FakeDisplay display = new FakeDisplay(PORT_A, configs, 0);
        setUpDisplay(display);
        updateAvailableDisplays();
        mAdapter.registerLocked();
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);

        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        assertThat(mListener.changedDisplays).isEmpty();

        DisplayDeviceInfo displayDeviceInfo = mListener.addedDisplays.get(
                0).getDisplayDeviceInfoLocked();

        assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(configs.length);
        assertModeIsSupported(displayDeviceInfo.supportedModes, displayInfo);

        Display.Mode defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
        assertThat(defaultMode.matches(displayInfo.width, displayInfo.height,
                displayInfo.refreshRate)).isTrue();

        Display.Mode activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
        assertThat(activeMode.matches(displayInfo.width, displayInfo.height,
                displayInfo.refreshRate)).isTrue();

        // Change the display
        SurfaceControl.DisplayConfig addedDisplayInfo = createFakeDisplayConfig(3840, 2160,
                60f);
        configs = new SurfaceControl.DisplayConfig[]{displayInfo, addedDisplayInfo};
        display.configs = configs;
        display.activeConfig = 1;
        setUpDisplay(display);
        mAdapter.registerLocked();
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);

        assertThat(SurfaceControl.getActiveConfig(display.token)).isEqualTo(1);
        assertThat(SurfaceControl.getDisplayConfigs(display.token).length).isEqualTo(2);

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

        DisplayDevice displayDevice = mListener.changedDisplays.get(0);
        displayDevice.applyPendingDisplayDeviceInfoChangesLocked();
        displayDeviceInfo = displayDevice.getDisplayDeviceInfoLocked();

        assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(configs.length);
        assertModeIsSupported(displayDeviceInfo.supportedModes, displayInfo);
        assertModeIsSupported(displayDeviceInfo.supportedModes, addedDisplayInfo);

        activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
        assertThat(activeMode.matches(addedDisplayInfo.width, addedDisplayInfo.height,
                addedDisplayInfo.refreshRate)).isTrue();

        defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
        assertThat(defaultMode.matches(addedDisplayInfo.width, addedDisplayInfo.height,
                addedDisplayInfo.refreshRate)).isTrue();
    }

    private void assertDisplayDpi(DisplayDeviceInfo info, int expectedPort,
                                  float expectedXdpi,
                                  float expectedYDpi,
@@ -194,16 +260,40 @@ public class LocalDisplayAdapterTest {
        assertEquals(expectedDensityDpi, info.densityDpi);
    }

    private Display.Mode getModeById(DisplayDeviceInfo displayDeviceInfo, int modeId) {
        return Arrays.stream(displayDeviceInfo.supportedModes)
                .filter(mode -> mode.getModeId() == modeId)
                .findFirst()
                .get();
    }

    private void assertModeIsSupported(Display.Mode[] supportedModes,
            SurfaceControl.DisplayConfig mode) {
        assertThat(Arrays.stream(supportedModes).anyMatch(
                x -> x.matches(mode.width, mode.height, mode.refreshRate))).isTrue();
    }

    private static class FakeDisplay {
        public final DisplayAddress.Physical address;
        public final IBinder token = new Binder();
        public final SurfaceControl.DisplayInfo info;
        public final SurfaceControl.DisplayConfig config;
        public SurfaceControl.DisplayConfig[] configs;
        public int activeConfig;

        private FakeDisplay(int port) {
            this.address = createDisplayAddress(port);
            this.info = createFakeDisplayInfo();
            this.config = createFakeDisplayConfig();
            this.configs = new SurfaceControl.DisplayConfig[]{
                    createFakeDisplayConfig(800, 600, 60f)
            };
            this.activeConfig = 0;
        }

        private FakeDisplay(int port, SurfaceControl.DisplayConfig[] configs, int activeConfig) {
            this.address = createDisplayAddress(port);
            this.info = createFakeDisplayInfo();
            this.configs = configs;
            this.activeConfig = activeConfig;
        }
    }

@@ -212,9 +302,9 @@ public class LocalDisplayAdapterTest {
        doReturn(display.token).when(() ->
                SurfaceControl.getPhysicalDisplayToken(display.address.getPhysicalDisplayId()));
        doReturn(display.info).when(() -> SurfaceControl.getDisplayInfo(display.token));
        doReturn(new SurfaceControl.DisplayConfig[] { display.config }).when(
        doReturn(display.configs).when(
                () -> SurfaceControl.getDisplayConfigs(display.token));
        doReturn(0).when(() -> SurfaceControl.getActiveConfig(display.token));
        doReturn(display.activeConfig).when(() -> SurfaceControl.getActiveConfig(display.token));
        doReturn(0).when(() -> SurfaceControl.getActiveColorMode(display.token));
        doReturn(new int[] { 0 }).when(
                () -> SurfaceControl.getDisplayColorModes(display.token));
@@ -242,10 +332,12 @@ public class LocalDisplayAdapterTest {
        return info;
    }

    private static SurfaceControl.DisplayConfig createFakeDisplayConfig() {
    private static SurfaceControl.DisplayConfig createFakeDisplayConfig(int width, int height,
            float refreshRate) {
        final SurfaceControl.DisplayConfig config = new SurfaceControl.DisplayConfig();
        config.width = 800;
        config.height = 600;
        config.width = width;
        config.height = height;
        config.refreshRate = refreshRate;
        config.xDpi = 100;
        config.yDpi = 100;
        return config;
@@ -266,17 +358,19 @@ public class LocalDisplayAdapterTest {

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

        @Override
        public void onDisplayDeviceEvent(DisplayDevice device, int event) {
            if (event == DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED) {
                addedDisplays.add(device);
            } else if (event == DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED) {
                changedDisplays.add(device);
            }
        }

        @Override
        public void onTraversalRequested() {

        }
    }
}