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

Commit eddb7c09 authored by Andrii Kulian's avatar Andrii Kulian
Browse files

Update display contents when metrics change

There are two separate overrides for display metrics in DisplayManager
and WindowManager:
- In DM - LogicalDisplay#mOverrideDisplayInfo, in most cases not null.
- In WM - DisplayContent#mBaseDisplayWidth/Height/Density, different
from #mInitialDisplayWidth/Height/Density values when some metrics are
forced.

When display was resized its windows weren't updated because of
two problems: old LogicaDisplay#mOverrideDisplayInfo was preventing
WM from detecting the change and override (base) display metrics were
never updated by resize.

When display size changes:
- Before this CL:
DM receives DISPLAY_CHANGED event, it updates internal values.
In most cases there is an override obtained from WM and WM doesn't
get new values from LogicalDisplay#getDisplayInfoLocked().

- With this CL:
DM receives DISPLAY_CHANGED event, it updates internal values and
resets the override received from WM. WM will receive updated values
and will decide whether to apply them or not: if there is no override
in WM - it will apply values from WM, otherwise it will keep the
override. In both cases WM will eventually update its own override
and will update the override in DM.

Bug: 35258051
Bug: 34164473
Test: android.server.cts.ActivityManagerDisplayTests
Test: #testDisplayResize
Test: #testForceDisplayMetrics
Change-Id: I80795434a6a35adb0577fbce334d76fabd2fa03d
parent a5c560b3
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ import java.util.Arrays;
 * <li>The real display area specifies the part of the display that contains content
 * including the system decorations.  Even so, the real display area may be smaller than the
 * physical size of the display if the window manager is emulating a smaller display
 * using (adb shell am display-size).  Use the following methods to query the
 * using (adb shell wm size).  Use the following methods to query the
 * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
 * </ul>
 * </p><p>
@@ -947,7 +947,7 @@ public final class Display {
     * The size is adjusted based on the current rotation of the display.
     * </p><p>
     * The real size may be smaller than the physical size of the screen when the
     * window manager is emulating a smaller display (using adb shell am display-size).
     * window manager is emulating a smaller display (using adb shell wm size).
     * </p>
     *
     * @param outSize Set to the real size of the display.
+15 −1
Original line number Diff line number Diff line
@@ -62,7 +62,18 @@ final class LogicalDisplay {

    private final int mDisplayId;
    private final int mLayerStack;
    private DisplayInfo mOverrideDisplayInfo; // set by the window manager
    /**
     * Override information set by the window manager. Will be reported instead of {@link #mInfo}
     * if not null.
     * @see #setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo)
     * @see #getDisplayInfoLocked()
     */
    private DisplayInfo mOverrideDisplayInfo;
    /**
     * Current display info. Initialized with {@link #mBaseDisplayInfo}. Set to {@code null} if
     * needs to be updated.
     * @see #getDisplayInfoLocked()
     */
    private DisplayInfo mInfo;

    // The display device that this logical display is based on and which
@@ -261,6 +272,9 @@ final class LogicalDisplay {

            mPrimaryDisplayDeviceInfo = deviceInfo;
            mInfo = null;
            // Make sure that WM will be notified of new changes. It will then decide whether to
            // apply them or not and will set the value again.
            mOverrideDisplayInfo = null;
        }
    }

+65 −4
Original line number Diff line number Diff line
@@ -179,11 +179,23 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    // Mapping from a token IBinder to a WindowToken object on this display.
    private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();

    // Initial display metrics.
    int mInitialDisplayWidth = 0;
    int mInitialDisplayHeight = 0;
    int mInitialDisplayDensity = 0;

    /**
     * Overridden display size. Initialized with {@link #mInitialDisplayWidth}
     * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size".
     * @see WindowManagerService#setForcedDisplaySize(int, int, int)
     */
    int mBaseDisplayWidth = 0;
    int mBaseDisplayHeight = 0;
    /**
     * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity}
     * but can be set from Settings or via shell command "adb shell wm density".
     * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
     */
    int mBaseDisplayDensity = 0;
    boolean mDisplayScalingDisabled;
    private final DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -1511,6 +1523,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    void updateDisplayInfo() {
        mDisplay.getDisplayInfo(mDisplayInfo);
        mDisplay.getMetrics(mDisplayMetrics);

        // Check if display metrics changed and update base values if needed.
        updateBaseDisplayMetricsIfNeeded();

        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
            mTaskStackContainers.get(i).updateDisplayInfo(null);
        }
@@ -1526,10 +1542,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            }
        }

        mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
        mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
        mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
        updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
                mDisplayInfo.logicalDensityDpi);
        mInitialDisplayWidth = mDisplayInfo.logicalWidth;
        mInitialDisplayHeight = mDisplayInfo.logicalHeight;
        mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
    }

    void getLogicalDisplayRect(Rect out) {
@@ -1559,6 +1576,50 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        }
    }

    /**
     * If display metrics changed, overrides are not set and it's not just a rotation - update base
     * values.
     */
    private void updateBaseDisplayMetricsIfNeeded() {
        final int orientation = mDisplayInfo.rotation;
        final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
        final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
        final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
        int density = mDisplayInfo.logicalDensityDpi;

        boolean displayMetricsChanged = false;

        // Check if display size is not forced and changed in new display info.
        boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth
                || mBaseDisplayHeight != mInitialDisplayHeight;
        if (!isDisplaySizeForced) {
            displayMetricsChanged = mBaseDisplayWidth != newWidth
                    || mBaseDisplayHeight != newHeight;
        }

        // Check if display density is not forced and changed in new display info.
        final int forcedDensity = mBaseDisplayDensity != mInitialDisplayDensity
                ? mBaseDisplayDensity : 0;
        if (forcedDensity != 0) {
            density = forcedDensity;
        } else {
            displayMetricsChanged |= mBaseDisplayDensity != mDisplayInfo.logicalDensityDpi;
        }

        if (displayMetricsChanged) {
            updateBaseDisplayMetrics(newWidth, newHeight, density);
            mService.reconfigureDisplayLocked(this);
        }
    }

    /** Update base (override) display metrics. */
    void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) {
        mBaseDisplayWidth = baseWidth;
        mBaseDisplayHeight = baseHeight;
        mBaseDisplayDensity = baseDensity;
        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
    }

    void getContentRect(Rect out) {
        out.set(mContentRect);
    }
+3 −4
Original line number Diff line number Diff line
@@ -5324,8 +5324,8 @@ public class WindowManagerService extends IWindowManager.Stub
                    if (displayContent.mBaseDisplayWidth != width
                            || displayContent.mBaseDisplayHeight != height) {
                        Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
                        displayContent.mBaseDisplayWidth = width;
                        displayContent.mBaseDisplayHeight = height;
                        displayContent.updateBaseDisplayMetrics(width, height,
                                displayContent.mBaseDisplayDensity);
                    }
                } catch (NumberFormatException ex) {
                }
@@ -5350,8 +5350,7 @@ public class WindowManagerService extends IWindowManager.Stub
    // displayContent must not be null
    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
        Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
        displayContent.mBaseDisplayWidth = width;
        displayContent.mBaseDisplayHeight = height;
        displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
        reconfigureDisplayLocked(displayContent);
    }