diff options
9 files changed, 83 insertions, 23 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 0abd5eaaf2aa..0f67262bf901 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -4848,7 +4848,7 @@ public class PackageParser { } /** - * Sets every the max aspect ratio of every child activity that doesn't already have an aspect + * Sets every the min aspect ratio of every child activity that doesn't already have an aspect * ratio set. */ private void setMinAspectRatio(Package owner) { diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index d14164f69850..dae2692c7722 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3252,7 +3252,7 @@ skinny aspect ratio that is not expected to be widely used. --> <item name="config_pictureInPictureMinAspectRatio" format="float" type="dimen">0.41841004184</item> - <!-- The minimum aspect ratio (width/height) that is supported for picture-in-picture. Any + <!-- The maximum aspect ratio (width/height) that is supported for picture-in-picture. Any ratio larger than this is considered to wide and short to be usable. Currently 2.39:1. --> <item name="config_pictureInPictureMaxAspectRatio" format="float" type="dimen">2.39</item> @@ -3273,6 +3273,11 @@ --> <integer name="config_dockedStackDividerSnapMode">0</integer> + <!-- The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. If + config_forceDefaultOrientation is set to true, the rotation on a close-to-square display + will be fixed. --> + <item name="config_closeToSquareDisplayMaxAspectRatio" format="float" type="dimen">1.333</item> + <!-- List of comma separated package names for which we the system will not show crash, ANR, etc. dialogs. --> <string translatable="false" name="config_appsNotReportingCrashes"></string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a1bafbf8de69..01abffeed384 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -403,6 +403,7 @@ <java-symbol type="integer" name="config_defaultPictureInPictureGravity" /> <java-symbol type="dimen" name="config_pictureInPictureMinAspectRatio" /> <java-symbol type="dimen" name="config_pictureInPictureMaxAspectRatio" /> + <java-symbol type="dimen" name="config_closeToSquareDisplayMaxAspectRatio" /> <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_threshold" /> <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_factor" /> <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_threshold" /> diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 0251efb872bc..f33c518941e5 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2677,8 +2677,9 @@ final class ActivityRecord extends ConfigurationContainer { * Get the configuration orientation by the requested screen orientation * ({@link ActivityInfo.ScreenOrientation}) of this activity. * - * @return orientation in ({@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}, - * {@link #ORIENTATION_UNDEFINED}). + * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE}, + * {@link Configuration#ORIENTATION_PORTRAIT}, + * {@link Configuration#ORIENTATION_UNDEFINED}). */ int getRequestedConfigurationOrientation() { final int screenOrientation = getOrientation(); @@ -2936,14 +2937,36 @@ final class ActivityRecord extends ConfigurationContainer { // should be given the aspect ratio. activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f); } - } else if (containingRatio < minAspectRatio && minAspectRatio != 0) { - if (containingAppWidth < containingAppHeight) { - // Width is the shorter side, so we use the height to figure-out what the max. width - // should be given the aspect ratio. + } else if (containingRatio < minAspectRatio) { + boolean adjustWidth; + switch (getRequestedConfigurationOrientation()) { + case ORIENTATION_LANDSCAPE: + // Width should be the longer side for this landscape app, so we use the width + // to figure-out what the max. height should be given the aspect ratio. + adjustWidth = false; + break; + case ORIENTATION_PORTRAIT: + // Height should be the longer side for this portrait app, so we use the height + // to figure-out what the max. width should be given the aspect ratio. + adjustWidth = true; + break; + default: + // This app doesn't have a preferred orientation, so we keep the length of the + // longer side, and use it to figure-out the length of the shorter side. + if (containingAppWidth < containingAppHeight) { + // Width is the shorter side, so we use the height to figure-out what the + // max. width should be given the aspect ratio. + adjustWidth = true; + } else { + // Height is the shorter side, so we use the width to figure-out what the + // max. height should be given the aspect ratio. + adjustWidth = false; + } + break; + } + if (adjustWidth) { activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f); } else { - // Height is the shorter side, so we use the width to figure-out what the max. - // height should be given the aspect ratio. activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f); } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 5cfc20b6339f..4795555e8ed2 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1500,8 +1500,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity; final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity; - mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp); mDisplayPolicy.configure(width, height, shortSizeDp); + mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp); mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo, calculateDisplayCutoutForRotation(mDisplayInfo.rotation)); diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 2ee30ac5c8ff..91d573defc16 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -2617,9 +2617,8 @@ public class DisplayPolicy { DisplayCutout displayCutout) { int width = fullWidth; if (hasNavigationBar()) { - // For a basic navigation bar, when we are in landscape mode we place - // the navigation bar to the side. - if (navigationBarCanMove() && fullWidth > fullHeight) { + final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation); + if (navBarPosition == NAV_BAR_LEFT || navBarPosition == NAV_BAR_RIGHT) { width -= getNavigationBarWidth(rotation, uiMode); } } @@ -2646,9 +2645,8 @@ public class DisplayPolicy { DisplayCutout displayCutout) { int height = fullHeight; if (hasNavigationBar()) { - // For a basic navigation bar, when we are in portrait mode we place - // the navigation bar to the bottom. - if (!navigationBarCanMove() || fullWidth < fullHeight) { + final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation); + if (navBarPosition == NAV_BAR_BOTTOM) { height -= getNavigationBarHeight(rotation, uiMode); } } diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 5f341ee8002c..543f19655350 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -38,6 +38,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; import android.util.SparseArray; +import android.view.DisplayCutout; import android.view.Surface; import com.android.internal.annotations.VisibleForTesting; @@ -70,6 +71,8 @@ public class DisplayRotation { private final int mDeskDockRotation; private final int mUndockedHdmiRotation; + private final float mCloseToSquareMaxAspectRatio; + private OrientationListener mOrientationListener; private StatusBarManagerInternal mStatusBarManagerInternal; private SettingsObserver mSettingsObserver; @@ -132,6 +135,9 @@ public class DisplayRotation { mUndockedHdmiRotation = readRotation( com.android.internal.R.integer.config_undockedHdmiRotation); + mCloseToSquareMaxAspectRatio = mContext.getResources().getFloat( + com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio); + if (isDefaultDisplay) { final Handler uiHandler = UiThread.getHandler(); mOrientationListener = new OrientationListener(mContext, uiHandler); @@ -212,10 +218,12 @@ public class DisplayRotation { // so if the orientation is forced, we need to respect that no matter what. final boolean isTv = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_LEANBACK); + final boolean isCloseToSquare = + isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height); final boolean forceDefaultOrientationInRes = res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation); final boolean forceDefaultOrienation = - ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) + ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv || isCloseToSquare) && forceDefaultOrientationInRes // For debug purposes the next line turns this feature off with: // $ adb shell setprop config.override_forced_orient true @@ -227,6 +235,18 @@ public class DisplayRotation { setFixedToUserRotation(forceDefaultOrienation); } + private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) { + final DisplayCutout displayCutout = + mDisplayContent.calculateDisplayCutoutForRotation(rotation).getDisplayCutout(); + final int uiMode = mService.mPolicy.getUiMode(); + final int w = mDisplayPolicy.getNonDecorDisplayWidth( + width, height, rotation, uiMode, displayCutout); + final int h = mDisplayPolicy.getNonDecorDisplayHeight( + width, height, rotation, uiMode, displayCutout); + final float aspectRatio = Math.max(w, h) / (float) Math.min(w, h); + return aspectRatio <= mCloseToSquareMaxAspectRatio; + } + void setRotation(int rotation) { if (mOrientationListener != null) { mOrientationListener.setCurrentRotation(rotation); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c747c6d95fcd..168c9adb61be 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -446,7 +446,8 @@ public class WindowManagerService extends IWindowManager.Stub final boolean mLimitedAlphaCompositing; final int mMaxUiWidth; - final WindowManagerPolicy mPolicy; + @VisibleForTesting + WindowManagerPolicy mPolicy; final IActivityManager mActivityManager; // TODO: Probably not needed once activities are fully in WM. @@ -4263,9 +4264,12 @@ public class WindowManagerService extends IWindowManager.Stub if (mMaxUiWidth > 0) { mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth)); } - applyForcedPropertiesForDefaultDisplay(); + final boolean changed = applyForcedPropertiesForDefaultDisplay(); mAnimator.ready(); mDisplayReady = true; + if (changed) { + reconfigureDisplayLocked(getDefaultDisplayContentLocked()); + } mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TOUCHSCREEN); } @@ -4865,7 +4869,8 @@ public class WindowManagerService extends IWindowManager.Stub } /** The global settings only apply to default display. */ - private void applyForcedPropertiesForDefaultDisplay() { + private boolean applyForcedPropertiesForDefaultDisplay() { + boolean changed = false; final DisplayContent displayContent = getDefaultDisplayContentLocked(); // Display size. String sizeStr = Settings.Global.getString(mContext.getContentResolver(), @@ -4885,6 +4890,7 @@ public class WindowManagerService extends IWindowManager.Stub Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height); displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity); + changed = true; } } catch (NumberFormatException ex) { } @@ -4893,17 +4899,20 @@ public class WindowManagerService extends IWindowManager.Stub // Display density. final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId); - if (density != 0) { + if (density != 0 && density != displayContent.mBaseDisplayDensity) { displayContent.mBaseDisplayDensity = density; + changed = true; } // Display scaling mode. int mode = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.DISPLAY_SCALING_FORCE, 0); - if (mode != 0) { + if (displayContent.mDisplayScalingDisabled != (mode != 0)) { Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED"); displayContent.mDisplayScalingDisabled = true; + changed = true; } + return changed; } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java index 198e7ce63f52..b15e99aaa8c2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java @@ -60,6 +60,7 @@ import com.android.server.LocalServices; import com.android.server.UiThread; import com.android.server.policy.WindowManagerPolicy; import com.android.server.statusbar.StatusBarManagerInternal; +import com.android.server.wm.utils.WmDisplayCutout; import org.junit.After; import org.junit.Before; @@ -113,6 +114,7 @@ public class DisplayRotationTests { public static void setUpOnce() { sMockWm = mock(WindowManagerService.class); sMockWm.mPowerManagerInternal = mock(PowerManagerInternal.class); + sMockWm.mPolicy = mock(WindowManagerPolicy.class); } @Before @@ -807,6 +809,8 @@ public class DisplayRotationTests { mMockDisplayContent = mock(WindowTestUtils.TestDisplayContent.class); mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay; + when(mMockDisplayContent.calculateDisplayCutoutForRotation(anyInt())) + .thenReturn(WmDisplayCutout.NO_CUTOUT); mMockDisplayPolicy = mock(DisplayPolicy.class); |