diff options
5 files changed, 164 insertions, 16 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 214a3a15bb44..55eea876eadb 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -46,6 +46,7 @@ import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.STATE_UNKNOWN; +import static android.view.Display.TYPE_EXTERNAL; import static android.view.Display.isSuspendedState; import static android.view.InsetsSource.ID_IME; import static android.view.Surface.ROTATION_0; @@ -155,6 +156,7 @@ import static com.android.server.wm.utils.DisplayInfoOverrides.WM_OVERRIDE_FIELD import static com.android.server.wm.utils.DisplayInfoOverrides.copyDisplayInfoFields; import static com.android.server.wm.utils.RegionUtils.forEachRectReverse; import static com.android.server.wm.utils.RegionUtils.rectListToRegion; +import static com.android.window.flags.Flags.enablePersistingDensityScaleForConnectedDisplays; import android.annotation.IntDef; import android.annotation.NonNull; @@ -426,6 +428,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int) */ int mBaseDisplayDensity = 0; + + /** + * Ratio between overridden display density for current user and the initial display density, + * used only for external displays. + */ + float mExternalDisplayForcedDensityRatio = 0.0f; boolean mIsDensityForced = false; /** @@ -3065,6 +3073,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mDisplayPolicy.physicalDisplayChanged(); } + // Real display metrics changed, so we should also update initial values. + mInitialDisplayWidth = newWidth; + mInitialDisplayHeight = newHeight; + mInitialDisplayDensity = newDensity; + mInitialPhysicalXDpi = newXDpi; + mInitialPhysicalYDpi = newYDpi; + mInitialDisplayCutout = newCutout; + mInitialRoundedCorners = newRoundedCorners; + mInitialDisplayShape = newDisplayShape; + mCurrentUniqueDisplayId = newUniqueId; + // If there is an override set for base values - use it, otherwise use new values. updateBaseDisplayMetrics(mIsSizeForced ? mBaseDisplayWidth : newWidth, mIsSizeForced ? mBaseDisplayHeight : newHeight, @@ -3081,16 +3100,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mWmService.mDisplayWindowSettings.applyRotationSettingsToDisplayLocked(this); } - // Real display metrics changed, so we should also update initial values. - mInitialDisplayWidth = newWidth; - mInitialDisplayHeight = newHeight; - mInitialDisplayDensity = newDensity; - mInitialPhysicalXDpi = newXDpi; - mInitialPhysicalYDpi = newYDpi; - mInitialDisplayCutout = newCutout; - mInitialRoundedCorners = newRoundedCorners; - mInitialDisplayShape = newDisplayShape; - mCurrentUniqueDisplayId = newUniqueId; reconfigureDisplayLocked(); if (physicalDisplayChanged) { @@ -3143,6 +3152,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp + mBaseDisplayHeight + " on display:" + getDisplayId()); } } + // Update the base density if there is a forced density ratio. + if (enablePersistingDensityScaleForConnectedDisplays() + && mIsDensityForced && mExternalDisplayForcedDensityRatio != 0.0f) { + mBaseDisplayDensity = (int) + (mInitialDisplayDensity * mExternalDisplayForcedDensityRatio + 0.5); + } if (mDisplayReady && !mDisplayPolicy.shouldKeepCurrentDecorInsets()) { mDisplayPolicy.mDecorInsets.invalidate(); } @@ -3172,6 +3187,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (density == getInitialDisplayDensity()) { density = 0; } + // Save the new density ratio to settings for external displays. + if (enablePersistingDensityScaleForConnectedDisplays() + && mDisplayInfo.type == TYPE_EXTERNAL) { + mExternalDisplayForcedDensityRatio = (float) + mBaseDisplayDensity / getInitialDisplayDensity(); + mWmService.mDisplayWindowSettings.setForcedDensityRatio(getDisplayInfo(), + mExternalDisplayForcedDensityRatio); + } mWmService.mDisplayWindowSettings.setForcedDensity(getDisplayInfo(), density, userId); } diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index 117387553f30..c6892e941fc6 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -23,11 +23,10 @@ import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY; import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY; import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED; +import static com.android.server.display.feature.flags.Flags.enableDisplayContentModeManagement; import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO; import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED; -import static com.android.server.display.feature.flags.Flags.enableDisplayContentModeManagement; - import android.annotation.NonNull; import android.annotation.Nullable; import android.app.WindowConfiguration; @@ -100,6 +99,13 @@ class DisplayWindowSettings { mSettingsProvider.updateOverrideSettings(info, overrideSettings); } + void setForcedDensityRatio(@NonNull DisplayInfo info, float ratio) { + final SettingsProvider.SettingsEntry overrideSettings = + mSettingsProvider.getOverrideSettings(info); + overrideSettings.mForcedDensityRatio = ratio; + mSettingsProvider.updateOverrideSettings(info, overrideSettings); + } + void setForcedScalingMode(@NonNull DisplayContent displayContent, @ForceScalingMode int mode) { if (displayContent.isDefaultDisplay) { Settings.Global.putInt(mService.mContext.getContentResolver(), @@ -367,6 +373,7 @@ class DisplayWindowSettings { mFixedToUserRotation); final boolean hasDensityOverride = settings.mForcedDensity != 0; + final boolean hasDensityOverrideRatio = settings.mForcedDensityRatio != 0.0f; final boolean hasSizeOverride = settings.mForcedWidth != 0 && settings.mForcedHeight != 0; dc.mIsDensityForced = hasDensityOverride; dc.mIsSizeForced = hasSizeOverride; @@ -378,6 +385,10 @@ class DisplayWindowSettings { final int height = hasSizeOverride ? settings.mForcedHeight : dc.mInitialDisplayHeight; final int density = hasDensityOverride ? settings.mForcedDensity : dc.getInitialDisplayDensity(); + if (hasDensityOverrideRatio) { + dc.mExternalDisplayForcedDensityRatio = settings.mForcedDensityRatio; + } + dc.updateBaseDisplayMetrics(width, height, density, dc.mBaseDisplayPhysicalXDpi, dc.mBaseDisplayPhysicalYDpi); @@ -496,6 +507,13 @@ class DisplayWindowSettings { int mForcedWidth; int mForcedHeight; int mForcedDensity; + /** + * The ratio of the forced density to the initial density of the display. This is only + * saved for external displays, and used to make sure ratio between forced density and + * initial density persist when a resolution change happens. Ratio is updated when + * mForcedDensity is changed. + */ + float mForcedDensityRatio; @Nullable @ForceScalingMode Integer mForcedScalingMode; @@ -561,6 +579,10 @@ class DisplayWindowSettings { mForcedDensity = other.mForcedDensity; changed = true; } + if (other.mForcedDensityRatio != mForcedDensityRatio) { + mForcedDensityRatio = other.mForcedDensityRatio; + changed = true; + } if (!Objects.equals(other.mForcedScalingMode, mForcedScalingMode)) { mForcedScalingMode = other.mForcedScalingMode; changed = true; @@ -649,6 +671,11 @@ class DisplayWindowSettings { mForcedDensity = delta.mForcedDensity; changed = true; } + if (delta.mForcedDensityRatio != 0 + && delta.mForcedDensityRatio != mForcedDensityRatio) { + mForcedDensityRatio = delta.mForcedDensityRatio; + changed = true; + } if (delta.mForcedScalingMode != null && !Objects.equals(delta.mForcedScalingMode, mForcedScalingMode)) { mForcedScalingMode = delta.mForcedScalingMode; @@ -713,6 +740,7 @@ class DisplayWindowSettings { && mUserRotationMode == null && mUserRotation == null && mForcedWidth == 0 && mForcedHeight == 0 && mForcedDensity == 0 + && mForcedDensityRatio == 0.0f && mForcedScalingMode == null && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED && mShouldShowWithInsecureKeyguard == null @@ -736,6 +764,7 @@ class DisplayWindowSettings { && mForcedHeight == that.mForcedHeight && mForcedDensity == that.mForcedDensity && mRemoveContentMode == that.mRemoveContentMode + && mForcedDensityRatio == that.mForcedDensityRatio && Objects.equals(mUserRotationMode, that.mUserRotationMode) && Objects.equals(mUserRotation, that.mUserRotation) && Objects.equals(mForcedScalingMode, that.mForcedScalingMode) @@ -755,10 +784,11 @@ class DisplayWindowSettings { @Override public int hashCode() { return Objects.hash(mWindowingMode, mUserRotationMode, mUserRotation, mForcedWidth, - mForcedHeight, mForcedDensity, mForcedScalingMode, mRemoveContentMode, - mShouldShowWithInsecureKeyguard, mShouldShowSystemDecors, mIsHomeSupported, - mImePolicy, mFixedToUserRotation, mIgnoreOrientationRequest, - mIgnoreDisplayCutout, mDontMoveToTop, mIgnoreActivitySizeRestrictions); + mForcedHeight, mForcedDensity, mForcedDensityRatio, mForcedScalingMode, + mRemoveContentMode, mShouldShowWithInsecureKeyguard, + mShouldShowSystemDecors, mIsHomeSupported, mImePolicy, mFixedToUserRotation, + mIgnoreOrientationRequest, mIgnoreDisplayCutout, mDontMoveToTop, + mIgnoreActivitySizeRestrictions); } @Override @@ -770,6 +800,7 @@ class DisplayWindowSettings { + ", mForcedWidth=" + mForcedWidth + ", mForcedHeight=" + mForcedHeight + ", mForcedDensity=" + mForcedDensity + + ", mForcedDensityRatio=" + mForcedDensityRatio + ", mForcedScalingMode=" + mForcedScalingMode + ", mRemoveContentMode=" + mRemoveContentMode + ", mShouldShowWithInsecureKeyguard=" + mShouldShowWithInsecureKeyguard diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java index 7135c3b8cda8..e7a1fdd120f7 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java @@ -511,6 +511,8 @@ class DisplayWindowSettingsProvider implements SettingsProvider { 0 /* defaultValue */); settingsEntry.mForcedDensity = getIntAttribute(parser, "forcedDensity", 0 /* defaultValue */); + settingsEntry.mForcedDensityRatio = parser.getAttributeFloat(null, "forcedDensityRatio", + 0.0f /* defaultValue */); settingsEntry.mForcedScalingMode = getIntegerAttribute(parser, "forcedScalingMode", null /* defaultValue */); settingsEntry.mRemoveContentMode = getIntAttribute(parser, "removeContentMode", @@ -599,6 +601,10 @@ class DisplayWindowSettingsProvider implements SettingsProvider { if (settingsEntry.mForcedDensity != 0) { out.attributeInt(null, "forcedDensity", settingsEntry.mForcedDensity); } + if (settingsEntry.mForcedDensityRatio != 0.0f) { + out.attributeFloat(null, "forcedDensityRatio", + settingsEntry.mForcedDensityRatio); + } if (settingsEntry.mForcedScalingMode != null) { out.attributeInt(null, "forcedScalingMode", settingsEntry.mForcedScalingMode); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index a99bc4966c03..76609dd58dad 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -83,6 +83,7 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING; import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE; import static com.android.server.display.feature.flags.Flags.FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT; +import static com.android.window.flags.Flags.FLAG_ENABLE_PERSISTING_DENSITY_SCALE_FOR_CONNECTED_DISPLAYS; import static com.google.common.truth.Truth.assertThat; @@ -2872,6 +2873,74 @@ public class DisplayContentTests extends WindowTestsBase { assertFalse(dc.mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(dc)); } + @EnableFlags(FLAG_ENABLE_PERSISTING_DENSITY_SCALE_FOR_CONNECTED_DISPLAYS) + @Test + public void testForcedDensityRatioSetForExternalDisplays_persistDensityScaleFlagEnabled() { + final DisplayInfo displayInfo = new DisplayInfo(mDisplayInfo); + displayInfo.displayId = DEFAULT_DISPLAY + 1; + displayInfo.type = Display.TYPE_EXTERNAL; + final DisplayContent displayContent = createNewDisplay(displayInfo); + final int baseWidth = 1280; + final int baseHeight = 720; + final int baseDensity = 320; + final float baseXDpi = 60; + final float baseYDpi = 60; + + displayContent.mInitialDisplayWidth = baseWidth; + displayContent.mInitialDisplayHeight = baseHeight; + displayContent.mInitialDisplayDensity = baseDensity; + displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity, baseXDpi, + baseYDpi); + + final int forcedDensity = 640; + + // Verify that forcing the density is honored and the size doesn't change. + displayContent.setForcedDensity(forcedDensity, 0 /* userId */); + verifySizes(displayContent, baseWidth, baseHeight, forcedDensity); + + // Verify that density ratio is set correctly. + assertEquals((float) forcedDensity / baseDensity, + displayContent.mExternalDisplayForcedDensityRatio, 0.01); + } + + @EnableFlags(FLAG_ENABLE_PERSISTING_DENSITY_SCALE_FOR_CONNECTED_DISPLAYS) + @Test + public void testForcedDensityUpdateForExternalDisplays_persistDensityScaleFlagEnabled() { + final DisplayInfo displayInfo = new DisplayInfo(mDisplayInfo); + displayInfo.displayId = DEFAULT_DISPLAY + 1; + displayInfo.type = Display.TYPE_EXTERNAL; + final DisplayContent displayContent = createNewDisplay(displayInfo); + final int baseWidth = 1280; + final int baseHeight = 720; + final int baseDensity = 320; + final float baseXDpi = 60; + final float baseYDpi = 60; + + displayContent.mInitialDisplayWidth = baseWidth; + displayContent.mInitialDisplayHeight = baseHeight; + displayContent.mInitialDisplayDensity = baseDensity; + displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity, baseXDpi, + baseYDpi); + + final int forcedDensity = 640; + + // Verify that forcing the density is honored and the size doesn't change. + displayContent.setForcedDensity(forcedDensity, 0 /* userId */); + verifySizes(displayContent, baseWidth, baseHeight, forcedDensity); + + // Verify that density ratio is set correctly. + assertEquals((float) 2.0f, + displayContent.mExternalDisplayForcedDensityRatio, 0.001); + + + displayContent.mInitialDisplayDensity = 160; + displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity, baseXDpi, + baseYDpi); + + // Verify that forced density is updated based on the ratio. + assertEquals(320, displayContent.mBaseDisplayDensity); + } + @EnableFlags(FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT) @Test public void testSetShouldShowSystemDecorations_nonDefaultNonPrivateDisplay() { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java index b1cad513ad83..a57577a96f79 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java @@ -42,6 +42,7 @@ import static org.mockito.Matchers.eq; import android.annotation.NonNull; import android.app.WindowConfiguration; import android.content.ContentResolver; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.provider.Settings; import android.view.Display; @@ -53,6 +54,7 @@ import androidx.test.filters.SmallTest; import com.android.server.LocalServices; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.DisplayWindowSettings.SettingsProvider.SettingsEntry; +import com.android.window.flags.Flags; import org.junit.Before; import org.junit.Test; @@ -272,6 +274,23 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mSecondaryDisplay.mBaseDisplayDensity); } + @EnableFlags(Flags.FLAG_ENABLE_PERSISTING_DENSITY_SCALE_FOR_CONNECTED_DISPLAYS) + @Test + public void testSetForcedDensityRatio() { + mDisplayWindowSettings.setForcedDensity(mSecondaryDisplay.getDisplayInfo(), + 300 /* density */, 0 /* userId */); + mDisplayWindowSettings.setForcedDensityRatio(mSecondaryDisplay.getDisplayInfo(), + 2.0f /* ratio */); + mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay); + + assertEquals(mSecondaryDisplay.mInitialDisplayDensity * 2.0f, + mSecondaryDisplay.mBaseDisplayDensity, 0.01); + + mWm.clearForcedDisplayDensityForUser(mSecondaryDisplay.getDisplayId(), 0 /* userId */); + assertEquals(mSecondaryDisplay.mInitialDisplayDensity, + mSecondaryDisplay.mBaseDisplayDensity); + } + @Test public void testSetForcedScalingMode() { mDisplayWindowSettings.setForcedScalingMode(mSecondaryDisplay, |