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

Commit 0998f90d authored by Ebru Kurnaz's avatar Ebru Kurnaz
Browse files

Change resolution via synthetic mode.

This is a fake resolution change where resolution is changed in LogicalDisplay and SurfaceFlinger doesn't know about it.

Bug: 438485020
Flag: com.android.server.display.feature.flags.enable_size_override_for_external_displays
Test: atest LogicalDisplayTest
Change-Id: I9c45056268f8d6075e26c6cbb265ee6a69d477ea
parent e9b44c27
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -2433,10 +2433,18 @@ public final class Display {
         * @hide
         */
        public static final int FLAG_ARR_RENDER_RATE = 1 << 0;
        /**
         * @hide
         *
         * A synthetic display mode flag that indicates the mode is used to override the display's
         * logical width and height without changing the mode reported to SurfaceFlinger.
         */
        public static final int FLAG_SIZE_OVERRIDE = 1 << 1;

        /** @hide */
        @IntDef(flag = true, prefix = {"FLAG_"}, value = {
                FLAG_ARR_RENDER_RATE,
                FLAG_SIZE_OVERRIDE,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface ModeFlags {}
@@ -2761,6 +2769,9 @@ public final class Display {
            if ((flags & FLAG_ARR_RENDER_RATE) != 0) {
                msg.append(", FLAG_ARR_RENDER_RATE");
            }
            if ((flags & FLAG_SIZE_OVERRIDE) != 0) {
                msg.append(", FLAG_SIZE_OVERRIDE");
            }
            return msg.toString();
        }

+5 −1
Original line number Diff line number Diff line
@@ -54,13 +54,17 @@ public class DisplayModeFactory {

    @SuppressLint("WrongConstant")
    static Display.Mode createMode(SurfaceControl.DisplayMode mode, float[] alternativeRefreshRates,
            boolean hasArrSupport, boolean syntheticModesV2Enabled) {
            boolean hasArrSupport, boolean syntheticModesV2Enabled, boolean sizeOverrideEnabled) {
        int flags = 0;
        if (syntheticModesV2Enabled
                && hasArrSupport && mode.peakRefreshRate <= SYNTHETIC_MODE_HIGH_BOUNDARY) {
            flags |= Display.Mode.FLAG_ARR_RENDER_RATE;
        }

        if (sizeOverrideEnabled) {
            flags |= Display.Mode.FLAG_SIZE_OVERRIDE;
        }

        return new Display.Mode(NEXT_DISPLAY_MODE_ID.getAndIncrement(),
                Display.Mode.INVALID_MODE_ID, flags,
                mode.width, mode.height, mode.peakRefreshRate, mode.vsyncRate,
+7 −5
Original line number Diff line number Diff line
@@ -293,8 +293,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        public boolean updateDisplayPropertiesLocked(SurfaceControl.StaticDisplayInfo staticInfo,
                SurfaceControl.DynamicDisplayInfo dynamicInfo,
                SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
            boolean changed = updateDisplayModesLocked(dynamicInfo, modeSpecs);

            boolean changed = updateDisplayModesLocked(dynamicInfo, modeSpecs,
                    staticInfo.isInternal);
            changed |= updateStaticInfo(staticInfo);
            changed |= updateColorModesLocked(dynamicInfo.supportedColorModes,
                    dynamicInfo.activeColorMode);
@@ -312,13 +312,15 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        }

        private boolean updateDisplayModesLocked(SurfaceControl.DynamicDisplayInfo dynamicInfo,
                SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
                SurfaceControl.DesiredDisplayModeSpecs modeSpecs, boolean isInternal) {
            SurfaceControl.DisplayMode[] displayModes = dynamicInfo.supportedDisplayModes;
            int preferredSfDisplayModeId = dynamicInfo.preferredBootDisplayMode;
            int activeSfDisplayModeId = dynamicInfo.activeDisplayModeId;
            float renderFrameRate = dynamicInfo.renderFrameRate;
            boolean hasArrSupport = dynamicInfo.hasArrSupport;
            boolean syntheticModesV2Enabled = getFeatureFlags().isSyntheticModesV2Enabled();
            boolean sizeOverrideEnabled =
                    getFeatureFlags().isSizeOverrideForExternalDisplaysEnabled() && !isInternal;

            mSfDisplayModes = Arrays.copyOf(displayModes, displayModes.length);
            mActiveSfDisplayMode = getModeById(displayModes, activeSfDisplayModeId);
@@ -369,8 +371,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                    for (int j = 0; j < alternativeRates.length; j++) {
                        alternativeRates[j] = alternativeRefreshRates.get(j);
                    }
                    Display.Mode displayMode = DisplayModeFactory.createMode(
                            mode, alternativeRates, hasArrSupport, syntheticModesV2Enabled);
                    Display.Mode displayMode = DisplayModeFactory.createMode(mode, alternativeRates,
                            hasArrSupport, syntheticModesV2Enabled, sizeOverrideEnabled);
                    record = new DisplayModeRecord(displayMode);
                    modesAdded = true;
                }
+61 −12
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.display;

import static android.view.Display.Mode.INVALID_MODE_ID;

import static com.android.server.display.DisplayDeviceInfo.TOUCH_NONE;
import static com.android.server.display.layout.Layout.Display.POSITION_REAR;
import static com.android.server.wm.utils.DisplayInfoOverrides.WM_OVERRIDE_FIELDS;
@@ -232,15 +234,17 @@ final class LogicalDisplay {
    private final boolean mSyncedResolutionSwitchEnabled;

    private final boolean mSyntheticModesV2Enabled;
    private final boolean mSizeOverrideEnabled;

    private boolean mCanHostTasks;

    LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) {
        this(displayId, layerStack, primaryDisplayDevice, false, true);
        this(displayId, layerStack, primaryDisplayDevice, false, true, false);
    }

    LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice,
            boolean isSyncedResolutionSwitchEnabled, boolean syntheticModesV2Enabled) {
            boolean isSyncedResolutionSwitchEnabled, boolean syntheticModesV2Enabled,
            boolean sizeOverrideEnabled) {
        mDisplayId = displayId;
        mLayerStack = layerStack;
        mPrimaryDisplayDevice = primaryDisplayDevice;
@@ -253,6 +257,7 @@ final class LogicalDisplay {
        mBaseDisplayInfo.thermalBrightnessThrottlingDataId = mThermalBrightnessThrottlingDataId;
        mSyncedResolutionSwitchEnabled = isSyncedResolutionSwitchEnabled;
        mSyntheticModesV2Enabled = syntheticModesV2Enabled;
        mSizeOverrideEnabled = sizeOverrideEnabled;

        // No need to initialize mCanHostTasks here; it's handled in
        // DisplayManagerService#setupLogicalDisplay().
@@ -505,16 +510,30 @@ final class LogicalDisplay {
                    && mDevicePosition != Layout.Display.POSITION_REAR) {
                mBaseDisplayInfo.flags |= Display.FLAG_ALLOWS_CONTENT_MODE_SWITCH;
            }

            int currentWidth = deviceInfo.width;
            int currentHeight = deviceInfo.height;
            float currentXDpi = deviceInfo.xDpi;
            float currentYDpi = deviceInfo.yDpi;

            Display.Mode sizeOverrideMode = getUserPreferredModeForSizeOverrideLocked(deviceInfo);
            if (sizeOverrideMode != null && mSizeOverrideEnabled) {
                currentWidth = sizeOverrideMode.getPhysicalWidth();
                currentHeight = sizeOverrideMode.getPhysicalHeight();
                currentXDpi = currentXDpi * (currentWidth / (float) deviceInfo.width);
                currentYDpi = currentYDpi * (currentHeight / (float) deviceInfo.height);
            }

            Rect maskingInsets = getMaskingInsets(deviceInfo);
            int maskedWidth = deviceInfo.width - maskingInsets.left - maskingInsets.right;
            int maskedHeight = deviceInfo.height - maskingInsets.top - maskingInsets.bottom;
            int maskedWidth = currentWidth - maskingInsets.left - maskingInsets.right;
            int maskedHeight = currentHeight - maskingInsets.top - maskingInsets.bottom;

            if (mIsAnisotropyCorrectionEnabled && deviceInfo.type == Display.TYPE_EXTERNAL
                        && deviceInfo.xDpi > 0 && deviceInfo.yDpi > 0) {
                if (deviceInfo.xDpi > deviceInfo.yDpi * DisplayDevice.MAX_ANISOTROPY) {
                    maskedHeight = (int) (maskedHeight * deviceInfo.xDpi / deviceInfo.yDpi + 0.5);
                } else if (deviceInfo.xDpi * DisplayDevice.MAX_ANISOTROPY < deviceInfo.yDpi) {
                    maskedWidth = (int) (maskedWidth * deviceInfo.yDpi / deviceInfo.xDpi + 0.5);
                        && currentXDpi > 0 && currentYDpi > 0) {
                if (currentXDpi > currentYDpi * DisplayDevice.MAX_ANISOTROPY) {
                    maskedHeight = (int) (maskedHeight * currentXDpi / currentYDpi + 0.5);
                } else if (currentXDpi * DisplayDevice.MAX_ANISOTROPY < currentYDpi) {
                    maskedWidth = (int) (maskedWidth * currentYDpi / currentXDpi + 0.5);
                }
            }

@@ -553,10 +572,10 @@ final class LogicalDisplay {
                    deviceInfo.allmSupported || deviceInfo.gameContentTypeSupported;
            mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi > 0
                    ? deviceInfo.densityDpi
                    : calculateBaseDensity(deviceInfo.xDpi, deviceInfo.yDpi, maskedWidth,
                    : calculateBaseDensity(currentXDpi, currentYDpi, maskedWidth,
                            maskedHeight);
            mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
            mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
            mBaseDisplayInfo.physicalXDpi = currentXDpi;
            mBaseDisplayInfo.physicalYDpi = currentYDpi;
            mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos;
            mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos;
            mBaseDisplayInfo.state = deviceInfo.state;
@@ -623,6 +642,36 @@ final class LogicalDisplay {
        return Math.max((int) (dpi + 0.5), EXTERNAL_DISPLAY_MIN_DENSITY_DPI);
    }

    @Nullable
    private Display.Mode getUserPreferredModeForSizeOverrideLocked(DisplayDeviceInfo deviceInfo) {
        Display.Mode[] modes = deviceInfo.supportedModes;
        int selectedModeId = deviceInfo.modeId;
        int userPreferredModeId = deviceInfo.userPreferredModeId;

        if (userPreferredModeId == INVALID_MODE_ID) {
            return null;
        }
        // user preferred mode is normal mode
        if (userPreferredModeId == selectedModeId) {
            return null;
        }

        Display.Mode userPreferredMode = null;
        for (Display.Mode mode : modes) {
            if (userPreferredModeId == mode.getModeId()) {
                userPreferredMode = mode;
                break;
            }
        }

        if (userPreferredMode != null
                && (userPreferredMode.getFlags() & Display.Mode.FLAG_SIZE_OVERRIDE) != 0) {
            return userPreferredMode;
        }

        return null;
    }

    private void updateFrameRateOverrides(DisplayDeviceInfo deviceInfo) {
        mTempFrameRateOverride.clear();
        if (mFrameRateOverrides != null) {
+2 −1
Original line number Diff line number Diff line
@@ -1312,7 +1312,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
    private LogicalDisplay createNewLogicalDisplayLocked(DisplayDevice device, int displayId) {
        final int layerStack = assignLayerStackLocked(displayId);
        final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device,
                mFlags.isSyncedResolutionSwitchEnabled(), mFlags.isSyntheticModesV2Enabled());
                mFlags.isSyncedResolutionSwitchEnabled(), mFlags.isSyntheticModesV2Enabled(),
                mFlags.isSizeOverrideForExternalDisplaysEnabled());
        display.updateLocked(mDisplayDeviceRepo, mSyntheticModeManager);

        final DisplayInfo info = display.getDisplayInfoLocked();
Loading