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

Commit cd097993 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 and
WM is notified about them with a message. In most cases there is an
override obtained from WM and WM doesn't get new values from
LogicalDisplay#getDisplayInfoLocked().

- With this CL:
WM will requests real updated values from DM without any overrides
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. Also it will always update initial display metrics if there
is a real change detected.

Bug: 35258051
Bug: 34164473
Bug: 36518752
Test: android.server.cts.ActivityManagerDisplayTests
Test: #testDisplayResize
Test: #testForceDisplayMetrics
Change-Id: I2495c27797f11f9aaee4ea06648a8ccd29ac5b62
parent 3f2bbcbe
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -101,6 +101,16 @@ public abstract class DisplayManagerInternal {
    public abstract void setDisplayInfoOverrideFromWindowManager(
            int displayId, DisplayInfo info);

    /**
     * Get current display info without override from WindowManager.
     * Current implementation of LogicalDisplay#getDisplayInfoLocked() always returns display info
     * with overrides from WM if set. This method can be used for getting real display size without
     * overrides to determine if real changes to display metrics happened.
     * @param displayId Id of the target display.
     * @param outInfo {@link DisplayInfo} to fill.
     */
    public abstract void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo);

    /**
     * Called by the window manager to perform traversals while holding a
     * surface flinger transaction.
+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.
+17 −0
Original line number Diff line number Diff line
@@ -339,6 +339,18 @@ public final class DisplayManagerService extends SystemService {
        }
    }

    /**
     * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
     */
    private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) {
        synchronized (mSyncRoot) {
            final LogicalDisplay display = mLogicalDisplays.get(displayId);
            if (display != null) {
                display.getNonOverrideDisplayInfoLocked(outInfo);
            }
        }
    }

    private void performTraversalInTransactionFromWindowManagerInternal() {
        synchronized (mSyncRoot) {
            if (!mPendingTraversal) {
@@ -1662,6 +1674,11 @@ public final class DisplayManagerService extends SystemService {
            setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
        }

        @Override
        public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) {
            getNonOverrideDisplayInfoInternal(displayId, outInfo);
        }

        @Override
        public void performTraversalInTransactionFromWindowManager() {
            performTraversalInTransactionFromWindowManagerInternal();
+20 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.display;

import android.graphics.Rect;
import android.hardware.display.DisplayManagerInternal;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -62,7 +63,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
@@ -141,6 +153,13 @@ final class LogicalDisplay {
        return mInfo;
    }

    /**
     * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
     */
    void getNonOverrideDisplayInfoLocked(DisplayInfo outInfo) {
        outInfo.copyFrom(mBaseDisplayInfo);
    }

    /**
     * Sets overridden logical display information from the window manager.
     * This method can be used to adjust application insets, rotation, and other
+57 −4
Original line number Diff line number Diff line
@@ -180,11 +180,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();
@@ -1497,8 +1509,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    }

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

        mDisplay.getDisplayInfo(mDisplayInfo);
        mDisplay.getMetrics(mDisplayMetrics);

        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
            mTaskStackContainers.get(i).updateDisplayInfo(null);
        }
@@ -1514,10 +1530,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) {
@@ -1547,6 +1564,42 @@ 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() {
        // Get real display metrics without overrides from WM.
        mService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo);
        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;
        final int newDensity = mDisplayInfo.logicalDensityDpi;

        final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth
                || mInitialDisplayHeight != newHeight
                || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi;

        if (displayMetricsChanged) {
            // Check if display size or density is forced.
            final boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth
                    || mBaseDisplayHeight != mInitialDisplayHeight;
            final boolean isDisplayDensityForced = mBaseDisplayDensity != mInitialDisplayDensity;

            // If there is an override set for base values - use it, otherwise use new values.
            updateBaseDisplayMetrics(isDisplaySizeForced ? mBaseDisplayWidth : newWidth,
                    isDisplaySizeForced ? mBaseDisplayHeight : newHeight,
                    isDisplayDensityForced ? mBaseDisplayDensity : newDensity);

            // Real display metrics changed, so we should also update initial values.
            mInitialDisplayWidth = newWidth;
            mInitialDisplayHeight = newHeight;
            mInitialDisplayDensity = newDensity;
            mService.reconfigureDisplayLocked(this);
        }
    }

    /** Sets the maximum width the screen resolution can be */
    void setMaxUiWidth(int width) {
        if (DEBUG_DISPLAY) {
Loading