Disables display content scaling for foldables
When setting folded area with changes both in width and height (set
0,0,540,1080 to a 1080x2160 device), the content of display will be
auto-scaled to physical display size. It is not an expected behavior
for foldable devices. Disable auto-scale to fix this issue.
1. LogicalDisplay.configureDisplayLocked() scales the contents according
the DisplayInfo.flags.
2. DisplayInfo.flags should not be overridden by design for a logical
display.
3. Adds disableDisplayScaling() for DisplayFoldController to bypass that.
Bug: 123245311
Test: atest WmTests
Test: adb shell wm folded-area 0,0,840,1260
Change-Id: I9a24c5d56799981b4f2cfe82fdf1898d87193681
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 1af9cde..43ea682 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -171,6 +171,15 @@
public abstract void setDisplayOffsets(int displayId, int x, int y);
/**
+ * Disables scaling for a display.
+ *
+ * @param displayId The logical display id to disable scaling for.
+ * @param disableScaling {@code true} to disable scaling,
+ * {@code false} to use the default scaling behavior of the logical display.
+ */
+ public abstract void setDisplayScalingDisabled(int displayId, boolean disableScaling);
+
+ /**
* Provide a list of UIDs that are present on the display and are allowed to access it.
*
* @param displayAccessUIDs Mapping displayId -> int array of UIDs.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b99ba7e..b2509e9 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1222,6 +1222,22 @@
}
}
+ private void setDisplayScalingDisabledInternal(int displayId, boolean disable) {
+ synchronized (mSyncRoot) {
+ final LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display == null) {
+ return;
+ }
+ if (display.isDisplayScalingDisabled() != disable) {
+ if (DEBUG) {
+ Slog.d(TAG, "Display " + displayId + " content scaling disabled = " + disable);
+ }
+ display.setDisplayScalingDisabledLocked(disable);
+ scheduleTraversalLocked(false);
+ }
+ }
+ }
+
// Updates the lists of UIDs that are present on displays.
private void setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs) {
synchronized (mSyncRoot) {
@@ -2359,6 +2375,11 @@
}
@Override
+ public void setDisplayScalingDisabled(int displayId, boolean disableScaling) {
+ setDisplayScalingDisabledInternal(displayId, disableScaling);
+ }
+
+ @Override
public void setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs) {
setDisplayAccessUIDsInternal(newDisplayAccessUIDs);
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 7414e55..7ee8422 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -94,6 +94,14 @@
private int mDisplayOffsetX;
private int mDisplayOffsetY;
+ /**
+ * {@code true} if display scaling is disabled, or {@code false} if the default scaling mode
+ * is used.
+ * @see #isDisplayScalingDisabled()
+ * @see #setDisplayScalingDisabledLocked(boolean)
+ */
+ private boolean mDisplayScalingDisabled;
+
// Temporary rectangle used when needed.
private final Rect mTempLayerStackRect = new Rect();
private final Rect mTempDisplayRect = new Rect();
@@ -397,7 +405,7 @@
// multiplying the fractions by the product of their denominators before
// comparing them.
int displayRectWidth, displayRectHeight;
- if ((displayInfo.flags & Display.FLAG_SCALING_DISABLED) != 0) {
+ if ((displayInfo.flags & Display.FLAG_SCALING_DISABLED) != 0 || mDisplayScalingDisabled) {
displayRectWidth = displayInfo.logicalWidth;
displayRectHeight = displayInfo.logicalHeight;
} else if (physWidth * displayInfo.logicalHeight
@@ -501,6 +509,24 @@
mDisplayOffsetY = y;
}
+ /**
+ * @return {@code true} if display scaling is disabled, or {@code false} if the default scaling
+ * mode is used.
+ */
+ public boolean isDisplayScalingDisabled() {
+ return mDisplayScalingDisabled;
+ }
+
+ /**
+ * Disables scaling for a display.
+ *
+ * @param disableScaling {@code true} to disable scaling,
+ * {@code false} to use the default scaling behavior of the logical display.
+ */
+ public void setDisplayScalingDisabledLocked(boolean disableScaling) {
+ mDisplayScalingDisabled = disableScaling;
+ }
+
public void dumpLocked(PrintWriter pw) {
pw.println("mDisplayId=" + mDisplayId);
pw.println("mLayerStack=" + mLayerStack);
@@ -508,6 +534,7 @@
pw.println("mRequestedMode=" + mRequestedModeId);
pw.println("mRequestedColorMode=" + mRequestedColorMode);
pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")");
+ pw.println("mDisplayScalingDisabled=" + mDisplayScalingDisabled);
pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ?
mPrimaryDisplayDevice.getNameLocked() : "null"));
pw.println("mBaseDisplayInfo=" + mBaseDisplayInfo);
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index 0c6b773..cf026e9 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -87,10 +87,13 @@
final int dy = (mNonOverrideDisplayInfo.logicalHeight - foldedArea.height()) / 2
- foldedArea.top;
+ // Bypass scaling otherwise LogicalDisplay will scale contents by default.
+ mDisplayManagerInternal.setDisplayScalingDisabled(mDisplayId, true);
mWindowManagerInternal.setForcedDisplaySize(mDisplayId,
foldedArea.width(), foldedArea.height());
mDisplayManagerInternal.setDisplayOffsets(mDisplayId, -dx, -dy);
} else {
+ mDisplayManagerInternal.setDisplayScalingDisabled(mDisplayId, false);
mWindowManagerInternal.clearForcedDisplaySize(mDisplayId);
mDisplayManagerInternal.setDisplayOffsets(mDisplayId, 0, 0);
}