From cd097993399f94aa663c5fad50e444b75e6ee5dd Mon Sep 17 00:00:00 2001
From: Andrii Kulian
Date: Thu, 23 Mar 2017 18:31:59 -0700
Subject: [PATCH] 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
---
.../display/DisplayManagerInternal.java | 10 +++
core/java/android/view/Display.java | 4 +-
.../server/display/DisplayManagerService.java | 17 ++++++
.../server/display/LogicalDisplay.java | 21 ++++++-
.../com/android/server/wm/DisplayContent.java | 61 +++++++++++++++++--
.../server/wm/WindowManagerService.java | 7 +--
6 files changed, 109 insertions(+), 11 deletions(-)
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index b27600800cc69..e845359a35c40 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -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.
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5494377ceebd1..6dedbde01995a 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -50,7 +50,7 @@ import java.util.Arrays;
* 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}.
*
*
@@ -947,7 +947,7 @@ public final class Display {
* The size is adjusted based on the current rotation of the display.
*
* 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).
*
*
* @param outSize Set to the real size of the display.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a1a74377cf620..ddd918fdcc5d4 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -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();
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index a947b41067941..addad0b413a38 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -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
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 3c68e4ff4e7fd..da524c764ebaa 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 @@ class DisplayContent extends WindowContainer 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= 0; --i) {
mTaskStackContainers.get(i).updateDisplayInfo(null);
}
@@ -1514,10 +1530,11 @@ class DisplayContent extends WindowContainer