Loading services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleClosedStatePredicate.java +44 −36 Original line number Diff line number Diff line Loading @@ -34,7 +34,10 @@ import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.HandlerExecutor; import android.os.PowerManager; import android.os.PowerManager.ScreenTimeoutPolicy; import android.os.PowerManager.ScreenTimeoutPolicyListener; import android.util.ArraySet; import android.util.Dumpable; import android.util.Slog; Loading Loading @@ -75,9 +78,6 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt private final FeatureFlags mFeatureFlags; private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo(); @PowerManager.ScreenTimeoutPolicy private volatile int mScreenTimeoutPolicy; /** * Creates {@link BookStyleClosedStatePredicate}. It is expected that the device has a pair * of accelerometer sensors (one for each movable part of the device), see parameter Loading Loading @@ -115,7 +115,7 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt final Sensor orientationSensor = sensorManager.getDefaultSensor( Sensor.TYPE_DEVICE_ORIENTATION); mPostureEstimator = new PostureEstimator(mHandler, sensorManager, mPostureEstimator = new PostureEstimator(mHandler, mFeatureFlags, sensorManager, leftAccelerometerSensor, rightAccelerometerSensor, orientationSensor, updatesListener::onClosedStateUpdated); } Loading @@ -127,8 +127,8 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt public void init() { if (mFeatureFlags.forceFoldablesTentModeWithScreenWakelock()) { try { mPowerManager.addScreenTimeoutPolicyListener(DEFAULT_DISPLAY, Runnable::run, new ScreenTimeoutPolicyListener()); mPowerManager.addScreenTimeoutPolicyListener(DEFAULT_DISPLAY, new HandlerExecutor(mHandler), mPostureEstimator); } catch (IllegalStateException exception) { // TODO: b/389613319 - remove after removing the screen timeout policy API flagging Slog.e(TAG, "Error subscribing to the screen timeout policy changes"); Loading @@ -149,8 +149,7 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt mPostureEstimator.onDeviceClosedStatusChanged(hingeAngle == ANGLE_0); final boolean isLikelyTentOrWedgeMode = mPostureEstimator.isLikelyTentOrWedgeMode() || shouldForceTentOrWedgeMode(); final boolean isLikelyTentOrWedgeMode = mPostureEstimator.isLikelyTentOrWedgeMode(); final PreferredScreen preferredScreen = mClosedStateCalculator. calculatePreferredScreen(hingeAngle, isLikelyTentOrWedgeMode, Loading @@ -159,14 +158,6 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt return preferredScreen == OUTER; } private boolean shouldForceTentOrWedgeMode() { if (!mFeatureFlags.forceFoldablesTentModeWithScreenWakelock()) { return false; } return mScreenTimeoutPolicy == PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON; } private HingeAngle hingeAngleFromFloat(float hingeAngle) { if (hingeAngle == 0f) { return ANGLE_0; Loading Loading @@ -204,7 +195,6 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt @Override public void dump(@NonNull PrintWriter writer, @Nullable String[] args) { writer.println(" " + getDumpableName()); writer.println(" mScreenTimeoutPolicy=" + mScreenTimeoutPolicy); mPostureEstimator.dump(writer, args); mClosedStateCalculator.dump(writer, args); } Loading @@ -213,19 +203,11 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt void onClosedStateUpdated(); } private class ScreenTimeoutPolicyListener implements PowerManager.ScreenTimeoutPolicyListener { @Override public void onScreenTimeoutPolicyChanged(int screenTimeoutPolicy) { // called from the binder thread mScreenTimeoutPolicy = screenTimeoutPolicy; } } /** * Estimates if the device is going to enter wedge/tent mode based on the sensor data */ private static class PostureEstimator implements SensorEventListener, Dumpable { private static class PostureEstimator implements SensorEventListener, ScreenTimeoutPolicyListener, Dumpable { private static final String FLAT_INCLINATION_THRESHOLD_DEGREES_PROPERTY = "persist.foldable_postures.wedge_inclination_threshold_degrees"; Loading @@ -245,9 +227,10 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt @Nullable private final Sensor mRightAccelerometerSensor; private final Sensor mOrientationSensor; private final Runnable mOnSensorUpdatedListener; private final Runnable mOnEstimationChanged; private final ConditionSensorListener mConditionedSensorListener; private final FeatureFlags mFeatureFlags; @Nullable private float[] mRightGravityVector; Loading @@ -261,17 +244,22 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt @Nullable private SensorEvent mLastDeviceOrientationSensorEvent = null; @ScreenTimeoutPolicy private int mScreenTimeoutPolicy = PowerManager.SCREEN_TIMEOUT_ACTIVE; private boolean mScreenTurnedOn = false; private boolean mDeviceClosed = false; public PostureEstimator(Handler handler, SensorManager sensorManager, @Nullable Sensor leftAccelerometerSensor, @Nullable Sensor rightAccelerometerSensor, Sensor orientationSensor, Runnable onSensorUpdated) { public PostureEstimator(Handler handler, FeatureFlags featureFlags, SensorManager sensorManager, @Nullable Sensor leftAccelerometerSensor, @Nullable Sensor rightAccelerometerSensor, Sensor orientationSensor, Runnable onEstimationChanged) { mLeftAccelerometerSensor = leftAccelerometerSensor; mRightAccelerometerSensor = rightAccelerometerSensor; mOrientationSensor = orientationSensor; mOnSensorUpdatedListener = onSensorUpdated; mFeatureFlags = featureFlags; mOnEstimationChanged = onEstimationChanged; final List<SensorSubscription> sensorSubscriptions = new ArrayList<>(); if (mLeftAccelerometerSensor != null) { Loading Loading @@ -320,7 +308,7 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt mLastDeviceOrientationSensorEvent = event; } mOnSensorUpdatedListener.run(); mOnEstimationChanged.run(); } @Override Loading @@ -328,6 +316,16 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt } /** * Called from {@link BookStyleClosedStatePredicate#mHandler}'s thread * (system server's main thread) */ @Override public void onScreenTimeoutPolicyChanged(int screenTimeoutPolicy) { mScreenTimeoutPolicy = screenTimeoutPolicy; mOnEstimationChanged.run(); } private void setNewValueWithHighPassFilter(float[] output, float[] newValues) { final float alpha = GRAVITY_VECTOR_LOW_PASS_ALPHA_VALUE; output[0] = alpha * output[0] + (1 - alpha) * newValues[0]; Loading @@ -345,9 +343,12 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt } /** * Returns true if the phone is likely in tent or wedge mode when unfolding. Tent mode * is detected by checking if the phone is in seascape position, screen is rotated to * landscape or seascape, or if the right side of the device is mostly flat. * Returns true if the phone is likely in tent or wedge mode when unfolding. * Tent/wedge mode is detected by checking if: * - the phone is in seascape position * - screen is rotated to landscape or seascape * - if the right side of the device is mostly flat * - if there is an active screen wake lock */ public boolean isLikelyTentOrWedgeMode() { boolean isScreenLandscapeOrSeascape = Objects.equals(mLastScreenRotation, Loading @@ -369,6 +370,11 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt return true; } if (mFeatureFlags.forceFoldablesTentModeWithScreenWakelock() && mScreenTimeoutPolicy == PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON) { return true; } return false; } Loading Loading @@ -414,6 +420,7 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt */ public void onDisplayRotationChanged(int rotation) { mLastScreenRotation = rotation; mOnEstimationChanged.run(); } /** Loading @@ -430,6 +437,7 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt writer.println(" isLikelyTentOrWedgeMode = " + isLikelyTentOrWedgeMode()); writer.println(" mScreenTurnedOn = " + mScreenTurnedOn); writer.println(" mLastScreenRotation = " + mLastScreenRotation); writer.println(" mScreenTimeoutPolicy=" + mScreenTimeoutPolicy); writer.println(" mDeviceClosed = " + mDeviceClosed); writer.println(" mLeftGravityVector = " + Arrays.toString(mLeftGravityVector)); writer.println(" mRightGravityVector = " + Arrays.toString(mRightGravityVector)); Loading services/foldables/devicestateprovider/tests/src/com/android/server/policy/BookStyleDeviceStatePolicyTest.java +56 −0 Original line number Diff line number Diff line Loading @@ -475,6 +475,21 @@ public final class BookStyleDeviceStatePolicyTest { verify(mListener, never()).onStateChanged(mDeviceStateCaptor.capture()); } @Test public void test_unfoldTo30Degrees_becomesLandscapeScreenRotation_keepsClosedState() { sendHingeAngle(0f); sendRightSideFlatSensorEvent(false); sendScreenRotation(Surface.ROTATION_0); mProvider.setListener(mListener); assertLatestReportedState(DEVICE_STATE_CLOSED); sendScreenRotation(Surface.ROTATION_90); clearInvocations(mListener); sendHingeAngle(30f); verify(mListener, never()).onStateChanged(mDeviceStateCaptor.capture()); } @Test public void test_unfoldTo30Degrees_seascapeScreenRotation_keepsClosedState() { sendHingeAngle(0f); Loading Loading @@ -643,6 +658,47 @@ public final class BookStyleDeviceStatePolicyTest { assertLatestReportedState(DEVICE_STATE_HALF_OPENED); } @Test public void test_unfoldTo85Degrees_afterScreenWakeLockBecomesActive_keepsClosedDeviceState() throws Exception { mFakeFeatureFlags.setFlag(Flags.FLAG_FORCE_FOLDABLES_TENT_MODE_WITH_SCREEN_WAKELOCK, true); mInstrumentation.runOnMainSync(() -> mProvider = createProvider()); mPolicy.getDeviceStateProvider().onSystemReady(); sendHingeAngle(0f); mProvider.setListener(mListener); assertLatestReportedState(DEVICE_STATE_CLOSED); final ScreenTimeoutPolicyListener listener = captureScreenTimeoutPolicyListener(); listener.onScreenTimeoutPolicyChanged(PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON); sendHingeAngle(15f); assertLatestReportedState(DEVICE_STATE_CLOSED); sendHingeAngle(85f); assertLatestReportedState(DEVICE_STATE_CLOSED); } @Test public void test_unfoldTo85Degrees_screenWakeLockPresentAndThenRemoved_movesToHalfOpenedState() throws Exception { mFakeFeatureFlags.setFlag(Flags.FLAG_FORCE_FOLDABLES_TENT_MODE_WITH_SCREEN_WAKELOCK, true); mInstrumentation.runOnMainSync(() -> mProvider = createProvider()); mPolicy.getDeviceStateProvider().onSystemReady(); sendHingeAngle(0f); mProvider.setListener(mListener); assertLatestReportedState(DEVICE_STATE_CLOSED); final ScreenTimeoutPolicyListener listener = captureScreenTimeoutPolicyListener(); listener.onScreenTimeoutPolicyChanged(PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON); listener.onScreenTimeoutPolicyChanged(PowerManager.SCREEN_TIMEOUT_ACTIVE); sendHingeAngle(15f); assertLatestReportedState(DEVICE_STATE_HALF_OPENED); sendHingeAngle(85f); assertLatestReportedState(DEVICE_STATE_HALF_OPENED); } @Test public void test_unfoldTo85Degrees_notSubscribedToWakeLocks_forceTentModeWithWakeLockDisabled() throws Exception { Loading Loading
services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleClosedStatePredicate.java +44 −36 Original line number Diff line number Diff line Loading @@ -34,7 +34,10 @@ import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.HandlerExecutor; import android.os.PowerManager; import android.os.PowerManager.ScreenTimeoutPolicy; import android.os.PowerManager.ScreenTimeoutPolicyListener; import android.util.ArraySet; import android.util.Dumpable; import android.util.Slog; Loading Loading @@ -75,9 +78,6 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt private final FeatureFlags mFeatureFlags; private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo(); @PowerManager.ScreenTimeoutPolicy private volatile int mScreenTimeoutPolicy; /** * Creates {@link BookStyleClosedStatePredicate}. It is expected that the device has a pair * of accelerometer sensors (one for each movable part of the device), see parameter Loading Loading @@ -115,7 +115,7 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt final Sensor orientationSensor = sensorManager.getDefaultSensor( Sensor.TYPE_DEVICE_ORIENTATION); mPostureEstimator = new PostureEstimator(mHandler, sensorManager, mPostureEstimator = new PostureEstimator(mHandler, mFeatureFlags, sensorManager, leftAccelerometerSensor, rightAccelerometerSensor, orientationSensor, updatesListener::onClosedStateUpdated); } Loading @@ -127,8 +127,8 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt public void init() { if (mFeatureFlags.forceFoldablesTentModeWithScreenWakelock()) { try { mPowerManager.addScreenTimeoutPolicyListener(DEFAULT_DISPLAY, Runnable::run, new ScreenTimeoutPolicyListener()); mPowerManager.addScreenTimeoutPolicyListener(DEFAULT_DISPLAY, new HandlerExecutor(mHandler), mPostureEstimator); } catch (IllegalStateException exception) { // TODO: b/389613319 - remove after removing the screen timeout policy API flagging Slog.e(TAG, "Error subscribing to the screen timeout policy changes"); Loading @@ -149,8 +149,7 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt mPostureEstimator.onDeviceClosedStatusChanged(hingeAngle == ANGLE_0); final boolean isLikelyTentOrWedgeMode = mPostureEstimator.isLikelyTentOrWedgeMode() || shouldForceTentOrWedgeMode(); final boolean isLikelyTentOrWedgeMode = mPostureEstimator.isLikelyTentOrWedgeMode(); final PreferredScreen preferredScreen = mClosedStateCalculator. calculatePreferredScreen(hingeAngle, isLikelyTentOrWedgeMode, Loading @@ -159,14 +158,6 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt return preferredScreen == OUTER; } private boolean shouldForceTentOrWedgeMode() { if (!mFeatureFlags.forceFoldablesTentModeWithScreenWakelock()) { return false; } return mScreenTimeoutPolicy == PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON; } private HingeAngle hingeAngleFromFloat(float hingeAngle) { if (hingeAngle == 0f) { return ANGLE_0; Loading Loading @@ -204,7 +195,6 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt @Override public void dump(@NonNull PrintWriter writer, @Nullable String[] args) { writer.println(" " + getDumpableName()); writer.println(" mScreenTimeoutPolicy=" + mScreenTimeoutPolicy); mPostureEstimator.dump(writer, args); mClosedStateCalculator.dump(writer, args); } Loading @@ -213,19 +203,11 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt void onClosedStateUpdated(); } private class ScreenTimeoutPolicyListener implements PowerManager.ScreenTimeoutPolicyListener { @Override public void onScreenTimeoutPolicyChanged(int screenTimeoutPolicy) { // called from the binder thread mScreenTimeoutPolicy = screenTimeoutPolicy; } } /** * Estimates if the device is going to enter wedge/tent mode based on the sensor data */ private static class PostureEstimator implements SensorEventListener, Dumpable { private static class PostureEstimator implements SensorEventListener, ScreenTimeoutPolicyListener, Dumpable { private static final String FLAT_INCLINATION_THRESHOLD_DEGREES_PROPERTY = "persist.foldable_postures.wedge_inclination_threshold_degrees"; Loading @@ -245,9 +227,10 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt @Nullable private final Sensor mRightAccelerometerSensor; private final Sensor mOrientationSensor; private final Runnable mOnSensorUpdatedListener; private final Runnable mOnEstimationChanged; private final ConditionSensorListener mConditionedSensorListener; private final FeatureFlags mFeatureFlags; @Nullable private float[] mRightGravityVector; Loading @@ -261,17 +244,22 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt @Nullable private SensorEvent mLastDeviceOrientationSensorEvent = null; @ScreenTimeoutPolicy private int mScreenTimeoutPolicy = PowerManager.SCREEN_TIMEOUT_ACTIVE; private boolean mScreenTurnedOn = false; private boolean mDeviceClosed = false; public PostureEstimator(Handler handler, SensorManager sensorManager, @Nullable Sensor leftAccelerometerSensor, @Nullable Sensor rightAccelerometerSensor, Sensor orientationSensor, Runnable onSensorUpdated) { public PostureEstimator(Handler handler, FeatureFlags featureFlags, SensorManager sensorManager, @Nullable Sensor leftAccelerometerSensor, @Nullable Sensor rightAccelerometerSensor, Sensor orientationSensor, Runnable onEstimationChanged) { mLeftAccelerometerSensor = leftAccelerometerSensor; mRightAccelerometerSensor = rightAccelerometerSensor; mOrientationSensor = orientationSensor; mOnSensorUpdatedListener = onSensorUpdated; mFeatureFlags = featureFlags; mOnEstimationChanged = onEstimationChanged; final List<SensorSubscription> sensorSubscriptions = new ArrayList<>(); if (mLeftAccelerometerSensor != null) { Loading Loading @@ -320,7 +308,7 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt mLastDeviceOrientationSensorEvent = event; } mOnSensorUpdatedListener.run(); mOnEstimationChanged.run(); } @Override Loading @@ -328,6 +316,16 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt } /** * Called from {@link BookStyleClosedStatePredicate#mHandler}'s thread * (system server's main thread) */ @Override public void onScreenTimeoutPolicyChanged(int screenTimeoutPolicy) { mScreenTimeoutPolicy = screenTimeoutPolicy; mOnEstimationChanged.run(); } private void setNewValueWithHighPassFilter(float[] output, float[] newValues) { final float alpha = GRAVITY_VECTOR_LOW_PASS_ALPHA_VALUE; output[0] = alpha * output[0] + (1 - alpha) * newValues[0]; Loading @@ -345,9 +343,12 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt } /** * Returns true if the phone is likely in tent or wedge mode when unfolding. Tent mode * is detected by checking if the phone is in seascape position, screen is rotated to * landscape or seascape, or if the right side of the device is mostly flat. * Returns true if the phone is likely in tent or wedge mode when unfolding. * Tent/wedge mode is detected by checking if: * - the phone is in seascape position * - screen is rotated to landscape or seascape * - if the right side of the device is mostly flat * - if there is an active screen wake lock */ public boolean isLikelyTentOrWedgeMode() { boolean isScreenLandscapeOrSeascape = Objects.equals(mLastScreenRotation, Loading @@ -369,6 +370,11 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt return true; } if (mFeatureFlags.forceFoldablesTentModeWithScreenWakelock() && mScreenTimeoutPolicy == PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON) { return true; } return false; } Loading Loading @@ -414,6 +420,7 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt */ public void onDisplayRotationChanged(int rotation) { mLastScreenRotation = rotation; mOnEstimationChanged.run(); } /** Loading @@ -430,6 +437,7 @@ public class BookStyleClosedStatePredicate implements Predicate<FoldableDeviceSt writer.println(" isLikelyTentOrWedgeMode = " + isLikelyTentOrWedgeMode()); writer.println(" mScreenTurnedOn = " + mScreenTurnedOn); writer.println(" mLastScreenRotation = " + mLastScreenRotation); writer.println(" mScreenTimeoutPolicy=" + mScreenTimeoutPolicy); writer.println(" mDeviceClosed = " + mDeviceClosed); writer.println(" mLeftGravityVector = " + Arrays.toString(mLeftGravityVector)); writer.println(" mRightGravityVector = " + Arrays.toString(mRightGravityVector)); Loading
services/foldables/devicestateprovider/tests/src/com/android/server/policy/BookStyleDeviceStatePolicyTest.java +56 −0 Original line number Diff line number Diff line Loading @@ -475,6 +475,21 @@ public final class BookStyleDeviceStatePolicyTest { verify(mListener, never()).onStateChanged(mDeviceStateCaptor.capture()); } @Test public void test_unfoldTo30Degrees_becomesLandscapeScreenRotation_keepsClosedState() { sendHingeAngle(0f); sendRightSideFlatSensorEvent(false); sendScreenRotation(Surface.ROTATION_0); mProvider.setListener(mListener); assertLatestReportedState(DEVICE_STATE_CLOSED); sendScreenRotation(Surface.ROTATION_90); clearInvocations(mListener); sendHingeAngle(30f); verify(mListener, never()).onStateChanged(mDeviceStateCaptor.capture()); } @Test public void test_unfoldTo30Degrees_seascapeScreenRotation_keepsClosedState() { sendHingeAngle(0f); Loading Loading @@ -643,6 +658,47 @@ public final class BookStyleDeviceStatePolicyTest { assertLatestReportedState(DEVICE_STATE_HALF_OPENED); } @Test public void test_unfoldTo85Degrees_afterScreenWakeLockBecomesActive_keepsClosedDeviceState() throws Exception { mFakeFeatureFlags.setFlag(Flags.FLAG_FORCE_FOLDABLES_TENT_MODE_WITH_SCREEN_WAKELOCK, true); mInstrumentation.runOnMainSync(() -> mProvider = createProvider()); mPolicy.getDeviceStateProvider().onSystemReady(); sendHingeAngle(0f); mProvider.setListener(mListener); assertLatestReportedState(DEVICE_STATE_CLOSED); final ScreenTimeoutPolicyListener listener = captureScreenTimeoutPolicyListener(); listener.onScreenTimeoutPolicyChanged(PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON); sendHingeAngle(15f); assertLatestReportedState(DEVICE_STATE_CLOSED); sendHingeAngle(85f); assertLatestReportedState(DEVICE_STATE_CLOSED); } @Test public void test_unfoldTo85Degrees_screenWakeLockPresentAndThenRemoved_movesToHalfOpenedState() throws Exception { mFakeFeatureFlags.setFlag(Flags.FLAG_FORCE_FOLDABLES_TENT_MODE_WITH_SCREEN_WAKELOCK, true); mInstrumentation.runOnMainSync(() -> mProvider = createProvider()); mPolicy.getDeviceStateProvider().onSystemReady(); sendHingeAngle(0f); mProvider.setListener(mListener); assertLatestReportedState(DEVICE_STATE_CLOSED); final ScreenTimeoutPolicyListener listener = captureScreenTimeoutPolicyListener(); listener.onScreenTimeoutPolicyChanged(PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON); listener.onScreenTimeoutPolicyChanged(PowerManager.SCREEN_TIMEOUT_ACTIVE); sendHingeAngle(15f); assertLatestReportedState(DEVICE_STATE_HALF_OPENED); sendHingeAngle(85f); assertLatestReportedState(DEVICE_STATE_HALF_OPENED); } @Test public void test_unfoldTo85Degrees_notSubscribedToWakeLocks_forceTentModeWithWakeLockDisabled() throws Exception { Loading