diff options
5 files changed, 80 insertions, 62 deletions
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index ccf8509c2f8f..2163a5532018 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3322,9 +3322,8 @@ --> <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. --> + <!-- The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. The + orientation requests from apps would be ignored if the display is close-to-square. --> <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, diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 3f783f67b73c..6c198352a938 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; @@ -371,6 +372,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo private int mLastKeyguardForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; /** + * The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. The + * orientation requests from apps would be ignored if the display is close-to-square. + */ + @VisibleForTesting + final float mCloseToSquareMaxAspectRatio; + + /** + * If this is true, we would not rotate the display for apps. The rotation would be either the + * sensor rotation or the user rotation, controlled by + * {@link WindowManagerPolicy.UserRotationMode}. + */ + private boolean mIgnoreRotationForApps; + + /** * Keep track of wallpaper visibility to notify changes. */ private boolean mLastWallpaperVisible = false; @@ -898,6 +913,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mDisplayPolicy = new DisplayPolicy(service, this); mDisplayRotation = new DisplayRotation(service, this); + mCloseToSquareMaxAspectRatio = service.mContext.getResources().getFloat( + com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio); if (isDefaultDisplay) { // The policy may be invoked right after here, so it requires the necessary default // fields of this display content. @@ -1523,6 +1540,21 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo, calculateDisplayCutoutForRotation(mDisplayInfo.rotation)); + + // Not much of use to rotate the display for apps since it's close to square. + mIgnoreRotationForApps = isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height); + } + + private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) { + final DisplayCutout displayCutout = + calculateDisplayCutoutForRotation(rotation).getDisplayCutout(); + final int uiMode = mWmService.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; } /** @@ -2103,6 +2135,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo int getOrientation() { final WindowManagerPolicy policy = mWmService.mPolicy; + if (mIgnoreRotationForApps) { + return SCREEN_ORIENTATION_USER; + } + if (mWmService.mDisplayFrozen) { if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) { if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 34a480291863..282ed42468dd 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -39,7 +39,6 @@ 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; @@ -74,8 +73,6 @@ public class DisplayRotation { private final int mDeskDockRotation; private final int mUndockedHdmiRotation; - private final float mCloseToSquareMaxAspectRatio; - private OrientationListener mOrientationListener; private StatusBarManagerInternal mStatusBarManagerInternal; private SettingsObserver mSettingsObserver; @@ -163,9 +160,6 @@ 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); @@ -242,31 +236,16 @@ public class DisplayRotation { // It's also not likely to rotate a TV screen. final boolean isTv = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_LEANBACK); - // Not much of use to rotate the display since it's close to square. - final boolean isCloseToSquare = - isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height); final boolean forceDesktopMode = mService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay; mDefaultFixedToUserRotation = - (isCar || isTv || mService.mIsPc || forceDesktopMode || isCloseToSquare) + (isCar || isTv || mService.mIsPc || forceDesktopMode) // For debug purposes the next line turns this feature off with: // $ adb shell setprop config.override_forced_orient true // $ adb shell wm size reset && !"true".equals(SystemProperties.get("config.override_forced_orient")); } - 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/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index e60e54c9e44f..bbba0a00e861 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER; import static android.os.Build.VERSION_CODES.P; import static android.os.Build.VERSION_CODES.Q; import static android.view.Display.DEFAULT_DISPLAY; @@ -29,6 +30,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; @@ -528,6 +530,43 @@ public class DisplayContentTests extends WindowTestsBase { } @Test + public void testOrientationForAspectRatio() { + final DisplayContent dc = createNewDisplay(); + + // When display content is created its configuration is not yet initialized, which could + // cause unnecessary configuration propagation, so initialize it here. + final Configuration config = new Configuration(); + dc.computeScreenConfiguration(config); + dc.onRequestedOverrideConfigurationChanged(config); + + // Create a window that requests a fixed orientation. It will define device orientation + // by default. + final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc, + "window"); + window.mHasSurface = true; + window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE; + + // -------------------------------- + // Test non-close-to-square display + // -------------------------------- + dc.mBaseDisplayWidth = 1000; + dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f); + dc.configureDisplayPolicy(); + + assertEquals("Screen orientation must be defined by the window by default.", + window.mAttrs.screenOrientation, dc.getOrientation()); + + // ---------------------------- + // Test close-to-square display + // ---------------------------- + dc.mBaseDisplayHeight = dc.mBaseDisplayWidth; + dc.configureDisplayPolicy(); + + assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.", + SCREEN_ORIENTATION_USER, dc.getOrientation()); + } + + @Test public void testDisableDisplayInfoOverrideFromWindowManager() { final DisplayContent dc = createNewDisplay(); 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 1c10ffb01f8e..49d38c062049 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java @@ -17,7 +17,6 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; -import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -394,19 +393,6 @@ public class DisplayRotationTests { verifyOrientationListenerRegistration(0); } - @Test - public void testNotEnablesSensor_ForceDefaultRotation_Squared() throws Exception { - mBuilder.build(); - configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false); - - when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); - when(mMockDisplayPolicy.isAwake()).thenReturn(true); - when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true); - when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true); - mTarget.updateOrientationListener(); - verifyOrientationListenerRegistration(0); - } - private void enableOrientationSensor() { when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); when(mMockDisplayPolicy.isAwake()).thenReturn(true); @@ -533,15 +519,6 @@ public class DisplayRotationTests { } @Test - public void testReturnsUserRotation_ForceDefaultRotation_Squared() throws Exception { - mBuilder.build(); - configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false); - - assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT, - Surface.ROTATION_180)); - } - - @Test public void testReturnsLidOpenRotation_LidOpen() throws Exception { mBuilder.setLidOpenRotation(Surface.ROTATION_90).build(); configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); @@ -643,14 +620,9 @@ public class DisplayRotationTests { width = 1080; height = 1920; break; - case SCREEN_ORIENTATION_LOCKED: - // We use locked for squared display. - width = 1080; - height = 1080; - break; default: - throw new IllegalArgumentException("displayOrientation needs to be landscape, " - + "portrait or locked, but we got " + throw new IllegalArgumentException("displayOrientation needs to be either landscape" + + " or portrait, but we got " + ActivityInfo.screenOrientationToString(displayOrientation)); } @@ -660,10 +632,6 @@ public class DisplayRotationTests { .thenReturn(isCar); when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) .thenReturn(isTv); - when(mMockDisplayPolicy.getNonDecorDisplayWidth(anyInt(), anyInt(), anyInt(), anyInt(), - any())).thenReturn(width); - when(mMockDisplayPolicy.getNonDecorDisplayHeight(anyInt(), anyInt(), anyInt(), anyInt(), - any())).thenReturn(height); final int shortSizeDp = (isCar || isTv) ? 540 : 720; final int longSizeDp = 960; @@ -831,9 +799,6 @@ public class DisplayRotationTests { .thenReturn(convertRotationToDegrees(mDeskDockRotation)); when(mMockRes.getInteger(com.android.internal.R.integer.config_undockedHdmiRotation)) .thenReturn(convertRotationToDegrees(mUndockedHdmiRotation)); - when(mMockRes.getFloat( - com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio)) - .thenReturn(1.33f); mMockSensorManager = mock(SensorManager.class); when(mMockContext.getSystemService(Context.SENSOR_SERVICE)) |