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

Commit 53a296d2 authored by Jason Macnak's avatar Jason Macnak
Browse files

Map SurfaceFlinger display mode ids to Display.Mode ids

Noticed while trying to switch Cuttlefish to HWComposer3
with ag/16624862. By default, Cuttlefish has a single display
with a single config:

`RanchuHwc: config: id: 0 w:720 h:1280 dpi-x:320 dpi-y:320 ...`

In `LocalDeviceDisplay::updateDisplayModesLocked()`, the display
config ids which come from HWComposer via SurfaceFlinger are mapped
to DisplayRecord's Display.Mode's `mModeId` which are globally
unique ids created from the atomic integer
`DisplayAdapter.NEXT_DISPLAY_MODE_ID` (which defaults to 1).

However, the preferred display config id (`mSystemPreferredModeId`)
was not being mapped. This would lead to boot failures such as:

`
AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: android.anim
AndroidRuntime: java.lang.IllegalStateException: Unable to locate mode 0
`

with ag/16774826 because `mDefaultModeId` was being set to
`mSystemPreferredModeId` which was the unmapped `0` from HWComposer.

(Perhaps the need for this change suggests there should be strongly
typed integers to represent the different id spaces,
`SurfaceFlingerModeId` vs `DisplayAdapaterModeId` or something)

Bug: b/193240715
Test: lunch cf_x86_64_phone-userdebug && cherry-pick ag/16624862 &&
      m && cvd start
Change-Id: I8fc0fca6816e037196f51d256430fad480f3b0ff
parent f0d48baf
Loading
Loading
Loading
Loading
+44 −29
Original line number Diff line number Diff line
@@ -257,10 +257,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        public boolean updateDisplayPropertiesLocked(SurfaceControl.StaticDisplayInfo staticInfo,
                SurfaceControl.DynamicDisplayInfo dynamicInfo,
                SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
            boolean changed =
                    updateSystemPreferredDisplayMode(dynamicInfo.preferredBootDisplayMode);
            changed |= updateDisplayModesLocked(
                    dynamicInfo.supportedDisplayModes, dynamicInfo.activeDisplayModeId, modeSpecs);
            boolean changed = updateDisplayModesLocked(
                    dynamicInfo.supportedDisplayModes, dynamicInfo.preferredBootDisplayMode,
                    dynamicInfo.activeDisplayModeId, modeSpecs);
            changed |= updateStaticInfo(staticInfo);
            changed |= updateColorModesLocked(dynamicInfo.supportedColorModes,
                    dynamicInfo.activeColorMode);
@@ -275,10 +274,12 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        }

        public boolean updateDisplayModesLocked(
                SurfaceControl.DisplayMode[] displayModes, int activeDisplayModeId,
                SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
                SurfaceControl.DisplayMode[] displayModes, int preferredSfDisplayModeId,
                int activeSfDisplayModeId, SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
            mSfDisplayModes = Arrays.copyOf(displayModes, displayModes.length);
            mActiveSfDisplayMode = getModeById(displayModes, activeDisplayModeId);
            mActiveSfDisplayMode = getModeById(displayModes, activeSfDisplayModeId);
            SurfaceControl.DisplayMode preferredSfDisplayMode =
                        getModeById(displayModes, preferredSfDisplayModeId);

            // Build an updated list of all existing modes.
            ArrayList<DisplayModeRecord> records = new ArrayList<>();
@@ -337,6 +338,27 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                }
            }

            boolean preferredModeChanged = false;

            if (preferredSfDisplayModeId != INVALID_MODE_ID && preferredSfDisplayMode != null) {
                DisplayModeRecord preferredRecord = null;
                for (DisplayModeRecord record : records) {
                    if (record.hasMatchingMode(preferredSfDisplayMode)) {
                        preferredRecord = record;
                        break;
                    }
                }

                if (preferredRecord != null) {
                    int preferredModeId = preferredRecord.mMode.getModeId();
                    if (mSurfaceControlProxy.getBootDisplayModeSupport()
                            && mSystemPreferredModeId != preferredModeId) {
                        mSystemPreferredModeId = preferredModeId;
                        preferredModeChanged = true;
                    }
                }
            }

            boolean activeModeChanged = false;

            // Check whether SurfaceFlinger or the display device changed the active mode out from
@@ -375,7 +397,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
            // If the records haven't changed then we're done here.
            if (!recordsChanged) {
                return activeModeChanged;
                return activeModeChanged || preferredModeChanged;
            }

            mSupportedModes.clear();
@@ -388,14 +410,14 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                mDefaultModeId = mSystemPreferredModeId != INVALID_MODE_ID
                        ? mSystemPreferredModeId : activeRecord.mMode.getModeId();
                mDefaultModeGroup = mSystemPreferredModeId != INVALID_MODE_ID
                        ? getModeById(mSfDisplayModes, mSystemPreferredModeId).group
                        ? preferredSfDisplayMode.group
                        : mActiveSfDisplayMode.group;
            } else if (modesAdded && activeModeChanged) {
                Slog.d(TAG, "New display modes are added and the active mode has changed, "
                        + "use active mode as default mode.");
                mDefaultModeId = activeRecord.mMode.getModeId();
                mDefaultModeGroup = mActiveSfDisplayMode.group;
            } else if (findDisplayModeIdLocked(mDefaultModeId, mDefaultModeGroup) < 0) {
            } else if (findSfDisplayModeIdLocked(mDefaultModeId, mDefaultModeGroup) < 0) {
                Slog.w(TAG, "Default display mode no longer available, using currently"
                        + " active mode as default.");
                mDefaultModeId = activeRecord.mMode.getModeId();
@@ -550,15 +572,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            return true;
        }

        private boolean updateSystemPreferredDisplayMode(int modeId) {
            if (!mSurfaceControlProxy.getBootDisplayModeSupport()
                    || mSystemPreferredModeId == modeId) {
                return false;
            }
            mSystemPreferredModeId = modeId;
            return true;
        }

        private SurfaceControl.DisplayMode getModeById(SurfaceControl.DisplayMode[] supportedModes,
                int modeId) {
            for (SurfaceControl.DisplayMode mode : supportedModes) {
@@ -892,8 +905,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            if (mUserPreferredMode == null) {
                mSurfaceControlProxy.clearBootDisplayMode(getDisplayTokenLocked());
            } else {
                int preferredSfDisplayModeId = findSfDisplayModeIdLocked(
                        mUserPreferredMode.getModeId(), mDefaultModeGroup);
                mSurfaceControlProxy.setBootDisplayMode(getDisplayTokenLocked(),
                        mUserPreferredMode.getModeId());
                        preferredSfDisplayModeId);
            }
        }

@@ -928,9 +943,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            // mode based on vendor requirements.
            // Note: We prefer the default mode group over the current one as this is the mode
            // group the vendor prefers.
            int baseModeId = findDisplayModeIdLocked(displayModeSpecs.baseModeId,
            int baseSfModeId = findSfDisplayModeIdLocked(displayModeSpecs.baseModeId,
                    mDefaultModeGroup);
            if (baseModeId < 0) {
            if (baseSfModeId < 0) {
                // When a display is hotplugged, it's possible for a mode to be removed that was
                // previously valid. Because of the way display changes are propagated through the
                // framework, and the caching of the display mode specs in LogicalDisplay, it's
@@ -948,7 +963,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                getHandler().sendMessage(PooledLambda.obtainMessage(
                        LocalDisplayDevice::setDesiredDisplayModeSpecsAsync, this,
                        getDisplayTokenLocked(),
                        new SurfaceControl.DesiredDisplayModeSpecs(baseModeId,
                        new SurfaceControl.DesiredDisplayModeSpecs(baseSfModeId,
                                mDisplayModeSpecs.allowGroupSwitching,
                                mDisplayModeSpecs.primaryRefreshRateRange.min,
                                mDisplayModeSpecs.primaryRefreshRateRange.max,
@@ -1095,14 +1110,14 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            pw.println("mDisplayDeviceConfig=" + mDisplayDeviceConfig);
        }

        private int findDisplayModeIdLocked(int modeId, int modeGroup) {
            int matchingModeId = INVALID_MODE_ID;
            DisplayModeRecord record = mSupportedModes.get(modeId);
        private int findSfDisplayModeIdLocked(int displayModeId, int modeGroup) {
            int matchingSfDisplayModeId = INVALID_MODE_ID;
            DisplayModeRecord record = mSupportedModes.get(displayModeId);
            if (record != null) {
                for (SurfaceControl.DisplayMode mode : mSfDisplayModes) {
                    if (record.hasMatchingMode(mode)) {
                        if (matchingModeId == INVALID_MODE_ID) {
                            matchingModeId = mode.id;
                        if (matchingSfDisplayModeId == INVALID_MODE_ID) {
                            matchingSfDisplayModeId = mode.id;
                        }

                        // Prefer to return a mode that matches the modeGroup
@@ -1112,7 +1127,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                    }
                }
            }
            return matchingModeId;
            return matchingSfDisplayModeId;
        }

        // Returns a mode with id = modeId.