</string-array>
- <!-- Flag indicating that this device does not rotate and will always remain in its default
- orientation. Activities that desire to run in a non-compatible orientation will be run
- from an emulated display within the physical display. -->
- <bool name="config_forceDefaultOrientation">false</bool>
-
<!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM -->
<integer name="config_toastDefaultGravity">0x00000051</integer>
<java-symbol type="bool" name="config_requireRadioPowerOffOnSimRefreshReset" />
<java-symbol type="bool" name="config_speed_up_audio_on_mt_calls" />
<java-symbol type="bool" name="config_useFixedVolume" />
- <java-symbol type="bool" name="config_forceDefaultOrientation" />
<java-symbol type="bool" name="config_wifi_batched_scan_supported" />
<java-symbol type="bool" name="config_wifi_softap_acs_supported" />
<java-symbol type="string" name="config_wifi_softap_acs_supported_channel_list" />
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.IntDef;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.ContentResolver;
import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* Defines the mapping between orientation and rotation of a display.
private int mUserRotation = Surface.ROTATION_0;
/**
+ * Flag that indicates this is a display that may run better when fixed to user rotation.
+ */
+ private boolean mDefaultFixedToUserRotation;
+
+ /**
+ * No overridden behavior is provided in terms of fixing rotation to user rotation. Use other
+ * flags to derive the default behavior, such as {@link WindowManagerService#mIsPc} and
+ * {@link WindowManagerService#mForceDesktopModeOnExternalDisplays}.
+ */
+ static final int FIXED_TO_USER_ROTATION_DEFAULT = 0;
+ /**
+ * Don't fix display rotation to {@link #mUserRotation} only. Always allow other factors to play
+ * a role in deciding display rotation.
+ */
+ static final int FIXED_TO_USER_ROTATION_DISABLED = 1;
+ /**
+ * Only use {@link #mUserRotation} as the display rotation.
+ */
+ static final int FIXED_TO_USER_ROTATION_ENABLED = 2;
+ @IntDef({ FIXED_TO_USER_ROTATION_DEFAULT, FIXED_TO_USER_ROTATION_DISABLED,
+ FIXED_TO_USER_ROTATION_ENABLED })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface FixedToUserRotation {}
+
+ /**
* A flag to indicate if the display rotation should be fixed to user specified rotation
* regardless of all other states (including app requrested orientation). {@code true} the
* display rotation should be fixed to user specified rotation, {@code false} otherwise.
*/
- private boolean mFixedToUserRotation;
+ private int mFixedToUserRotation = FIXED_TO_USER_ROTATION_DEFAULT;
private int mDemoHdmiRotation;
private int mDemoRotation;
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 || isCloseToSquare)
- && forceDefaultOrientationInRes
- // 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"));
- // Configuration says we force to use the default orientation. We can fall back to fix
- // rotation to only user rotation. As long as OEM doesn't change user rotation then the
- // rotation of this display is effectively stuck at 0 deg.
- setFixedToUserRotation(forceDefaultOrienation);
+ final boolean forceDesktopMode =
+ mService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay;
+ mDefaultFixedToUserRotation =
+ (isCar || isTv || mService.mIsPc || forceDesktopMode || isCloseToSquare)
+ // 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) {
}
void restoreSettings(int userRotationMode, int userRotation,
- boolean fixedToUserRotation) {
+ @FixedToUserRotation int fixedToUserRotation) {
mFixedToUserRotation = fixedToUserRotation;
// We will retrieve user rotation and user rotation mode from settings for default display.
mUserRotation = userRotation;
}
- void setFixedToUserRotation(boolean fixedToUserRotation) {
+ void setFixedToUserRotation(@FixedToUserRotation int fixedToUserRotation) {
if (mFixedToUserRotation == fixedToUserRotation) {
return;
}
mFixedToUserRotation = fixedToUserRotation;
- mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent,
- fixedToUserRotation);
+ mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent, fixedToUserRotation);
mService.updateRotation(true /* alwaysSendConfiguration */,
false /* forceRelayout */);
}
}
boolean isFixedToUserRotation() {
- return mFixedToUserRotation;
+ switch (mFixedToUserRotation) {
+ case FIXED_TO_USER_ROTATION_DISABLED:
+ return false;
+ case FIXED_TO_USER_ROTATION_ENABLED:
+ return true;
+ default:
+ return mDefaultFixedToUserRotation;
+ }
}
/**
* false} is when {@link #isFixedToUserRotation()} is {@code true}.
*/
boolean respectAppRequestedOrientation() {
- return !mFixedToUserRotation;
+ return !isFixedToUserRotation();
}
public int getLandscapeRotation() {
* screen is switched off.
*/
private boolean needSensorRunning() {
- if (mFixedToUserRotation) {
+ if (isFixedToUserRotation()) {
// We are sure we only respect user rotation settings, so we are sure we will not
// support sensor rotation.
return false;
);
}
- if (mFixedToUserRotation) {
+ if (isFixedToUserRotation()) {
return mUserRotation;
}
// demo, hdmi, vr, etc mode.
// Determine if the rotation is currently forced.
- if (mFixedToUserRotation) {
+ if (isFixedToUserRotation()) {
return false; // Rotation is forced to user settings.
}
pw.print(" mDemoHdmiRotationLock=" + mDemoHdmiRotationLock);
pw.println(" mUndockedHdmiRotation=" + Surface.rotationToString(mUndockedHdmiRotation));
pw.println(prefix + " mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
- pw.println(prefix + " mFixedToUserRotation=" + mFixedToUserRotation);
+ pw.println(prefix + " mFixedToUserRotation=" + isFixedToUserRotation());
}
private class OrientationListener extends WindowOrientationListener {
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.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
private boolean mShouldShowWithInsecureKeyguard = false;
private boolean mShouldShowSystemDecors = false;
private boolean mShouldShowIme = false;
- private boolean mFixedToUserRotation;
+ private @DisplayRotation.FixedToUserRotation int mFixedToUserRotation =
+ FIXED_TO_USER_ROTATION_DEFAULT;
private Entry(String name) {
mName = name;
&& !mShouldShowWithInsecureKeyguard
&& !mShouldShowSystemDecors
&& !mShouldShowIme
- && !mFixedToUserRotation;
+ && mFixedToUserRotation == FIXED_TO_USER_ROTATION_DEFAULT;
}
}
writeSettingsIfNeeded(entry, displayInfo);
}
- void setFixedToUserRotation(DisplayContent displayContent, boolean fixedToUserRotation) {
+ void setFixedToUserRotation(DisplayContent displayContent,
+ @DisplayRotation.FixedToUserRotation int fixedToUserRotation) {
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
final Entry entry = getOrCreateEntry(displayInfo);
entry.mFixedToUserRotation = fixedToUserRotation;
"shouldShowWithInsecureKeyguard");
entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
- entry.mFixedToUserRotation = getBooleanAttribute(parser,
- "fixedToUserRotation");
+ entry.mFixedToUserRotation = getIntAttribute(parser, "fixedToUserRotation");
mEntries.put(name, entry);
}
XmlUtils.skipCurrentTag(parser);
if (entry.mShouldShowIme) {
out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
}
- if (entry.mFixedToUserRotation) {
+ if (entry.mFixedToUserRotation != FIXED_TO_USER_ROTATION_DEFAULT) {
out.attribute(null, "fixedToUserRotation",
- Boolean.toString(entry.mFixedToUserRotation));
+ Integer.toString(entry.mFixedToUserRotation));
}
out.endTag(null, "display");
}
}
}
- void setRotateForApp(int displayId, boolean enabled) {
+ void setRotateForApp(int displayId,
+ @DisplayRotation.FixedToUserRotation int fixedToUserRotation) {
synchronized (mGlobalLock) {
final DisplayContent display = mRoot.getDisplayContent(displayId);
if (display == null) {
Slog.w(TAG, "Trying to set rotate for app for a missing display.");
return;
}
- display.getDisplayRotation().setFixedToUserRotation(enabled);
+ display.getDisplayRotation().setFixedToUserRotation(fixedToUserRotation);
}
}
arg = getNextArgRequired();
}
- final boolean enabled;
+ final @DisplayRotation.FixedToUserRotation int fixedToUserRotation;
switch (arg) {
case "enabled":
- enabled = true;
+ fixedToUserRotation = DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
break;
case "disabled":
- enabled = false;
+ fixedToUserRotation = DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
+ break;
+ case "default":
+ fixedToUserRotation = DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
break;
default:
- getErrPrintWriter().println("Error: expecting enabled or disabled, but we get "
- + arg);
+ getErrPrintWriter().println("Error: expecting enabled, disabled or default, but we "
+ + "get " + arg);
return -1;
}
- mInternal.setRotateForApp(displayId, enabled);
+ mInternal.setRotateForApp(displayId, fixedToUserRotation);
return 0;
}
@Test
public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
final DisplayContent dc = createNewDisplay();
- dc.getDisplayRotation().setFixedToUserRotation(true);
+ dc.getDisplayRotation().setFixedToUserRotation(
+ DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
? SCREEN_ORIENTATION_PORTRAIT
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;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@Test
public void testPersistsUserRotation_LockRotation_NonDefaultDisplay() throws Exception {
- mBuilder.mIsDefaultDisplay = false;
-
- mBuilder.build();
+ mBuilder.setIsDefaultDisplay(false).build();
freezeRotation(Surface.ROTATION_180);
@Test
public void testPersistsUserRotation_UnlockRotation_NonDefaultDisplay() throws Exception {
- mBuilder.mIsDefaultDisplay = false;
-
- mBuilder.build();
+ mBuilder.setIsDefaultDisplay(false).build();
thawRotation();
public void testPersistsFixedToUserRotation() throws Exception {
mBuilder.build();
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
- verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, true);
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent,
+ FIXED_TO_USER_ROTATION_ENABLED);
reset(mMockDisplayWindowSettings);
- mTarget.setFixedToUserRotation(false);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_DISABLED);
- verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, false);
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent,
+ FIXED_TO_USER_ROTATION_DISABLED);
+
+ reset(mMockDisplayWindowSettings);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_DEFAULT);
+
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent,
+ FIXED_TO_USER_ROTATION_DEFAULT);
}
// ========================================
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
mTarget.updateOrientationListener();
verifyOrientationListenerRegistration(0);
}
@Test
- public void testNotEnablesSensor_ForceDefaultRotation() throws Exception {
+ public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
}
@Test
- public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception {
+ public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
}
@Test
- public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception {
+ public void testNotEnablesSensor_ForceDefaultRotation_Squared() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false);
when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
// Tests for Policy based Rotation
// =================================
@Test
- public void testReturnsUserRotation_ForceDefaultRotation() throws Exception {
+ public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
Surface.ROTATION_180));
}
@Test
- public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception {
+ public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
Surface.ROTATION_180));
}
@Test
- public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception {
+ public void testReturnsUserRotation_ForceDefaultRotation_Squared() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false);
assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
Surface.ROTATION_180));
mBuilder.build();
configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
freezeRotation(Surface.ROTATION_180);
@Test
public void testNotRespectAppRequestedOrientation_FixedToUserRotation() throws Exception {
mBuilder.build();
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
assertFalse("Display rotation shouldn't respect app requested orientation if"
+ " fixed to user rotation.", mTarget.respectAppRequestedOrientation());
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 either landscape"
- + " or portrait, but we got "
+ throw new IllegalArgumentException("displayOrientation needs to be landscape, "
+ + "portrait or locked, but we got "
+ ActivityInfo.screenOrientationToString(displayOrientation));
}
.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;
.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))
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
}
@Test
- public void testNotFixedToUserRotationByDefault() {
+ public void testFixedToUserRotationDefault() {
mTarget.setUserRotation(mPrimaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
Surface.ROTATION_0);
mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
- verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(false));
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(),
+ eq(FIXED_TO_USER_ROTATION_DEFAULT));
mockitoSession.finishMocking();
}
@Test
- public void testSetFixedToUserRotation() {
- mTarget.setFixedToUserRotation(mPrimaryDisplay, true);
+ public void testSetFixedToUserRotationDisabled() {
+ mTarget.setFixedToUserRotation(mPrimaryDisplay, FIXED_TO_USER_ROTATION_DISABLED);
final MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
.startMocking();
applySettingsToDisplayByNewInstance(mPrimaryDisplay);
- verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(true));
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(),
+ eq(FIXED_TO_USER_ROTATION_DISABLED));
+ mockitoSession.finishMocking();
+ }
+
+ @Test
+ public void testSetFixedToUserRotationEnabled() {
+ mTarget.setFixedToUserRotation(mPrimaryDisplay, FIXED_TO_USER_ROTATION_ENABLED);
+
+ final MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
+ .startMocking();
+ final DisplayRotation displayRotation = mock(DisplayRotation.class);
+ spyOn(mPrimaryDisplay);
+ doReturn(displayRotation).when(mPrimaryDisplay).getDisplayRotation();
+
+ applySettingsToDisplayByNewInstance(mPrimaryDisplay);
+
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(),
+ eq(FIXED_TO_USER_ROTATION_ENABLED));
mockitoSession.finishMocking();
}