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

Commit fc1a2e08 authored by Ebru Kurnaz's avatar Ebru Kurnaz
Browse files

Add hidden WM API to set external display density ratio.

Flag: com.android.window.flags.enable_persisting_display_size_for_connected_displays
Test: atest DisplayContentTests
Test: atest WindowManagerServiceTests
Bug: 400418602
NO_IFTTT=Ifttt added with this change, no updates needed.

Change-Id: Ic470dddeed0ca7fcdae17f28746f99d1f78254b8
parent a2e1b4db
Loading
Loading
Loading
Loading
+21 −0
Original line number Original line Diff line number Diff line
@@ -135,8 +135,29 @@ interface IWindowManager
    int getDisplayIdByUniqueId(String uniqueId);
    int getDisplayIdByUniqueId(String uniqueId);
    @EnforcePermission("WRITE_SECURE_SETTINGS")
    @EnforcePermission("WRITE_SECURE_SETTINGS")
    void setForcedDisplayDensityForUser(int displayId, int density, int userId);
    void setForcedDisplayDensityForUser(int displayId, int density, int userId);
    /**
    * Clears forced density and forced density ratio in DisplayWindowSettings for the given
    * displayId.
    *
    * @param displayId Id of the display.
    * @param userId Id of the user.
    */
    @EnforcePermission("WRITE_SECURE_SETTINGS")
    @EnforcePermission("WRITE_SECURE_SETTINGS")
    void clearForcedDisplayDensityForUser(int displayId, int userId);
    void clearForcedDisplayDensityForUser(int displayId, int userId);
    /**
    * Sets display forced density ratio and forced density in DisplayWindowSettings for
    * the given displayId. Ratio is used to update forced density to persist display size when
    * resolution change happens. Use {@link #setForcedDisplayDensityForUser} when there is no need
    * to handle resolution changes for the display. If setForcedDisplayDensityForUser is used after,
    * this the ratio will be updated to use the last set forced density. Use
    * {@link #clearForcedDisplayDensityForUser} to reset.
    *
    * @param displayId Id of the display.
    * @param ratio The ratio of forced density to the default density.
    * @param userId Id of the user.
    */
    @EnforcePermission("WRITE_SECURE_SETTINGS")
    void setForcedDisplayDensityRatio(int displayId, float ratio, int userId);


    /**
    /**
     * Sets settings for a specific user in a batch to minimize configuration updates.
     * Sets settings for a specific user in a batch to minimize configuration updates.
+38 −4
Original line number Original line Diff line number Diff line
@@ -97,6 +97,12 @@ public class DisplayDensityUtils {
    @Nullable
    @Nullable
    private final int[] mValues;
    private final int[] mValues;


    /**
     * The density values before rounding to an integer.
     */
    @Nullable
    private final float[] mFloatValues;

    private final int mDefaultDensity;
    private final int mDefaultDensity;
    private final int mCurrentIndex;
    private final int mCurrentIndex;


@@ -124,6 +130,7 @@ public class DisplayDensityUtils {
            Log.w(LOG_TAG, "Cannot fetch display info for the default display");
            Log.w(LOG_TAG, "Cannot fetch display info for the default display");
            mEntries = null;
            mEntries = null;
            mValues = null;
            mValues = null;
            mFloatValues = null;
            mDefaultDensity = 0;
            mDefaultDensity = 0;
            mCurrentIndex = -1;
            mCurrentIndex = -1;
            return;
            return;
@@ -154,6 +161,7 @@ public class DisplayDensityUtils {
            Log.w(LOG_TAG, "No display satisfies the predicate");
            Log.w(LOG_TAG, "No display satisfies the predicate");
            mEntries = null;
            mEntries = null;
            mValues = null;
            mValues = null;
            mFloatValues = null;
            mDefaultDensity = 0;
            mDefaultDensity = 0;
            mCurrentIndex = -1;
            mCurrentIndex = -1;
            return;
            return;
@@ -165,6 +173,7 @@ public class DisplayDensityUtils {
            Log.w(LOG_TAG, "Cannot fetch default density for display " + idOfSmallestDisplay);
            Log.w(LOG_TAG, "Cannot fetch default density for display " + idOfSmallestDisplay);
            mEntries = null;
            mEntries = null;
            mValues = null;
            mValues = null;
            mFloatValues = null;
            mDefaultDensity = 0;
            mDefaultDensity = 0;
            mCurrentIndex = -1;
            mCurrentIndex = -1;
            return;
            return;
@@ -197,18 +206,25 @@ public class DisplayDensityUtils {


        String[] entries = new String[1 + numSmaller + numLarger];
        String[] entries = new String[1 + numSmaller + numLarger];
        int[] values = new int[entries.length];
        int[] values = new int[entries.length];
        float[] valuesFloat = new float[entries.length];
        int curIndex = 0;
        int curIndex = 0;


        if (numSmaller > 0) {
        if (numSmaller > 0) {
            final float interval = (1 - minScale) / numSmaller;
            final float interval = (1 - minScale) / numSmaller;
            for (int i = numSmaller - 1; i >= 0; i--) {
            for (int i = numSmaller - 1; i >= 0; i--) {
                // Save the float density value before rounding to be used to set the density ratio
                // of overridden density to default density in WM.
                final float densityFloat = defaultDensity * (1 - (i + 1) * interval);
                // Round down to a multiple of 2 by truncating the low bit.
                // Round down to a multiple of 2 by truncating the low bit.
                final int density = ((int) (defaultDensity * (1 - (i + 1) * interval))) & ~1;
                // LINT.IfChange
                final int density = ((int) densityFloat) & ~1;
                // LINT.ThenChange(/services/core/java/com/android/server/wm/DisplayContent.java:getBaseDensityFromRatio)
                if (currentDensity == density) {
                if (currentDensity == density) {
                    currentDensityIndex = curIndex;
                    currentDensityIndex = curIndex;
                }
                }
                entries[curIndex] = res.getString(SUMMARIES_SMALLER[i]);
                values[curIndex] = density;
                values[curIndex] = density;
                valuesFloat[curIndex] = densityFloat;
                entries[curIndex] = res.getString(SUMMARIES_SMALLER[i]);
                curIndex++;
                curIndex++;
            }
            }
        }
        }
@@ -217,18 +233,25 @@ public class DisplayDensityUtils {
            currentDensityIndex = curIndex;
            currentDensityIndex = curIndex;
        }
        }
        values[curIndex] = defaultDensity;
        values[curIndex] = defaultDensity;
        valuesFloat[curIndex] = (float) defaultDensity;
        entries[curIndex] = res.getString(SUMMARY_DEFAULT);
        entries[curIndex] = res.getString(SUMMARY_DEFAULT);
        curIndex++;
        curIndex++;


        if (numLarger > 0) {
        if (numLarger > 0) {
            final float interval = (maxScale - 1) / numLarger;
            final float interval = (maxScale - 1) / numLarger;
            for (int i = 0; i < numLarger; i++) {
            for (int i = 0; i < numLarger; i++) {
                // Save the float density value before rounding to be used to set the density ratio
                // of overridden density to default density in WM.
                final float densityFloat = defaultDensity * (1 + (i + 1) * interval);
                // Round down to a multiple of 2 by truncating the low bit.
                // Round down to a multiple of 2 by truncating the low bit.
                final int density = ((int) (defaultDensity * (1 + (i + 1) * interval))) & ~1;
                // LINT.IfChange
                final int density = ((int) densityFloat) & ~1;
                // LINT.ThenChange(/services/core/java/com/android/server/wm/DisplayContent.java:getBaseDensityFromRatio)
                if (currentDensity == density) {
                if (currentDensity == density) {
                    currentDensityIndex = curIndex;
                    currentDensityIndex = curIndex;
                }
                }
                values[curIndex] = density;
                values[curIndex] = density;
                valuesFloat[curIndex] = densityFloat;
                entries[curIndex] = res.getString(SUMMARIES_LARGER[i]);
                entries[curIndex] = res.getString(SUMMARIES_LARGER[i]);
                curIndex++;
                curIndex++;
            }
            }
@@ -244,6 +267,9 @@ public class DisplayDensityUtils {
            values = Arrays.copyOf(values, newLength);
            values = Arrays.copyOf(values, newLength);
            values[curIndex] = currentDensity;
            values[curIndex] = currentDensity;


            valuesFloat = Arrays.copyOf(valuesFloat, newLength);
            valuesFloat[curIndex] = (float) currentDensity;

            entries = Arrays.copyOf(entries, newLength);
            entries = Arrays.copyOf(entries, newLength);
            entries[curIndex] = res.getString(SUMMARY_CUSTOM, currentDensity);
            entries[curIndex] = res.getString(SUMMARY_CUSTOM, currentDensity);


@@ -254,6 +280,7 @@ public class DisplayDensityUtils {
        mCurrentIndex = displayIndex;
        mCurrentIndex = displayIndex;
        mEntries = entries;
        mEntries = entries;
        mValues = values;
        mValues = values;
        mFloatValues = valuesFloat;
    }
    }


    @Nullable
    @Nullable
@@ -348,8 +375,15 @@ public class DisplayDensityUtils {
                    }
                    }


                    final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                    final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                    // Only set the ratio for external displays as Settings uses
                    // ScreenResolutionFragment to handle density update for internal display.
                    if (info.type == Display.TYPE_EXTERNAL) {
                        wm.setForcedDisplayDensityRatio(displayId,
                                mFloatValues[index] / mDefaultDensity, userId);
                    } else {
                        wm.setForcedDisplayDensityForUser(displayId, mValues[index], userId);
                        wm.setForcedDisplayDensityForUser(displayId, mValues[index], userId);
                    }
                    }
                }
            } catch (RemoteException exc) {
            } catch (RemoteException exc) {
                Log.w(LOG_TAG, "Unable to save forced display density setting");
                Log.w(LOG_TAG, "Unable to save forced display density setting");
            }
            }
+29 −16
Original line number Original line Diff line number Diff line
@@ -46,7 +46,6 @@ import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.STATE_UNKNOWN;
import static android.view.Display.STATE_UNKNOWN;
import static android.view.Display.TYPE_EXTERNAL;
import static android.view.Display.isSuspendedState;
import static android.view.Display.isSuspendedState;
import static android.view.InsetsSource.ID_IME;
import static android.view.InsetsSource.ID_IME;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_0;
@@ -432,9 +431,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp


    /**
    /**
     * Ratio between overridden display density for current user and the initial display density,
     * Ratio between overridden display density for current user and the initial display density,
     * used only for external displays.
     * used for updating the base density when resolution change happens to preserve display size.
     */
     */
    float mExternalDisplayForcedDensityRatio = 0.0f;
    float mForcedDisplayDensityRatio = 0.0f;
    boolean mIsDensityForced = false;
    boolean mIsDensityForced = false;


    /**
    /**
@@ -3119,6 +3118,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            mBaseRoundedCorners = loadRoundedCorners(baseWidth, baseHeight);
            mBaseRoundedCorners = loadRoundedCorners(baseWidth, baseHeight);
        }
        }


        // Update the base density if there is a forced density ratio.
        if (DesktopExperienceFlags.ENABLE_PERSISTING_DISPLAY_SIZE_FOR_CONNECTED_DISPLAYS.isTrue()
                && mForcedDisplayDensityRatio != 0.0f) {
            mBaseDisplayDensity = getBaseDensityFromRatio();
        }

        if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) {
        if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) {
            final float ratio = mMaxUiWidth / (float) mBaseDisplayWidth;
            final float ratio = mMaxUiWidth / (float) mBaseDisplayWidth;
            mBaseDisplayHeight = (int) (mBaseDisplayHeight * ratio);
            mBaseDisplayHeight = (int) (mBaseDisplayHeight * ratio);
@@ -3136,17 +3141,21 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                        + mBaseDisplayHeight + " on display:" + getDisplayId());
                        + mBaseDisplayHeight + " on display:" + getDisplayId());
            }
            }
        }
        }
        // Update the base density if there is a forced density ratio.
        if (DesktopExperienceFlags.ENABLE_PERSISTING_DISPLAY_SIZE_FOR_CONNECTED_DISPLAYS.isTrue()
                && mIsDensityForced && mExternalDisplayForcedDensityRatio != 0.0f) {
            mBaseDisplayDensity = (int)
                    (mInitialDisplayDensity * mExternalDisplayForcedDensityRatio + 0.5);
        }
        if (mDisplayReady && !mDisplayPolicy.shouldKeepCurrentDecorInsets()) {
        if (mDisplayReady && !mDisplayPolicy.shouldKeepCurrentDecorInsets()) {
            mDisplayPolicy.mDecorInsets.invalidate();
            mDisplayPolicy.mDecorInsets.invalidate();
        }
        }
    }
    }


    /**
     * Returns the forced density from forcedDensityRatio if the ratio is valid by rounding the
     * density down to an even number. Returns the initial density if the ratio is 0.
     */
    private int getBaseDensityFromRatio() {
        return (mForcedDisplayDensityRatio != 0.0f)
                ? ((int) (mInitialDisplayDensity * mForcedDisplayDensityRatio)) & ~1
                : mInitialDisplayDensity;
    }

    /**
    /**
     * Forces this display to use the specified density.
     * Forces this display to use the specified density.
     *
     *
@@ -3171,15 +3180,19 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        if (density == getInitialDisplayDensity()) {
        if (density == getInitialDisplayDensity()) {
            density = 0;
            density = 0;
        }
        }
        // Save the new density ratio to settings for external displays.
        mWmService.mDisplayWindowSettings.setForcedDensity(getDisplayInfo(), density, userId);
        if (DesktopExperienceFlags.ENABLE_PERSISTING_DISPLAY_SIZE_FOR_CONNECTED_DISPLAYS.isTrue()
    }
                && mDisplayInfo.type == TYPE_EXTERNAL) {

            mExternalDisplayForcedDensityRatio = (float)
    void setForcedDensityRatio(float ratio, int userId) {
                    mBaseDisplayDensity / getInitialDisplayDensity();
        // Save the new density ratio to settings and update forced density with the ratio.
        if (DesktopExperienceFlags.ENABLE_PERSISTING_DISPLAY_SIZE_FOR_CONNECTED_DISPLAYS.isTrue()) {
            mForcedDisplayDensityRatio = ratio;
            mWmService.mDisplayWindowSettings.setForcedDensityRatio(getDisplayInfo(),
            mWmService.mDisplayWindowSettings.setForcedDensityRatio(getDisplayInfo(),
                    mExternalDisplayForcedDensityRatio);
                    mForcedDisplayDensityRatio);

            // Set forced density from ratio.
            setForcedDensity(getBaseDensityFromRatio(), userId);
        }
        }
        mWmService.mDisplayWindowSettings.setForcedDensity(getDisplayInfo(), density, userId);
    }
    }


    /** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */
    /** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */
+1 −1
Original line number Original line Diff line number Diff line
@@ -391,7 +391,7 @@ class DisplayWindowSettings {
        final int density = hasDensityOverride ? settings.mForcedDensity
        final int density = hasDensityOverride ? settings.mForcedDensity
                : dc.getInitialDisplayDensity();
                : dc.getInitialDisplayDensity();
        if (hasDensityOverrideRatio) {
        if (hasDensityOverrideRatio) {
            dc.mExternalDisplayForcedDensityRatio = settings.mForcedDensityRatio;
            dc.mForcedDisplayDensityRatio = settings.mForcedDensityRatio;
        }
        }


        dc.updateBaseDisplayMetrics(width, height, density, dc.mBaseDisplayPhysicalXDpi,
        dc.updateBaseDisplayMetrics(width, height, density, dc.mBaseDisplayPhysicalXDpi,
+35 −0
Original line number Original line Diff line number Diff line
@@ -6212,6 +6212,10 @@ public class WindowManagerService extends IWindowManager.Stub
        final long ident = Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        try {
        try {
            synchronized (mGlobalLock) {
            synchronized (mGlobalLock) {
                // Clear forced display density ratio
                setForcedDisplayDensityRatioInternal(displayId, 0.0f, userId);

                // Clear forced display density
                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                if (displayContent != null) {
                if (displayContent != null) {
                    displayContent.setForcedDensity(displayContent.getInitialDisplayDensity(),
                    displayContent.setForcedDensity(displayContent.getInitialDisplayDensity(),
@@ -6234,6 +6238,37 @@ public class WindowManagerService extends IWindowManager.Stub
        }
        }
    }
    }


    @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
    @Override
    public void setForcedDisplayDensityRatio(int displayId, float ratio, int userId) {
        setForcedDisplayDensityRatio_enforcePermission();
        final long ident = Binder.clearCallingIdentity();
        try {
            synchronized (mGlobalLock) {
                setForcedDisplayDensityRatioInternal(displayId, ratio, userId);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

    private void setForcedDisplayDensityRatioInternal(
            int displayId, float ratio, int userId) {
        final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
        if (displayContent != null) {
            displayContent.setForcedDensityRatio(ratio, userId);
            return;
        }

        final DisplayInfo info = mDisplayManagerInternal.getDisplayInfo(displayId);
        if (info == null) {
            ProtoLog.e(WM_ERROR, "Failed to get information about logical display %d. "
                    + "Skip setting forced display density.", displayId);
            return;
        }
        mDisplayWindowSettings.setForcedDensityRatio(info, ratio);
    }

    @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
    @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
    @Override
    @Override
    public void setConfigurationChangeSettingsForUser(
    public void setConfigurationChangeSettingsForUser(
Loading