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
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 3c68e4f..da524c7 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -180,11 +180,23 @@
// 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 @@
}
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 @@
}
}
- 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 @@
}
}
+ /**
+ * 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) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 95fbbb8..1691d14 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5312,8 +5312,8 @@
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) {
}
@@ -5338,8 +5338,7 @@
// 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);
}