Don't set override display info for ActivityView
ActivityView content should never be letter- or pillar-boxed
and it doesn't have overscan areas, so we can skip setting
display override info for a virtual display that backs it.
Bug: 72220802
Test: Manually resize with ActivityView demo app
Change-Id: I211449eaea50ec5d3214d63e7eb93a1d2ed2c0fd
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c35c05d..e2e1690 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -305,6 +305,11 @@
int pendingLayoutChanges;
// TODO(multi-display): remove some of the usages.
boolean isDefaultDisplay;
+ /**
+ * Flag indicating whether WindowManager should override info for this display in
+ * DisplayManager.
+ */
+ boolean mShouldOverrideDisplayConfiguration = true;
/** Window tokens that are in the process of exiting, but still on screen for animations. */
final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
@@ -1177,8 +1182,14 @@
mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
}
+ // We usually set the override info in DisplayManager so that we get consistent display
+ // metrics values when displays are changing and don't send out new values until WM is aware
+ // of them. However, we don't do this for displays that serve as containers for ActivityView
+ // because we don't want letter-/pillar-boxing during resize.
+ final DisplayInfo overrideDisplayInfo = mShouldOverrideDisplayConfiguration
+ ? mDisplayInfo : null;
mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
- mDisplayInfo);
+ overrideDisplayInfo);
mBaseDisplayRect.set(0, 0, dw, dh);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9f8de58b..5f0769d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1117,17 +1117,7 @@
throw new IllegalStateException("Display has not been initialialized");
}
- DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-
- // Adding a window is an exception where the WindowManagerService can create the
- // display instead of waiting for the ActivityManagerService to drive creation.
- if (displayContent == null) {
- final Display display = mDisplayManager.getDisplay(displayId);
-
- if (display != null) {
- displayContent = mRoot.createDisplayContent(display, null /* controller */);
- }
- }
+ final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
if (displayContent == null) {
Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
@@ -1493,6 +1483,32 @@
return res;
}
+ /**
+ * Get existing {@link DisplayContent} or create a new one if the display is registered in
+ * DisplayManager.
+ *
+ * NOTE: This should only be used in cases when there is a chance that a {@link DisplayContent}
+ * that corresponds to a display just added to DisplayManager has not yet been created. This
+ * usually means that the call of this method was initiated from outside of Activity or Window
+ * Manager. In most cases the regular getter should be used.
+ * @see RootWindowContainer#getDisplayContent(int)
+ */
+ private DisplayContent getDisplayContentOrCreate(int displayId) {
+ DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+
+ // Create an instance if possible instead of waiting for the ActivityManagerService to drive
+ // the creation.
+ if (displayContent == null) {
+ final Display display = mDisplayManager.getDisplay(displayId);
+
+ if (display != null) {
+ displayContent = mRoot.createDisplayContent(display, null /* controller */);
+ }
+ }
+
+ return displayContent;
+ }
+
private boolean doesAddToastWindowRequireToken(String packageName, int callingUid,
WindowState attachedWindow) {
// Try using the target SDK of the root window
@@ -6987,6 +7003,24 @@
}
@Override
+ public void dontOverrideDisplayInfo(int displayId) {
+ synchronized (mWindowMap) {
+ final DisplayContent dc = getDisplayContentOrCreate(displayId);
+ if (dc == null) {
+ throw new IllegalArgumentException(
+ "Trying to register a non existent display.");
+ }
+ // We usually set the override info in DisplayManager so that we get consistent
+ // values when displays are changing. However, we don't do this for displays that
+ // serve as containers for ActivityViews because we don't want letter-/pillar-boxing
+ // during resize.
+ dc.mShouldOverrideDisplayConfiguration = false;
+ mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId,
+ null /* info */);
+ }
+ }
+
+ @Override
public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
throws RemoteException {
if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 4f49a4a..b645700 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -31,7 +31,10 @@
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -457,6 +460,18 @@
SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
}
+ @Test
+ public void testDisableDisplayInfoOverrideFromWindowManager() {
+ final DisplayContent dc = createNewDisplay();
+
+ assertTrue(dc.mShouldOverrideDisplayConfiguration);
+ sWm.dontOverrideDisplayInfo(dc.getDisplayId());
+
+ assertFalse(dc.mShouldOverrideDisplayConfiguration);
+ verify(sWm.mDisplayManagerInternal, times(1))
+ .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
+ }
+
private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
int expectedBaseHeight, int expectedBaseDensity) {
assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);