diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2d103033f9bde..96578ef9d5dba 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -680,6 +680,20 @@
rotation. -->
false
+
+ false
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5927897a24a00..4aca6c8b7cefe 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4032,6 +4032,10 @@
+
+
+
+
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d25fe6e60895b..625c1d767b6a5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2886,6 +2886,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
/* includeRotationSettings */ false);
mDisplaySwitchTransitionLauncher.requestDisplaySwitchTransitionIfNeeded(mDisplayId,
mInitialDisplayWidth, mInitialDisplayHeight, newWidth, newHeight);
+ mDisplayRotation.physicalDisplayChanged();
}
// If there is an override set for base values - use it, otherwise use new values.
@@ -3263,6 +3264,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mWindowingLayer.release();
mInputMonitor.onDisplayRemoved();
mWmService.mDisplayNotificationController.dispatchDisplayRemoved(this);
+ mDisplayRotation.onDisplayRemoved();
mWmService.mAccessibilityController.onDisplayRemoved(mDisplayId);
mRootWindowContainer.mTaskSupervisor
.getKeyguardController().onDisplayRemoved(mDisplayId);
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 27e33b08d9361..30791d3a3cd5a 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -52,8 +52,13 @@ import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.hardware.power.Boost;
import android.os.Handler;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
@@ -1052,6 +1057,10 @@ public class DisplayRotation {
return false;
}
+ if (mFoldController != null && mFoldController.shouldDisableRotationSensor()) {
+ return false;
+ }
+
if (mSupportAutoRotation) {
if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
|| mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
@@ -1149,6 +1158,9 @@ public class DisplayRotation {
int sensorRotation = mOrientationListener != null
? mOrientationListener.getProposedRotation() // may be -1
: -1;
+ if (mFoldController != null && mFoldController.shouldIgnoreSensorRotation()) {
+ sensorRotation = -1;
+ }
if (mDeviceStateController.shouldReverseRotationDirectionAroundZAxis()) {
// Flipping 270 and 90 has the same effect as changing the direction which rotation is
// applied.
@@ -1396,6 +1408,11 @@ public class DisplayRotation {
return false;
}
+ // Do not show rotation choice when fold controller blocks rotation sensor
+ if (mFoldController != null && mFoldController.shouldIgnoreSensorRotation()) {
+ return false;
+ }
+
// Don't show rotation choice if we are in tabletop or book modes.
if (isTabletopAutoRotateOverrideEnabled()) return false;
@@ -1489,6 +1506,12 @@ public class DisplayRotation {
}
}
+ void onDisplayRemoved() {
+ if (mFoldController != null) {
+ mFoldController.onDisplayRemoved();
+ }
+ }
+
/** Return whether the rotation settings has changed. */
private boolean updateSettings() {
final ContentResolver resolver = mContext.getContentResolver();
@@ -1578,6 +1601,22 @@ public class DisplayRotation {
pw.println(prefix + " mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
pw.println(prefix + " mFixedToUserRotation=" + isFixedToUserRotation());
+ if (mFoldController != null) {
+ pw.println(prefix + "FoldController");
+ pw.println(prefix + " mPauseAutorotationDuringUnfolding="
+ + mFoldController.mPauseAutorotationDuringUnfolding);
+ pw.println(prefix + " mShouldDisableRotationSensor="
+ + mFoldController.mShouldDisableRotationSensor);
+ pw.println(prefix + " mShouldIgnoreSensorRotation="
+ + mFoldController.mShouldIgnoreSensorRotation);
+ pw.println(prefix + " mLastDisplaySwitchTime="
+ + mFoldController.mLastDisplaySwitchTime);
+ pw.println(prefix + " mLastHingeAngleEventTime="
+ + mFoldController.mLastHingeAngleEventTime);
+ pw.println(prefix + " mDeviceState="
+ + mFoldController.mDeviceState);
+ }
+
if (!mRotationHistory.mRecords.isEmpty()) {
pw.println();
pw.println(prefix + " RotationHistory");
@@ -1619,13 +1658,37 @@ public class DisplayRotation {
}
}
- private class FoldController {
+ /**
+ * Called by the DisplayContent when the physical display changes
+ */
+ void physicalDisplayChanged() {
+ if (mFoldController != null) {
+ mFoldController.onPhysicalDisplayChanged();
+ }
+ }
+
+ @VisibleForTesting
+ long uptimeMillis() {
+ return SystemClock.uptimeMillis();
+ }
+
+ class FoldController {
+ private final boolean mPauseAutorotationDuringUnfolding;
@Surface.Rotation
private int mHalfFoldSavedRotation = -1; // No saved rotation
private DeviceStateController.DeviceState mDeviceState =
DeviceStateController.DeviceState.UNKNOWN;
+ private long mLastHingeAngleEventTime = 0;
+ private long mLastDisplaySwitchTime = 0;
+ private boolean mShouldIgnoreSensorRotation;
+ private boolean mShouldDisableRotationSensor;
private boolean mInHalfFoldTransition = false;
+ private int mDisplaySwitchRotationBlockTimeMs;
+ private int mHingeAngleRotationBlockTimeMs;
+ private int mMaxHingeAngle;
private final boolean mIsDisplayAlwaysSeparatingHinge;
+ private SensorManager mSensorManager;
+ private SensorEventListener mHingeAngleSensorEventListener;
private final Set mTabletopRotations;
private final Runnable mActivityBoundsUpdateCallback;
@@ -1682,6 +1745,48 @@ public class DisplayRotation {
}
}
};
+
+ mPauseAutorotationDuringUnfolding = mContext.getResources().getBoolean(
+ R.bool.config_windowManagerPauseRotationWhenUnfolding);
+
+ if (mPauseAutorotationDuringUnfolding) {
+ mDisplaySwitchRotationBlockTimeMs = mContext.getResources().getInteger(
+ R.integer.config_pauseRotationWhenUnfolding_displaySwitchTimeout);
+ mHingeAngleRotationBlockTimeMs = mContext.getResources().getInteger(
+ R.integer.config_pauseRotationWhenUnfolding_hingeEventTimeout);
+ mMaxHingeAngle = mContext.getResources().getInteger(
+ R.integer.config_pauseRotationWhenUnfolding_maxHingeAngle);
+ registerSensorManager();
+ }
+ }
+
+ private void registerSensorManager() {
+ mSensorManager = mContext.getSystemService(SensorManager.class);
+ if (mSensorManager != null) {
+ final Sensor hingeAngleSensor = mSensorManager
+ .getDefaultSensor(Sensor.TYPE_HINGE_ANGLE);
+
+ if (hingeAngleSensor != null) {
+ mHingeAngleSensorEventListener = new SensorEventListener() {
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ onHingeAngleChanged(event.values[0]);
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+ };
+ mSensorManager.registerListener(mHingeAngleSensorEventListener,
+ hingeAngleSensor, SensorManager.SENSOR_DELAY_FASTEST, getHandler());
+ }
+ }
+ }
+
+ void onDisplayRemoved() {
+ if (mSensorManager != null && mHingeAngleSensorEventListener != null) {
+ mSensorManager.unregisterListener(mHingeAngleSensorEventListener);
+ }
}
boolean isDeviceInPosture(DeviceStateController.DeviceState state, boolean isTabletop) {
@@ -1711,6 +1816,7 @@ public class DisplayRotation {
boolean shouldRevertOverriddenRotation() {
// When transitioning to open.
return mDeviceState == DeviceStateController.DeviceState.OPEN
+ && !mShouldIgnoreSensorRotation // Ignore if the hinge angle still moving
&& mInHalfFoldTransition
&& mHalfFoldSavedRotation != -1 // Ignore if we've already reverted.
&& mUserRotationMode
@@ -1757,6 +1863,80 @@ public class DisplayRotation {
UiThread.getHandler().postDelayed(mActivityBoundsUpdateCallback,
FOLDING_RECOMPUTE_CONFIG_DELAY_MS);
}
+
+ boolean shouldIgnoreSensorRotation() {
+ return mShouldIgnoreSensorRotation;
+ }
+
+ boolean shouldDisableRotationSensor() {
+ return mShouldDisableRotationSensor;
+ }
+
+ private void updateSensorRotationBlockIfNeeded() {
+ final long currentTime = uptimeMillis();
+ final boolean newShouldIgnoreRotation =
+ currentTime - mLastDisplaySwitchTime < mDisplaySwitchRotationBlockTimeMs
+ || currentTime - mLastHingeAngleEventTime < mHingeAngleRotationBlockTimeMs;
+
+ if (newShouldIgnoreRotation != mShouldIgnoreSensorRotation) {
+ mShouldIgnoreSensorRotation = newShouldIgnoreRotation;
+
+ // Resuming the autorotation
+ if (!mShouldIgnoreSensorRotation) {
+ if (mShouldDisableRotationSensor) {
+ // Sensor was disabled, let's re-enable it
+ mShouldDisableRotationSensor = false;
+ updateOrientationListenerLw();
+ } else {
+ // Sensor was not disabled, let's update the rotation in case if we received
+ // some rotation sensor updates when autorotate was disabled
+ updateRotationAndSendNewConfigIfChanged();
+ }
+ }
+ }
+ }
+
+ void onPhysicalDisplayChanged() {
+ if (!mPauseAutorotationDuringUnfolding) return;
+
+ mLastDisplaySwitchTime = uptimeMillis();
+
+ final boolean isUnfolding =
+ mDeviceState == DeviceStateController.DeviceState.OPEN
+ || mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED;
+
+ if (isUnfolding) {
+ // Temporary disable rotation sensor updates when unfolding
+ mShouldDisableRotationSensor = true;
+ updateOrientationListenerLw();
+ }
+
+ updateSensorRotationBlockIfNeeded();
+ getHandler().postDelayed(() -> {
+ synchronized (mLock) {
+ updateSensorRotationBlockIfNeeded();
+ };
+ }, mDisplaySwitchRotationBlockTimeMs);
+ }
+
+ void onHingeAngleChanged(float hingeAngle) {
+ if (hingeAngle < mMaxHingeAngle) {
+ mLastHingeAngleEventTime = uptimeMillis();
+
+ updateSensorRotationBlockIfNeeded();
+
+ getHandler().postDelayed(() -> {
+ synchronized (mLock) {
+ updateSensorRotationBlockIfNeeded();
+ };
+ }, mHingeAngleRotationBlockTimeMs);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ Handler getHandler() {
+ return mService.mH;
}
private class OrientationListener extends WindowOrientationListener implements Runnable {
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 192274317173a..890e55b36194d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -61,6 +61,7 @@ import android.hardware.SensorManager;
import android.hardware.devicestate.DeviceStateManager;
import android.os.PowerManagerInternal;
import android.os.SystemClock;
+import android.os.Handler;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.view.DisplayAddress;
@@ -74,6 +75,9 @@ 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.testutils.OffsettableClock;
+import com.android.server.testutils.TestHandler;
+import com.android.server.wm.DisplayContent.FixedRotationTransitionListener;
import org.junit.After;
import org.junit.AfterClass;
@@ -101,6 +105,9 @@ public class DisplayRotationTests {
private static final long UI_HANDLER_WAIT_TIMEOUT_MS = 50;
private StatusBarManagerInternal mPreviousStatusBarManagerInternal;
+ private static final OffsettableClock sClock = new OffsettableClock.Stopped();
+ private static TestHandler sHandler;
+ private static long sCurrentUptimeMillis = 10_000;
private static WindowManagerService sMockWm;
private DisplayContent mMockDisplayContent;
@@ -110,6 +117,7 @@ public class DisplayRotationTests {
private Resources mMockRes;
private SensorManager mMockSensorManager;
private Sensor mFakeOrientationSensor;
+ private Sensor mFakeHingeAngleSensor;
private DisplayWindowSettings mMockDisplayWindowSettings;
private ContentResolver mMockResolver;
private FakeSettingsProvider mFakeSettingsProvider;
@@ -122,6 +130,9 @@ public class DisplayRotationTests {
private ContentObserver mUserRotationObserver;
private SensorEventListener mOrientationSensorListener;
+ ArgumentCaptor mHingeAngleSensorListenerCaptor = ArgumentCaptor.forClass(
+ SensorEventListener.class);
+
private DisplayRotationBuilder mBuilder;
private DeviceStateController mDeviceStateController;
@@ -132,6 +143,7 @@ public class DisplayRotationTests {
sMockWm = mock(WindowManagerService.class);
sMockWm.mPowerManagerInternal = mock(PowerManagerInternal.class);
sMockWm.mPolicy = mock(WindowManagerPolicy.class);
+ sHandler = new TestHandler(null, sClock);
}
@AfterClass
@@ -464,12 +476,16 @@ public class DisplayRotationTests {
}
private SensorEvent createSensorEvent(int rotation) throws Exception {
+ return createSensorEvent(mFakeOrientationSensor, rotation);
+ }
+
+ private SensorEvent createSensorEvent(Sensor sensor, int value) throws Exception {
final Constructor constructor =
SensorEvent.class.getDeclaredConstructor(int.class);
constructor.setAccessible(true);
final SensorEvent event = constructor.newInstance(1);
- event.sensor = mFakeOrientationSensor;
- event.values[0] = rotation;
+ event.sensor = sensor;
+ event.values[0] = value;
event.timestamp = SystemClock.elapsedRealtimeNanos();
return event;
}
@@ -901,6 +917,120 @@ public class DisplayRotationTests {
Surface.ROTATION_0, Surface.ROTATION_90, false /* forceUpdate */));
}
+ @Test
+ public void testSensorRotationAfterDisplayChangeBeforeTimeout_ignoresSensor() throws Exception {
+ mBuilder.setSupportHalfFoldAutoRotateOverride(true)
+ .setPauseRotationWhenUnfolding(true)
+ .setDisplaySwitchRotationBlockTimeMs(1000)
+ .build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+ thawRotation();
+ enableOrientationSensor();
+
+ mTarget.physicalDisplayChanged();
+
+ moveTimeForward(900);
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ @Test
+ public void testSensorRotationAfterDisplayChangeAfterTimeout_usesSensor() throws Exception {
+ mBuilder.setSupportHalfFoldAutoRotateOverride(true)
+ .setPauseRotationWhenUnfolding(true)
+ .setDisplaySwitchRotationBlockTimeMs(1000)
+ .build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+ thawRotation();
+ enableOrientationSensor();
+
+ mTarget.physicalDisplayChanged();
+
+ moveTimeForward(1100);
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ @Test
+ public void testSensorRotationAfterHingeEventBeforeTimeout_ignoresSensor() throws Exception {
+ mBuilder.setSupportHalfFoldAutoRotateOverride(true)
+ .setPauseRotationWhenUnfolding(true)
+ .setMaxHingeAngle(165)
+ .setHingeAngleRotationBlockTimeMs(400)
+ .build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+ thawRotation();
+ enableOrientationSensor();
+
+ sendHingeAngleEvent(130);
+
+ moveTimeForward( 300);
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ @Test
+ public void testSensorRotationAfterHingeEventBeforeTimeoutFlagDisabled_usesSensorData()
+ throws Exception {
+ mBuilder.setSupportHalfFoldAutoRotateOverride(true)
+ .setPauseRotationWhenUnfolding(false)
+ .setMaxHingeAngle(165)
+ .setHingeAngleRotationBlockTimeMs(400)
+ .build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+ thawRotation();
+ enableOrientationSensor();
+
+ sendHingeAngleEvent(130);
+
+ moveTimeForward( 300);
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ @Test
+ public void testSensorRotationAfterHingeEventAfterTimeout_usesSensorData() throws Exception {
+ mBuilder.setSupportHalfFoldAutoRotateOverride(true)
+ .setPauseRotationWhenUnfolding(true)
+ .setMaxHingeAngle(165)
+ .setHingeAngleRotationBlockTimeMs(400)
+ .build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+ thawRotation();
+ enableOrientationSensor();
+
+ sendHingeAngleEvent(180);
+
+ moveTimeForward(1010);
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+
+ @Test
+ public void testSensorRotationAfterLargeHingeEventBeforeTimeout_usesSensor() throws Exception {
+ mBuilder.setSupportHalfFoldAutoRotateOverride(true)
+ .setPauseRotationWhenUnfolding(true)
+ .setMaxHingeAngle(165)
+ .setHingeAngleRotationBlockTimeMs(400)
+ .build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+ thawRotation();
+ enableOrientationSensor();
+
+ sendHingeAngleEvent(180);
+
+ moveTimeForward(300);
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
// ========================
// Non-rotation API Tests
// ========================
@@ -921,6 +1051,12 @@ public class DisplayRotationTests {
+ " fixed to user rotation.", mTarget.isFixedToUserRotation());
}
+ private void moveTimeForward(long timeMillis) {
+ sCurrentUptimeMillis += timeMillis;
+ sClock.fastForward(timeMillis);
+ sHandler.timeAdvance();
+ }
+
/**
* Call {@link DisplayRotation#configure(int, int)} to configure {@link #mTarget}
* according to given parameters.
@@ -953,6 +1089,17 @@ public class DisplayRotationTests {
mTarget.configure(width, height);
}
+ private void sendHingeAngleEvent(int hingeAngle) {
+ mHingeAngleSensorListenerCaptor.getAllValues().forEach(sensorEventListener -> {
+ try {
+ sensorEventListener.onSensorChanged(createSensorEvent(mFakeHingeAngleSensor,
+ hingeAngle));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
private void freezeRotation(int rotation) {
mTarget.freezeRotation(rotation);
@@ -974,7 +1121,11 @@ public class DisplayRotationTests {
private class DisplayRotationBuilder {
private boolean mIsDefaultDisplay = true;
private boolean mSupportAutoRotation = true;
+ private boolean mPauseRotationWhenUnfolding = false;
private boolean mSupportHalfFoldAutoRotateOverride = false;
+ private int mDisplaySwitchRotationBlockTimeMs;
+ private int mHingeAngleRotationBlockTimeMs;
+ private int mMaxHingeAngle;
private int mLidOpenRotation = WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
private int mCarDockRotation;
@@ -986,6 +1137,29 @@ public class DisplayRotationTests {
return this;
}
+ public DisplayRotationBuilder setPauseRotationWhenUnfolding(
+ boolean pauseRotationWhenUnfolding) {
+ mPauseRotationWhenUnfolding = pauseRotationWhenUnfolding;
+ return this;
+ }
+
+ public DisplayRotationBuilder setDisplaySwitchRotationBlockTimeMs(
+ int displaySwitchRotationBlockTimeMs) {
+ mDisplaySwitchRotationBlockTimeMs = displaySwitchRotationBlockTimeMs;
+ return this;
+ }
+
+ public DisplayRotationBuilder setHingeAngleRotationBlockTimeMs(
+ int hingeAngleRotationBlockTimeMs) {
+ mHingeAngleRotationBlockTimeMs = hingeAngleRotationBlockTimeMs;
+ return this;
+ }
+
+ public DisplayRotationBuilder setMaxHingeAngle(int maxHingeAngle) {
+ mMaxHingeAngle = maxHingeAngle;
+ return this;
+ }
+
private DisplayRotationBuilder setSupportAutoRotation(boolean supportAutoRotation) {
mSupportAutoRotation = supportAutoRotation;
return this;
@@ -1111,10 +1285,27 @@ public class DisplayRotationTests {
when(mMockDisplayContent.getWindowConfiguration())
.thenReturn(new WindowConfiguration());
+ Field field = DisplayContent.class
+ .getDeclaredField("mFixedRotationTransitionListener");
+ field.setAccessible(true);
+ field.set(mMockDisplayContent, mock(FixedRotationTransitionListener.class));
+
mMockDisplayPolicy = mock(DisplayPolicy.class);
mMockRes = mock(Resources.class);
when(mMockContext.getResources()).thenReturn((mMockRes));
+ when(mMockRes.getBoolean(com.android.internal.R.bool
+ .config_windowManagerPauseRotationWhenUnfolding))
+ .thenReturn(mPauseRotationWhenUnfolding);
+ when(mMockRes.getInteger(com.android.internal.R.integer
+ .config_pauseRotationWhenUnfolding_displaySwitchTimeout))
+ .thenReturn(mDisplaySwitchRotationBlockTimeMs);
+ when(mMockRes.getInteger(com.android.internal.R.integer
+ .config_pauseRotationWhenUnfolding_hingeEventTimeout))
+ .thenReturn(mHingeAngleRotationBlockTimeMs);
+ when(mMockRes.getInteger(com.android.internal.R.integer
+ .config_pauseRotationWhenUnfolding_maxHingeAngle))
+ .thenReturn(mMaxHingeAngle);
when(mMockRes.getBoolean(com.android.internal.R.bool.config_supportAutoRotation))
.thenReturn(mSupportAutoRotation);
when(mMockRes.getInteger(com.android.internal.R.integer.config_lidOpenRotation))
@@ -1127,11 +1318,16 @@ public class DisplayRotationTests {
.thenReturn(convertRotationToDegrees(mUndockedHdmiRotation));
mMockSensorManager = mock(SensorManager.class);
+ when(mMockContext.getSystemService(SensorManager.class))
+ .thenReturn(mMockSensorManager);
when(mMockContext.getSystemService(Context.SENSOR_SERVICE))
.thenReturn(mMockSensorManager);
mFakeOrientationSensor = createSensor(Sensor.TYPE_DEVICE_ORIENTATION);
when(mMockSensorManager.getSensorList(Sensor.TYPE_DEVICE_ORIENTATION)).thenReturn(
Collections.singletonList(mFakeOrientationSensor));
+ mFakeHingeAngleSensor = mock(Sensor.class);
+ when(mMockSensorManager.getDefaultSensor(Sensor.TYPE_HINGE_ANGLE)).thenReturn(
+ mFakeHingeAngleSensor);
when(mMockContext.getResources().getBoolean(
com.android.internal.R.bool.config_windowManagerHalfFoldAutoRotateOverride))
@@ -1160,10 +1356,24 @@ public class DisplayRotationTests {
WindowManagerService service, DisplayContent displayContent) {
return null;
}
+
+ @Override
+ Handler getHandler() {
+ return sHandler;
+ }
+
+ @Override
+ long uptimeMillis() {
+ return sCurrentUptimeMillis;
+ }
};
reset(sMockWm);
+ verify(mMockSensorManager, atLeast(0)).registerListener(
+ mHingeAngleSensorListenerCaptor.capture(), eq(mFakeHingeAngleSensor), anyInt(),
+ any());
+
captureObservers();
}
}