Make DeviceStateController generic

Previously it was specific to fold-state, and used to notify a single
client of fold-state changes. DeviceStateController is now
generic and can be used (or modified) to cache, query, or receive
callbacks for other state changes.

Note that we are purposely removing the nested FoldStateListener class
since it's a very thin layer and makes it unnecessarily complex when
we add new functionality to DeviceStateController. A simple example would
be DeviceStateController#getCurrentState() needing to access an inner
FoldStateListener#getCurrentState().

Bug: 264499484
Test: atest DisplayRotationTests
Test: atest DeviceStateControllerTests
Change-Id: I81b0a61b52d74718fe1dee213a59509a44a9a920
This commit is contained in:
Kevin Chyn
2023-01-24 04:50:46 +00:00
parent 286074d5cf
commit b6e9d2fcc1
10 changed files with 179 additions and 147 deletions

View File

@@ -652,6 +652,16 @@
The default is false. -->
<bool name="config_lidControlsSleep">false</bool>
<!-- The device states (supplied by DeviceStateManager) that should be treated as open by the
device fold controller. Default is empty. -->
<integer-array name="config_openDeviceStates">
<!-- Example:
<item>0</item>
<item>1</item>
<item>2</item>
-->
</integer-array>
<!-- The device states (supplied by DeviceStateManager) that should be treated as folded by the
display fold controller. Default is empty. -->
<integer-array name="config_foldedDeviceStates">
@@ -672,6 +682,16 @@
-->
</integer-array>
<!-- The device states (supplied by DeviceStateManager) that should be treated as a rear display
state. Default is empty. -->
<integer-array name="config_rearDisplayDeviceStates">
<!-- Example:
<item>0</item>
<item>1</item>
<item>2</item>
-->
</integer-array>
<!-- Indicates whether the window manager reacts to half-fold device states by overriding
rotation. -->
<bool name="config_windowManagerHalfFoldAutoRotateOverride">false</bool>

View File

@@ -4015,8 +4015,10 @@
<java-symbol type="integer" name="config_maxScanTasksForHomeVisibility" />
<!-- For Foldables -->
<java-symbol type="array" name="config_openDeviceStates" />
<java-symbol type="array" name="config_foldedDeviceStates" />
<java-symbol type="array" name="config_halfFoldedDeviceStates" />
<java-symbol type="array" name="config_rearDisplayDeviceStates" />
<java-symbol type="bool" name="config_windowManagerHalfFoldAutoRotateOverride" />
<java-symbol type="array" name="config_deviceStatesOnWhichToWakeUp" />
<java-symbol type="array" name="config_deviceStatesOnWhichToSleep" />

View File

@@ -16,80 +16,92 @@
package com.android.server.wm;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Handler;
import android.os.HandlerExecutor;
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* Class that registers callbacks with the {@link DeviceStateManager} and
* responds to fold state changes by forwarding such events to a delegate.
* Class that registers callbacks with the {@link DeviceStateManager} and responds to device
* changes.
*/
final class DeviceStateController {
final class DeviceStateController implements DeviceStateManager.DeviceStateCallback {
@NonNull
private final DeviceStateManager mDeviceStateManager;
private final Context mContext;
@NonNull
private final int[] mOpenDeviceStates;
@NonNull
private final int[] mHalfFoldedDeviceStates;
@NonNull
private final int[] mFoldedDeviceStates;
@NonNull
private final int[] mRearDisplayDeviceStates;
@NonNull
private final List<Consumer<DeviceState>> mDeviceStateCallbacks = new ArrayList<>();
private FoldStateListener mDeviceStateListener;
@Nullable
private DeviceState mLastDeviceState;
public enum FoldState {
UNKNOWN, OPEN, FOLDED, HALF_FOLDED
public enum DeviceState {
UNKNOWN, OPEN, FOLDED, HALF_FOLDED, REAR,
}
DeviceStateController(Context context, Handler handler, Consumer<FoldState> delegate) {
mContext = context;
mDeviceStateManager = mContext.getSystemService(DeviceStateManager.class);
DeviceStateController(@NonNull Context context, @NonNull Handler handler) {
mDeviceStateManager = context.getSystemService(DeviceStateManager.class);
mOpenDeviceStates = context.getResources()
.getIntArray(R.array.config_openDeviceStates);
mHalfFoldedDeviceStates = context.getResources()
.getIntArray(R.array.config_halfFoldedDeviceStates);
mFoldedDeviceStates = context.getResources()
.getIntArray(R.array.config_foldedDeviceStates);
mRearDisplayDeviceStates = context.getResources()
.getIntArray(R.array.config_rearDisplayDeviceStates);
if (mDeviceStateManager != null) {
mDeviceStateListener = new FoldStateListener(mContext, delegate);
mDeviceStateManager
.registerCallback(new HandlerExecutor(handler),
mDeviceStateListener);
mDeviceStateManager.registerCallback(new HandlerExecutor(handler), this);
}
}
void unregisterFromDeviceStateManager() {
if (mDeviceStateListener != null) {
mDeviceStateManager.unregisterCallback(mDeviceStateListener);
if (mDeviceStateManager != null) {
mDeviceStateManager.unregisterCallback(this);
}
}
/**
* A listener for half-fold device state events that dispatches state changes to a delegate.
*/
static final class FoldStateListener implements DeviceStateManager.DeviceStateCallback {
void registerDeviceStateCallback(@NonNull Consumer<DeviceState> callback) {
mDeviceStateCallbacks.add(callback);
}
private final int[] mHalfFoldedDeviceStates;
private final int[] mFoldedDeviceStates;
@Nullable
private FoldState mLastResult;
private final Consumer<FoldState> mDelegate;
FoldStateListener(Context context, Consumer<FoldState> delegate) {
mFoldedDeviceStates = context.getResources().getIntArray(
com.android.internal.R.array.config_foldedDeviceStates);
mHalfFoldedDeviceStates = context.getResources().getIntArray(
com.android.internal.R.array.config_halfFoldedDeviceStates);
mDelegate = delegate;
@Override
public void onStateChanged(int state) {
final DeviceState deviceState;
if (ArrayUtils.contains(mHalfFoldedDeviceStates, state)) {
deviceState = DeviceState.HALF_FOLDED;
} else if (ArrayUtils.contains(mFoldedDeviceStates, state)) {
deviceState = DeviceState.FOLDED;
} else if (ArrayUtils.contains(mRearDisplayDeviceStates, state)) {
deviceState = DeviceState.REAR;
} else if (ArrayUtils.contains(mOpenDeviceStates, state)) {
deviceState = DeviceState.OPEN;
} else {
deviceState = DeviceState.UNKNOWN;
}
@Override
public void onStateChanged(int state) {
final boolean halfFolded = ArrayUtils.contains(mHalfFoldedDeviceStates, state);
FoldState result;
if (halfFolded) {
result = FoldState.HALF_FOLDED;
} else {
final boolean folded = ArrayUtils.contains(mFoldedDeviceStates, state);
result = folded ? FoldState.FOLDED : FoldState.OPEN;
}
if (mLastResult == null || !mLastResult.equals(result)) {
mLastResult = result;
mDelegate.accept(result);
if (mLastDeviceState == null || !mLastDeviceState.equals(deviceState)) {
mLastDeviceState = deviceState;
for (Consumer<DeviceState> callback : mDeviceStateCallbacks) {
callback.accept(mLastDeviceState);
}
}
}

View File

@@ -1125,14 +1125,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mWmService.mAtmService.getRecentTasks().getInputListener());
}
mDeviceStateController = new DeviceStateController(mWmService.mContext, mWmService.mH);
mDisplayPolicy = new DisplayPolicy(mWmService, this);
mDisplayRotation = new DisplayRotation(mWmService, this, mDisplayInfo.address);
mDeviceStateController = new DeviceStateController(mWmService.mContext, mWmService.mH,
newFoldState -> {
final Consumer<DeviceStateController.DeviceState> deviceStateConsumer =
(@NonNull DeviceStateController.DeviceState newFoldState) -> {
mDisplaySwitchTransitionLauncher.foldStateChanged(newFoldState);
mDisplayRotation.foldStateChanged(newFoldState);
});
};
mDeviceStateController.registerDeviceStateCallback(deviceStateConsumer);
mCloseToSquareMaxAspectRatio = mWmService.mContext.getResources().getFloat(
R.dimen.config_closeToSquareDisplayMaxAspectRatio);

View File

@@ -1573,7 +1573,7 @@ public class DisplayRotation {
proto.end(token);
}
boolean isDeviceInPosture(DeviceStateController.FoldState state, boolean isTabletop) {
boolean isDeviceInPosture(DeviceStateController.DeviceState state, boolean isTabletop) {
if (mFoldController == null) return false;
return mFoldController.isDeviceInPosture(state, isTabletop);
}
@@ -1585,10 +1585,10 @@ public class DisplayRotation {
/**
* Called by the DeviceStateManager callback when the device state changes.
*/
void foldStateChanged(DeviceStateController.FoldState foldState) {
void foldStateChanged(DeviceStateController.DeviceState deviceState) {
if (mFoldController != null) {
synchronized (mLock) {
mFoldController.foldStateChanged(foldState);
mFoldController.foldStateChanged(deviceState);
}
}
}
@@ -1596,8 +1596,8 @@ public class DisplayRotation {
private class FoldController {
@Surface.Rotation
private int mHalfFoldSavedRotation = -1; // No saved rotation
private DeviceStateController.FoldState mFoldState =
DeviceStateController.FoldState.UNKNOWN;
private DeviceStateController.DeviceState mDeviceState =
DeviceStateController.DeviceState.UNKNOWN;
private boolean mInHalfFoldTransition = false;
private final boolean mIsDisplayAlwaysSeparatingHinge;
private final Set<Integer> mTabletopRotations;
@@ -1637,32 +1637,33 @@ public class DisplayRotation {
R.bool.config_isDisplayHingeAlwaysSeparating);
}
boolean isDeviceInPosture(DeviceStateController.FoldState state, boolean isTabletop) {
if (state != mFoldState) {
boolean isDeviceInPosture(DeviceStateController.DeviceState state, boolean isTabletop) {
if (state != mDeviceState) {
return false;
}
if (mFoldState == DeviceStateController.FoldState.HALF_FOLDED) {
if (mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) {
return !(isTabletop ^ mTabletopRotations.contains(mRotation));
}
return true;
}
DeviceStateController.FoldState getFoldState() {
return mFoldState;
DeviceStateController.DeviceState getFoldState() {
return mDeviceState;
}
boolean isSeparatingHinge() {
return mFoldState == DeviceStateController.FoldState.HALF_FOLDED
|| (mFoldState == DeviceStateController.FoldState.OPEN
return mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED
|| (mDeviceState == DeviceStateController.DeviceState.OPEN
&& mIsDisplayAlwaysSeparatingHinge);
}
boolean overrideFrozenRotation() {
return mFoldState == DeviceStateController.FoldState.HALF_FOLDED;
return mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED;
}
boolean shouldRevertOverriddenRotation() {
return mFoldState == DeviceStateController.FoldState.OPEN // When transitioning to open.
// When transitioning to open.
return mDeviceState == DeviceStateController.DeviceState.OPEN
&& mInHalfFoldTransition
&& mHalfFoldSavedRotation != -1 // Ignore if we've already reverted.
&& mUserRotationMode
@@ -1676,30 +1677,30 @@ public class DisplayRotation {
return savedRotation;
}
void foldStateChanged(DeviceStateController.FoldState newState) {
void foldStateChanged(DeviceStateController.DeviceState newState) {
ProtoLog.v(WM_DEBUG_ORIENTATION,
"foldStateChanged: displayId %d, halfFoldStateChanged %s, "
+ "saved rotation: %d, mUserRotation: %d, mLastSensorRotation: %d, "
+ "mLastOrientation: %d, mRotation: %d",
mDisplayContent.getDisplayId(), newState.name(), mHalfFoldSavedRotation,
mUserRotation, mLastSensorRotation, mLastOrientation, mRotation);
if (mFoldState == DeviceStateController.FoldState.UNKNOWN) {
mFoldState = newState;
if (mDeviceState == DeviceStateController.DeviceState.UNKNOWN) {
mDeviceState = newState;
return;
}
if (newState == DeviceStateController.FoldState.HALF_FOLDED
&& mFoldState != DeviceStateController.FoldState.HALF_FOLDED) {
if (newState == DeviceStateController.DeviceState.HALF_FOLDED
&& mDeviceState != DeviceStateController.DeviceState.HALF_FOLDED) {
// The device has transitioned to HALF_FOLDED state: save the current rotation and
// update the device rotation.
mHalfFoldSavedRotation = mRotation;
mFoldState = newState;
mDeviceState = newState;
// Now mFoldState is set to HALF_FOLDED, the overrideFrozenRotation function will
// return true, so rotation is unlocked.
mService.updateRotation(false /* alwaysSendConfiguration */,
false /* forceRelayout */);
} else {
mInHalfFoldTransition = true;
mFoldState = newState;
mDeviceState = newState;
// Tell the device to update its orientation.
mService.updateRotation(false /* alwaysSendConfiguration */,
false /* forceRelayout */);
@@ -1822,7 +1823,7 @@ public class DisplayRotation {
final long mTimestamp = System.currentTimeMillis();
final int mHalfFoldSavedRotation;
final boolean mInHalfFoldTransition;
final DeviceStateController.FoldState mFoldState;
final DeviceStateController.DeviceState mDeviceState;
@Nullable final String mDisplayRotationCompatPolicySummary;
Record(DisplayRotation dr, int fromRotation, int toRotation) {
@@ -1852,11 +1853,11 @@ public class DisplayRotation {
if (dr.mFoldController != null) {
mHalfFoldSavedRotation = dr.mFoldController.mHalfFoldSavedRotation;
mInHalfFoldTransition = dr.mFoldController.mInHalfFoldTransition;
mFoldState = dr.mFoldController.mFoldState;
mDeviceState = dr.mFoldController.mDeviceState;
} else {
mHalfFoldSavedRotation = NO_FOLD_CONTROLLER;
mInHalfFoldTransition = false;
mFoldState = DeviceStateController.FoldState.UNKNOWN;
mDeviceState = DeviceStateController.DeviceState.UNKNOWN;
}
mDisplayRotationCompatPolicySummary = dc.mDisplayRotationCompatPolicy == null
? null
@@ -1882,7 +1883,7 @@ public class DisplayRotation {
pw.println(prefix + " halfFoldSavedRotation="
+ mHalfFoldSavedRotation
+ " mInHalfFoldTransition=" + mInHalfFoldTransition
+ " mFoldState=" + mFoldState);
+ " mFoldState=" + mDeviceState);
}
if (mDisplayRotationCompatPolicySummary != null) {
pw.println(prefix + mDisplayRotationCompatPolicySummary);

View File

@@ -533,7 +533,7 @@ final class LetterboxUiController {
// Note that we check the task rather than the parent as with ActivityEmbedding the parent might
// be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is
// actually fullscreen.
private boolean isDisplayFullScreenAndInPosture(DeviceStateController.FoldState state,
private boolean isDisplayFullScreenAndInPosture(DeviceStateController.DeviceState state,
boolean isTabletop) {
Task task = mActivityRecord.getTask();
return mActivityRecord.mDisplayContent != null
@@ -559,7 +559,7 @@ final class LetterboxUiController {
// Don't check resolved configuration because it may not be updated yet during
// configuration change.
boolean bookMode = isDisplayFullScreenAndInPosture(
DeviceStateController.FoldState.HALF_FOLDED, false /* isTabletop */);
DeviceStateController.DeviceState.HALF_FOLDED, false /* isTabletop */);
return isHorizontalReachabilityEnabled(parentConfiguration)
// Using the last global dynamic position to avoid "jumps" when moving
// between apps or activities.
@@ -571,7 +571,7 @@ final class LetterboxUiController {
// Don't check resolved configuration because it may not be updated yet during
// configuration change.
boolean tabletopMode = isDisplayFullScreenAndInPosture(
DeviceStateController.FoldState.HALF_FOLDED, true /* isTabletop */);
DeviceStateController.DeviceState.HALF_FOLDED, true /* isTabletop */);
return isVerticalReachabilityEnabled(parentConfiguration)
// Using the last global dynamic position to avoid "jumps" when moving
// between apps or activities.
@@ -1087,7 +1087,7 @@ final class LetterboxUiController {
int letterboxPositionForHorizontalReachability = getLetterboxConfiguration()
.getLetterboxPositionForHorizontalReachability(
isDisplayFullScreenAndInPosture(
DeviceStateController.FoldState.HALF_FOLDED,
DeviceStateController.DeviceState.HALF_FOLDED,
false /* isTabletop */));
positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPosition(
letterboxPositionForHorizontalReachability);
@@ -1095,7 +1095,7 @@ final class LetterboxUiController {
int letterboxPositionForVerticalReachability = getLetterboxConfiguration()
.getLetterboxPositionForVerticalReachability(
isDisplayFullScreenAndInPosture(
DeviceStateController.FoldState.HALF_FOLDED,
DeviceStateController.DeviceState.HALF_FOLDED,
true /* isTabletop */));
positionToLog = letterboxVerticalReachabilityPositionToLetterboxPosition(
letterboxPositionForVerticalReachability);

View File

@@ -51,10 +51,10 @@ public class PhysicalDisplaySwitchTransitionLauncher {
/**
* Called by the DeviceStateManager callback when the state changes.
*/
void foldStateChanged(DeviceStateController.FoldState newFoldState) {
void foldStateChanged(DeviceStateController.DeviceState newDeviceState) {
// Ignore transitions to/from half-folded.
if (newFoldState == DeviceStateController.FoldState.HALF_FOLDED) return;
mIsFolded = newFoldState == DeviceStateController.FoldState.FOLDED;
if (newDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) return;
mIsFolded = newDeviceState == DeviceStateController.DeviceState.FOLDED;
}
/**

View File

@@ -16,13 +16,12 @@
package com.android.server.wm;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
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 org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import android.content.Context;
import android.content.res.Resources;
@@ -32,9 +31,10 @@ import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import com.android.internal.R;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.util.function.Consumer;
@@ -48,92 +48,76 @@ import java.util.function.Consumer;
@Presubmit
public class DeviceStateControllerTests {
private DeviceStateController.FoldStateListener mFoldStateListener;
private DeviceStateController mTarget;
private DeviceStateControllerBuilder mBuilder;
private Context mMockContext;
private Handler mMockHandler;
private Resources mMockRes;
private DeviceStateManager mMockDeviceStateManager;
private Consumer<DeviceStateController.FoldState> mDelegate;
private DeviceStateController.FoldState mCurrentState = DeviceStateController.FoldState.UNKNOWN;
private DeviceStateController.DeviceState mCurrentState =
DeviceStateController.DeviceState.UNKNOWN;
@Before
public void setUp() {
mBuilder = new DeviceStateControllerBuilder();
mCurrentState = DeviceStateController.FoldState.UNKNOWN;
mCurrentState = DeviceStateController.DeviceState.UNKNOWN;
}
private void initialize(boolean supportFold, boolean supportHalfFold) throws Exception {
private void initialize(boolean supportFold, boolean supportHalfFold) {
mBuilder.setSupportFold(supportFold, supportHalfFold);
mDelegate = (newFoldState) -> {
Consumer<DeviceStateController.DeviceState> delegate = (newFoldState) -> {
mCurrentState = newFoldState;
};
mBuilder.setDelegate(mDelegate);
mBuilder.setDelegate(delegate);
mBuilder.build();
verifyFoldStateListenerRegistration(1);
verify(mMockDeviceStateManager).registerCallback(any(), any());
}
@Test
public void testInitialization() throws Exception {
public void testInitialization() {
initialize(true /* supportFold */, true /* supportHalfFolded */);
mFoldStateListener.onStateChanged(mUnfoldedStates[0]);
assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
mTarget.onStateChanged(mOpenDeviceStates[0]);
assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
}
@Test
public void testInitializationWithNoFoldSupport() throws Exception {
public void testInitializationWithNoFoldSupport() {
initialize(false /* supportFold */, false /* supportHalfFolded */);
mFoldStateListener.onStateChanged(mFoldedStates[0]);
mTarget.onStateChanged(mFoldedStates[0]);
// Note that the folded state is ignored.
assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
assertEquals(DeviceStateController.DeviceState.UNKNOWN, mCurrentState);
}
@Test
public void testWithFoldSupported() throws Exception {
public void testWithFoldSupported() {
initialize(true /* supportFold */, false /* supportHalfFolded */);
mFoldStateListener.onStateChanged(mUnfoldedStates[0]);
assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
mFoldStateListener.onStateChanged(mFoldedStates[0]);
assertEquals(mCurrentState, DeviceStateController.FoldState.FOLDED);
mFoldStateListener.onStateChanged(mHalfFoldedStates[0]);
assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN); // Ignored
mTarget.onStateChanged(mOpenDeviceStates[0]);
assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
mTarget.onStateChanged(mFoldedStates[0]);
assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
mTarget.onStateChanged(mHalfFoldedStates[0]);
assertEquals(DeviceStateController.DeviceState.UNKNOWN, mCurrentState); // Ignored
}
@Test
public void testWithHalfFoldSupported() throws Exception {
public void testWithHalfFoldSupported() {
initialize(true /* supportFold */, true /* supportHalfFolded */);
mFoldStateListener.onStateChanged(mUnfoldedStates[0]);
assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
mFoldStateListener.onStateChanged(mFoldedStates[0]);
assertEquals(mCurrentState, DeviceStateController.FoldState.FOLDED);
mFoldStateListener.onStateChanged(mHalfFoldedStates[0]);
assertEquals(mCurrentState, DeviceStateController.FoldState.HALF_FOLDED);
mTarget.onStateChanged(mOpenDeviceStates[0]);
assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
mTarget.onStateChanged(mFoldedStates[0]);
assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
mTarget.onStateChanged(mHalfFoldedStates[0]);
assertEquals(DeviceStateController.DeviceState.HALF_FOLDED, mCurrentState);
}
private final int[] mFoldedStates = {0};
private final int[] mUnfoldedStates = {1};
private final int[] mOpenDeviceStates = {1};
private final int[] mHalfFoldedStates = {2};
private void verifyFoldStateListenerRegistration(int numOfInvocation) {
final ArgumentCaptor<DeviceStateController.FoldStateListener> listenerCaptor =
ArgumentCaptor.forClass(DeviceStateController.FoldStateListener.class);
verify(mMockDeviceStateManager, times(numOfInvocation)).registerCallback(
any(),
listenerCaptor.capture());
if (numOfInvocation > 0) {
mFoldStateListener = listenerCaptor.getValue();
}
}
private final int[] mRearDisplayStates = {3};
private class DeviceStateControllerBuilder {
private boolean mSupportFold = false;
private boolean mSupportHalfFold = false;
private Consumer<DeviceStateController.FoldState> mDelegate;
private Consumer<DeviceStateController.DeviceState> mDelegate;
DeviceStateControllerBuilder setSupportFold(
boolean supportFold, boolean supportHalfFold) {
@@ -143,34 +127,44 @@ public class DeviceStateControllerTests {
}
DeviceStateControllerBuilder setDelegate(
Consumer<DeviceStateController.FoldState> delegate) {
Consumer<DeviceStateController.DeviceState> delegate) {
mDelegate = delegate;
return this;
}
private void mockFold(boolean enableFold, boolean enableHalfFold) {
if (enableFold || enableHalfFold) {
when(mMockContext.getResources()
.getIntArray(R.array.config_openDeviceStates))
.thenReturn(mOpenDeviceStates);
when(mMockContext.getResources()
.getIntArray(R.array.config_rearDisplayDeviceStates))
.thenReturn(mRearDisplayStates);
}
if (enableFold) {
when(mMockContext.getResources().getIntArray(
com.android.internal.R.array.config_foldedDeviceStates))
when(mMockContext.getResources()
.getIntArray(R.array.config_foldedDeviceStates))
.thenReturn(mFoldedStates);
}
if (enableHalfFold) {
when(mMockContext.getResources().getIntArray(
com.android.internal.R.array.config_halfFoldedDeviceStates))
when(mMockContext.getResources()
.getIntArray(R.array.config_halfFoldedDeviceStates))
.thenReturn(mHalfFoldedStates);
}
}
private void build() throws Exception {
private void build() {
mMockContext = mock(Context.class);
mMockRes = mock(Resources.class);
when(mMockContext.getResources()).thenReturn((mMockRes));
mMockDeviceStateManager = mock(DeviceStateManager.class);
when(mMockContext.getSystemService(DeviceStateManager.class))
.thenReturn(mMockDeviceStateManager);
Resources mockRes = mock(Resources.class);
when(mMockContext.getResources()).thenReturn((mockRes));
mockFold(mSupportFold, mSupportHalfFold);
mMockHandler = mock(Handler.class);
mTarget = new DeviceStateController(mMockContext, mMockHandler, mDelegate);
Handler mockHandler = mock(Handler.class);
mTarget = new DeviceStateController(mMockContext, mockHandler);
mTarget.registerDeviceStateCallback(mDelegate);
}
}
}

View File

@@ -705,7 +705,7 @@ public class DisplayRotationTests {
enableOrientationSensor();
mTarget.foldStateChanged(DeviceStateController.FoldState.OPEN);
mTarget.foldStateChanged(DeviceStateController.DeviceState.OPEN);
freezeRotation(Surface.ROTATION_270);
mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_0));
@@ -715,7 +715,7 @@ public class DisplayRotationTests {
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
// ... until half-fold
mTarget.foldStateChanged(DeviceStateController.FoldState.HALF_FOLDED);
mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED);
assertTrue(waitForUiHandler());
verify(sMockWm).updateRotation(false, false);
assertTrue(waitForUiHandler());
@@ -723,7 +723,7 @@ public class DisplayRotationTests {
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
// ... then transition back to flat
mTarget.foldStateChanged(DeviceStateController.FoldState.OPEN);
mTarget.foldStateChanged(DeviceStateController.DeviceState.OPEN);
assertTrue(waitForUiHandler());
verify(sMockWm, atLeast(1)).updateRotation(false, false);
assertTrue(waitForUiHandler());

View File

@@ -98,7 +98,7 @@ import androidx.test.filters.MediumTest;
import com.android.internal.policy.SystemBarUtils;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.DeviceStateController.FoldState;
import com.android.server.wm.DeviceStateController.DeviceState;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -3059,9 +3059,9 @@ public class SizeCompatTests extends WindowTestsBase {
private void setFoldablePosture(boolean isHalfFolded, boolean isTabletop) {
final DisplayRotation r = mActivity.mDisplayContent.getDisplayRotation();
doReturn(isHalfFolded).when(r).isDisplaySeparatingHinge();
doReturn(false).when(r).isDeviceInPosture(any(FoldState.class), anyBoolean());
doReturn(false).when(r).isDeviceInPosture(any(DeviceState.class), anyBoolean());
if (isHalfFolded) {
doReturn(true).when(r).isDeviceInPosture(FoldState.HALF_FOLDED, isTabletop);
doReturn(true).when(r).isDeviceInPosture(DeviceState.HALF_FOLDED, isTabletop);
}
mActivity.recomputeConfiguration();
}