Merge "Make DeviceStateController generic" into tm-qpr-dev
This commit is contained in:
@@ -652,6 +652,16 @@
|
|||||||
The default is false. -->
|
The default is false. -->
|
||||||
<bool name="config_lidControlsSleep">false</bool>
|
<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
|
<!-- The device states (supplied by DeviceStateManager) that should be treated as folded by the
|
||||||
display fold controller. Default is empty. -->
|
display fold controller. Default is empty. -->
|
||||||
<integer-array name="config_foldedDeviceStates">
|
<integer-array name="config_foldedDeviceStates">
|
||||||
@@ -672,6 +682,16 @@
|
|||||||
-->
|
-->
|
||||||
</integer-array>
|
</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
|
<!-- Indicates whether the window manager reacts to half-fold device states by overriding
|
||||||
rotation. -->
|
rotation. -->
|
||||||
<bool name="config_windowManagerHalfFoldAutoRotateOverride">false</bool>
|
<bool name="config_windowManagerHalfFoldAutoRotateOverride">false</bool>
|
||||||
|
|||||||
@@ -4014,8 +4014,10 @@
|
|||||||
<java-symbol type="integer" name="config_maxScanTasksForHomeVisibility" />
|
<java-symbol type="integer" name="config_maxScanTasksForHomeVisibility" />
|
||||||
|
|
||||||
<!-- For Foldables -->
|
<!-- For Foldables -->
|
||||||
|
<java-symbol type="array" name="config_openDeviceStates" />
|
||||||
<java-symbol type="array" name="config_foldedDeviceStates" />
|
<java-symbol type="array" name="config_foldedDeviceStates" />
|
||||||
<java-symbol type="array" name="config_halfFoldedDeviceStates" />
|
<java-symbol type="array" name="config_halfFoldedDeviceStates" />
|
||||||
|
<java-symbol type="array" name="config_rearDisplayDeviceStates" />
|
||||||
<java-symbol type="bool" name="config_windowManagerHalfFoldAutoRotateOverride" />
|
<java-symbol type="bool" name="config_windowManagerHalfFoldAutoRotateOverride" />
|
||||||
<java-symbol type="array" name="config_deviceStatesOnWhichToWakeUp" />
|
<java-symbol type="array" name="config_deviceStatesOnWhichToWakeUp" />
|
||||||
<java-symbol type="array" name="config_deviceStatesOnWhichToSleep" />
|
<java-symbol type="array" name="config_deviceStatesOnWhichToSleep" />
|
||||||
|
|||||||
@@ -16,80 +16,92 @@
|
|||||||
|
|
||||||
package com.android.server.wm;
|
package com.android.server.wm;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.hardware.devicestate.DeviceStateManager;
|
import android.hardware.devicestate.DeviceStateManager;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerExecutor;
|
import android.os.HandlerExecutor;
|
||||||
|
|
||||||
|
import com.android.internal.R;
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that registers callbacks with the {@link DeviceStateManager} and
|
* Class that registers callbacks with the {@link DeviceStateManager} and responds to device
|
||||||
* responds to fold state changes by forwarding such events to a delegate.
|
* changes.
|
||||||
*/
|
*/
|
||||||
final class DeviceStateController {
|
final class DeviceStateController implements DeviceStateManager.DeviceStateCallback {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private final DeviceStateManager mDeviceStateManager;
|
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 {
|
public enum DeviceState {
|
||||||
UNKNOWN, OPEN, FOLDED, HALF_FOLDED
|
UNKNOWN, OPEN, FOLDED, HALF_FOLDED, REAR,
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceStateController(Context context, Handler handler, Consumer<FoldState> delegate) {
|
DeviceStateController(@NonNull Context context, @NonNull Handler handler) {
|
||||||
mContext = context;
|
mDeviceStateManager = context.getSystemService(DeviceStateManager.class);
|
||||||
mDeviceStateManager = mContext.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) {
|
if (mDeviceStateManager != null) {
|
||||||
mDeviceStateListener = new FoldStateListener(mContext, delegate);
|
mDeviceStateManager.registerCallback(new HandlerExecutor(handler), this);
|
||||||
mDeviceStateManager
|
|
||||||
.registerCallback(new HandlerExecutor(handler),
|
|
||||||
mDeviceStateListener);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregisterFromDeviceStateManager() {
|
void unregisterFromDeviceStateManager() {
|
||||||
if (mDeviceStateListener != null) {
|
if (mDeviceStateManager != null) {
|
||||||
mDeviceStateManager.unregisterCallback(mDeviceStateListener);
|
mDeviceStateManager.unregisterCallback(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void registerDeviceStateCallback(@NonNull Consumer<DeviceState> callback) {
|
||||||
* A listener for half-fold device state events that dispatches state changes to a delegate.
|
mDeviceStateCallbacks.add(callback);
|
||||||
*/
|
|
||||||
static final class FoldStateListener implements DeviceStateManager.DeviceStateCallback {
|
|
||||||
|
|
||||||
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
|
@Override
|
||||||
public void onStateChanged(int state) {
|
public void onStateChanged(int state) {
|
||||||
final boolean halfFolded = ArrayUtils.contains(mHalfFoldedDeviceStates, state);
|
final DeviceState deviceState;
|
||||||
FoldState result;
|
if (ArrayUtils.contains(mHalfFoldedDeviceStates, state)) {
|
||||||
if (halfFolded) {
|
deviceState = DeviceState.HALF_FOLDED;
|
||||||
result = FoldState.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 {
|
} else {
|
||||||
final boolean folded = ArrayUtils.contains(mFoldedDeviceStates, state);
|
deviceState = DeviceState.UNKNOWN;
|
||||||
result = folded ? FoldState.FOLDED : FoldState.OPEN;
|
|
||||||
}
|
}
|
||||||
if (mLastResult == null || !mLastResult.equals(result)) {
|
|
||||||
mLastResult = result;
|
if (mLastDeviceState == null || !mLastDeviceState.equals(deviceState)) {
|
||||||
mDelegate.accept(result);
|
mLastDeviceState = deviceState;
|
||||||
|
|
||||||
|
for (Consumer<DeviceState> callback : mDeviceStateCallbacks) {
|
||||||
|
callback.accept(mLastDeviceState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1125,14 +1125,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
mWmService.mAtmService.getRecentTasks().getInputListener());
|
mWmService.mAtmService.getRecentTasks().getInputListener());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mDeviceStateController = new DeviceStateController(mWmService.mContext, mWmService.mH);
|
||||||
|
|
||||||
mDisplayPolicy = new DisplayPolicy(mWmService, this);
|
mDisplayPolicy = new DisplayPolicy(mWmService, this);
|
||||||
mDisplayRotation = new DisplayRotation(mWmService, this, mDisplayInfo.address);
|
mDisplayRotation = new DisplayRotation(mWmService, this, mDisplayInfo.address);
|
||||||
|
|
||||||
mDeviceStateController = new DeviceStateController(mWmService.mContext, mWmService.mH,
|
final Consumer<DeviceStateController.DeviceState> deviceStateConsumer =
|
||||||
newFoldState -> {
|
(@NonNull DeviceStateController.DeviceState newFoldState) -> {
|
||||||
mDisplaySwitchTransitionLauncher.foldStateChanged(newFoldState);
|
mDisplaySwitchTransitionLauncher.foldStateChanged(newFoldState);
|
||||||
mDisplayRotation.foldStateChanged(newFoldState);
|
mDisplayRotation.foldStateChanged(newFoldState);
|
||||||
});
|
};
|
||||||
|
mDeviceStateController.registerDeviceStateCallback(deviceStateConsumer);
|
||||||
|
|
||||||
mCloseToSquareMaxAspectRatio = mWmService.mContext.getResources().getFloat(
|
mCloseToSquareMaxAspectRatio = mWmService.mContext.getResources().getFloat(
|
||||||
R.dimen.config_closeToSquareDisplayMaxAspectRatio);
|
R.dimen.config_closeToSquareDisplayMaxAspectRatio);
|
||||||
|
|||||||
@@ -1573,7 +1573,7 @@ public class DisplayRotation {
|
|||||||
proto.end(token);
|
proto.end(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isDeviceInPosture(DeviceStateController.FoldState state, boolean isTabletop) {
|
boolean isDeviceInPosture(DeviceStateController.DeviceState state, boolean isTabletop) {
|
||||||
if (mFoldController == null) return false;
|
if (mFoldController == null) return false;
|
||||||
return mFoldController.isDeviceInPosture(state, isTabletop);
|
return mFoldController.isDeviceInPosture(state, isTabletop);
|
||||||
}
|
}
|
||||||
@@ -1585,10 +1585,10 @@ public class DisplayRotation {
|
|||||||
/**
|
/**
|
||||||
* Called by the DeviceStateManager callback when the device state changes.
|
* Called by the DeviceStateManager callback when the device state changes.
|
||||||
*/
|
*/
|
||||||
void foldStateChanged(DeviceStateController.FoldState foldState) {
|
void foldStateChanged(DeviceStateController.DeviceState deviceState) {
|
||||||
if (mFoldController != null) {
|
if (mFoldController != null) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
mFoldController.foldStateChanged(foldState);
|
mFoldController.foldStateChanged(deviceState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1596,8 +1596,8 @@ public class DisplayRotation {
|
|||||||
private class FoldController {
|
private class FoldController {
|
||||||
@Surface.Rotation
|
@Surface.Rotation
|
||||||
private int mHalfFoldSavedRotation = -1; // No saved rotation
|
private int mHalfFoldSavedRotation = -1; // No saved rotation
|
||||||
private DeviceStateController.FoldState mFoldState =
|
private DeviceStateController.DeviceState mDeviceState =
|
||||||
DeviceStateController.FoldState.UNKNOWN;
|
DeviceStateController.DeviceState.UNKNOWN;
|
||||||
private boolean mInHalfFoldTransition = false;
|
private boolean mInHalfFoldTransition = false;
|
||||||
private final boolean mIsDisplayAlwaysSeparatingHinge;
|
private final boolean mIsDisplayAlwaysSeparatingHinge;
|
||||||
private final Set<Integer> mTabletopRotations;
|
private final Set<Integer> mTabletopRotations;
|
||||||
@@ -1637,32 +1637,33 @@ public class DisplayRotation {
|
|||||||
R.bool.config_isDisplayHingeAlwaysSeparating);
|
R.bool.config_isDisplayHingeAlwaysSeparating);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isDeviceInPosture(DeviceStateController.FoldState state, boolean isTabletop) {
|
boolean isDeviceInPosture(DeviceStateController.DeviceState state, boolean isTabletop) {
|
||||||
if (state != mFoldState) {
|
if (state != mDeviceState) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (mFoldState == DeviceStateController.FoldState.HALF_FOLDED) {
|
if (mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) {
|
||||||
return !(isTabletop ^ mTabletopRotations.contains(mRotation));
|
return !(isTabletop ^ mTabletopRotations.contains(mRotation));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceStateController.FoldState getFoldState() {
|
DeviceStateController.DeviceState getFoldState() {
|
||||||
return mFoldState;
|
return mDeviceState;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isSeparatingHinge() {
|
boolean isSeparatingHinge() {
|
||||||
return mFoldState == DeviceStateController.FoldState.HALF_FOLDED
|
return mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED
|
||||||
|| (mFoldState == DeviceStateController.FoldState.OPEN
|
|| (mDeviceState == DeviceStateController.DeviceState.OPEN
|
||||||
&& mIsDisplayAlwaysSeparatingHinge);
|
&& mIsDisplayAlwaysSeparatingHinge);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean overrideFrozenRotation() {
|
boolean overrideFrozenRotation() {
|
||||||
return mFoldState == DeviceStateController.FoldState.HALF_FOLDED;
|
return mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean shouldRevertOverriddenRotation() {
|
boolean shouldRevertOverriddenRotation() {
|
||||||
return mFoldState == DeviceStateController.FoldState.OPEN // When transitioning to open.
|
// When transitioning to open.
|
||||||
|
return mDeviceState == DeviceStateController.DeviceState.OPEN
|
||||||
&& mInHalfFoldTransition
|
&& mInHalfFoldTransition
|
||||||
&& mHalfFoldSavedRotation != -1 // Ignore if we've already reverted.
|
&& mHalfFoldSavedRotation != -1 // Ignore if we've already reverted.
|
||||||
&& mUserRotationMode
|
&& mUserRotationMode
|
||||||
@@ -1676,30 +1677,30 @@ public class DisplayRotation {
|
|||||||
return savedRotation;
|
return savedRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void foldStateChanged(DeviceStateController.FoldState newState) {
|
void foldStateChanged(DeviceStateController.DeviceState newState) {
|
||||||
ProtoLog.v(WM_DEBUG_ORIENTATION,
|
ProtoLog.v(WM_DEBUG_ORIENTATION,
|
||||||
"foldStateChanged: displayId %d, halfFoldStateChanged %s, "
|
"foldStateChanged: displayId %d, halfFoldStateChanged %s, "
|
||||||
+ "saved rotation: %d, mUserRotation: %d, mLastSensorRotation: %d, "
|
+ "saved rotation: %d, mUserRotation: %d, mLastSensorRotation: %d, "
|
||||||
+ "mLastOrientation: %d, mRotation: %d",
|
+ "mLastOrientation: %d, mRotation: %d",
|
||||||
mDisplayContent.getDisplayId(), newState.name(), mHalfFoldSavedRotation,
|
mDisplayContent.getDisplayId(), newState.name(), mHalfFoldSavedRotation,
|
||||||
mUserRotation, mLastSensorRotation, mLastOrientation, mRotation);
|
mUserRotation, mLastSensorRotation, mLastOrientation, mRotation);
|
||||||
if (mFoldState == DeviceStateController.FoldState.UNKNOWN) {
|
if (mDeviceState == DeviceStateController.DeviceState.UNKNOWN) {
|
||||||
mFoldState = newState;
|
mDeviceState = newState;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (newState == DeviceStateController.FoldState.HALF_FOLDED
|
if (newState == DeviceStateController.DeviceState.HALF_FOLDED
|
||||||
&& mFoldState != DeviceStateController.FoldState.HALF_FOLDED) {
|
&& mDeviceState != DeviceStateController.DeviceState.HALF_FOLDED) {
|
||||||
// The device has transitioned to HALF_FOLDED state: save the current rotation and
|
// The device has transitioned to HALF_FOLDED state: save the current rotation and
|
||||||
// update the device rotation.
|
// update the device rotation.
|
||||||
mHalfFoldSavedRotation = mRotation;
|
mHalfFoldSavedRotation = mRotation;
|
||||||
mFoldState = newState;
|
mDeviceState = newState;
|
||||||
// Now mFoldState is set to HALF_FOLDED, the overrideFrozenRotation function will
|
// Now mFoldState is set to HALF_FOLDED, the overrideFrozenRotation function will
|
||||||
// return true, so rotation is unlocked.
|
// return true, so rotation is unlocked.
|
||||||
mService.updateRotation(false /* alwaysSendConfiguration */,
|
mService.updateRotation(false /* alwaysSendConfiguration */,
|
||||||
false /* forceRelayout */);
|
false /* forceRelayout */);
|
||||||
} else {
|
} else {
|
||||||
mInHalfFoldTransition = true;
|
mInHalfFoldTransition = true;
|
||||||
mFoldState = newState;
|
mDeviceState = newState;
|
||||||
// Tell the device to update its orientation.
|
// Tell the device to update its orientation.
|
||||||
mService.updateRotation(false /* alwaysSendConfiguration */,
|
mService.updateRotation(false /* alwaysSendConfiguration */,
|
||||||
false /* forceRelayout */);
|
false /* forceRelayout */);
|
||||||
@@ -1822,7 +1823,7 @@ public class DisplayRotation {
|
|||||||
final long mTimestamp = System.currentTimeMillis();
|
final long mTimestamp = System.currentTimeMillis();
|
||||||
final int mHalfFoldSavedRotation;
|
final int mHalfFoldSavedRotation;
|
||||||
final boolean mInHalfFoldTransition;
|
final boolean mInHalfFoldTransition;
|
||||||
final DeviceStateController.FoldState mFoldState;
|
final DeviceStateController.DeviceState mDeviceState;
|
||||||
@Nullable final String mDisplayRotationCompatPolicySummary;
|
@Nullable final String mDisplayRotationCompatPolicySummary;
|
||||||
|
|
||||||
Record(DisplayRotation dr, int fromRotation, int toRotation) {
|
Record(DisplayRotation dr, int fromRotation, int toRotation) {
|
||||||
@@ -1852,11 +1853,11 @@ public class DisplayRotation {
|
|||||||
if (dr.mFoldController != null) {
|
if (dr.mFoldController != null) {
|
||||||
mHalfFoldSavedRotation = dr.mFoldController.mHalfFoldSavedRotation;
|
mHalfFoldSavedRotation = dr.mFoldController.mHalfFoldSavedRotation;
|
||||||
mInHalfFoldTransition = dr.mFoldController.mInHalfFoldTransition;
|
mInHalfFoldTransition = dr.mFoldController.mInHalfFoldTransition;
|
||||||
mFoldState = dr.mFoldController.mFoldState;
|
mDeviceState = dr.mFoldController.mDeviceState;
|
||||||
} else {
|
} else {
|
||||||
mHalfFoldSavedRotation = NO_FOLD_CONTROLLER;
|
mHalfFoldSavedRotation = NO_FOLD_CONTROLLER;
|
||||||
mInHalfFoldTransition = false;
|
mInHalfFoldTransition = false;
|
||||||
mFoldState = DeviceStateController.FoldState.UNKNOWN;
|
mDeviceState = DeviceStateController.DeviceState.UNKNOWN;
|
||||||
}
|
}
|
||||||
mDisplayRotationCompatPolicySummary = dc.mDisplayRotationCompatPolicy == null
|
mDisplayRotationCompatPolicySummary = dc.mDisplayRotationCompatPolicy == null
|
||||||
? null
|
? null
|
||||||
@@ -1882,7 +1883,7 @@ public class DisplayRotation {
|
|||||||
pw.println(prefix + " halfFoldSavedRotation="
|
pw.println(prefix + " halfFoldSavedRotation="
|
||||||
+ mHalfFoldSavedRotation
|
+ mHalfFoldSavedRotation
|
||||||
+ " mInHalfFoldTransition=" + mInHalfFoldTransition
|
+ " mInHalfFoldTransition=" + mInHalfFoldTransition
|
||||||
+ " mFoldState=" + mFoldState);
|
+ " mFoldState=" + mDeviceState);
|
||||||
}
|
}
|
||||||
if (mDisplayRotationCompatPolicySummary != null) {
|
if (mDisplayRotationCompatPolicySummary != null) {
|
||||||
pw.println(prefix + mDisplayRotationCompatPolicySummary);
|
pw.println(prefix + mDisplayRotationCompatPolicySummary);
|
||||||
|
|||||||
@@ -542,7 +542,7 @@ final class LetterboxUiController {
|
|||||||
// Note that we check the task rather than the parent as with ActivityEmbedding the parent might
|
// 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
|
// be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is
|
||||||
// actually fullscreen.
|
// actually fullscreen.
|
||||||
private boolean isDisplayFullScreenAndInPosture(DeviceStateController.FoldState state,
|
private boolean isDisplayFullScreenAndInPosture(DeviceStateController.DeviceState state,
|
||||||
boolean isTabletop) {
|
boolean isTabletop) {
|
||||||
Task task = mActivityRecord.getTask();
|
Task task = mActivityRecord.getTask();
|
||||||
return mActivityRecord.mDisplayContent != null
|
return mActivityRecord.mDisplayContent != null
|
||||||
@@ -568,7 +568,7 @@ final class LetterboxUiController {
|
|||||||
// Don't check resolved configuration because it may not be updated yet during
|
// Don't check resolved configuration because it may not be updated yet during
|
||||||
// configuration change.
|
// configuration change.
|
||||||
boolean bookMode = isDisplayFullScreenAndInPosture(
|
boolean bookMode = isDisplayFullScreenAndInPosture(
|
||||||
DeviceStateController.FoldState.HALF_FOLDED, false /* isTabletop */);
|
DeviceStateController.DeviceState.HALF_FOLDED, false /* isTabletop */);
|
||||||
return isHorizontalReachabilityEnabled(parentConfiguration)
|
return isHorizontalReachabilityEnabled(parentConfiguration)
|
||||||
// Using the last global dynamic position to avoid "jumps" when moving
|
// Using the last global dynamic position to avoid "jumps" when moving
|
||||||
// between apps or activities.
|
// between apps or activities.
|
||||||
@@ -580,7 +580,7 @@ final class LetterboxUiController {
|
|||||||
// Don't check resolved configuration because it may not be updated yet during
|
// Don't check resolved configuration because it may not be updated yet during
|
||||||
// configuration change.
|
// configuration change.
|
||||||
boolean tabletopMode = isDisplayFullScreenAndInPosture(
|
boolean tabletopMode = isDisplayFullScreenAndInPosture(
|
||||||
DeviceStateController.FoldState.HALF_FOLDED, true /* isTabletop */);
|
DeviceStateController.DeviceState.HALF_FOLDED, true /* isTabletop */);
|
||||||
return isVerticalReachabilityEnabled(parentConfiguration)
|
return isVerticalReachabilityEnabled(parentConfiguration)
|
||||||
// Using the last global dynamic position to avoid "jumps" when moving
|
// Using the last global dynamic position to avoid "jumps" when moving
|
||||||
// between apps or activities.
|
// between apps or activities.
|
||||||
@@ -1107,7 +1107,7 @@ final class LetterboxUiController {
|
|||||||
int letterboxPositionForHorizontalReachability = getLetterboxConfiguration()
|
int letterboxPositionForHorizontalReachability = getLetterboxConfiguration()
|
||||||
.getLetterboxPositionForHorizontalReachability(
|
.getLetterboxPositionForHorizontalReachability(
|
||||||
isDisplayFullScreenAndInPosture(
|
isDisplayFullScreenAndInPosture(
|
||||||
DeviceStateController.FoldState.HALF_FOLDED,
|
DeviceStateController.DeviceState.HALF_FOLDED,
|
||||||
false /* isTabletop */));
|
false /* isTabletop */));
|
||||||
positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPosition(
|
positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPosition(
|
||||||
letterboxPositionForHorizontalReachability);
|
letterboxPositionForHorizontalReachability);
|
||||||
@@ -1115,7 +1115,7 @@ final class LetterboxUiController {
|
|||||||
int letterboxPositionForVerticalReachability = getLetterboxConfiguration()
|
int letterboxPositionForVerticalReachability = getLetterboxConfiguration()
|
||||||
.getLetterboxPositionForVerticalReachability(
|
.getLetterboxPositionForVerticalReachability(
|
||||||
isDisplayFullScreenAndInPosture(
|
isDisplayFullScreenAndInPosture(
|
||||||
DeviceStateController.FoldState.HALF_FOLDED,
|
DeviceStateController.DeviceState.HALF_FOLDED,
|
||||||
true /* isTabletop */));
|
true /* isTabletop */));
|
||||||
positionToLog = letterboxVerticalReachabilityPositionToLetterboxPosition(
|
positionToLog = letterboxVerticalReachabilityPositionToLetterboxPosition(
|
||||||
letterboxPositionForVerticalReachability);
|
letterboxPositionForVerticalReachability);
|
||||||
|
|||||||
@@ -51,10 +51,10 @@ public class PhysicalDisplaySwitchTransitionLauncher {
|
|||||||
/**
|
/**
|
||||||
* Called by the DeviceStateManager callback when the state changes.
|
* 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.
|
// Ignore transitions to/from half-folded.
|
||||||
if (newFoldState == DeviceStateController.FoldState.HALF_FOLDED) return;
|
if (newDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) return;
|
||||||
mIsFolded = newFoldState == DeviceStateController.FoldState.FOLDED;
|
mIsFolded = newDeviceState == DeviceStateController.DeviceState.FOLDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,13 +16,12 @@
|
|||||||
|
|
||||||
package com.android.server.wm;
|
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.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.verify;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
@@ -32,9 +31,10 @@ import android.platform.test.annotations.Presubmit;
|
|||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.internal.R;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@@ -48,92 +48,76 @@ import java.util.function.Consumer;
|
|||||||
@Presubmit
|
@Presubmit
|
||||||
public class DeviceStateControllerTests {
|
public class DeviceStateControllerTests {
|
||||||
|
|
||||||
private DeviceStateController.FoldStateListener mFoldStateListener;
|
|
||||||
private DeviceStateController mTarget;
|
private DeviceStateController mTarget;
|
||||||
private DeviceStateControllerBuilder mBuilder;
|
private DeviceStateControllerBuilder mBuilder;
|
||||||
|
|
||||||
private Context mMockContext;
|
private Context mMockContext;
|
||||||
private Handler mMockHandler;
|
|
||||||
private Resources mMockRes;
|
|
||||||
private DeviceStateManager mMockDeviceStateManager;
|
private DeviceStateManager mMockDeviceStateManager;
|
||||||
|
private DeviceStateController.DeviceState mCurrentState =
|
||||||
private Consumer<DeviceStateController.FoldState> mDelegate;
|
DeviceStateController.DeviceState.UNKNOWN;
|
||||||
private DeviceStateController.FoldState mCurrentState = DeviceStateController.FoldState.UNKNOWN;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mBuilder = new DeviceStateControllerBuilder();
|
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);
|
mBuilder.setSupportFold(supportFold, supportHalfFold);
|
||||||
mDelegate = (newFoldState) -> {
|
Consumer<DeviceStateController.DeviceState> delegate = (newFoldState) -> {
|
||||||
mCurrentState = newFoldState;
|
mCurrentState = newFoldState;
|
||||||
};
|
};
|
||||||
mBuilder.setDelegate(mDelegate);
|
mBuilder.setDelegate(delegate);
|
||||||
mBuilder.build();
|
mBuilder.build();
|
||||||
verifyFoldStateListenerRegistration(1);
|
verify(mMockDeviceStateManager).registerCallback(any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInitialization() throws Exception {
|
public void testInitialization() {
|
||||||
initialize(true /* supportFold */, true /* supportHalfFolded */);
|
initialize(true /* supportFold */, true /* supportHalfFolded */);
|
||||||
mFoldStateListener.onStateChanged(mUnfoldedStates[0]);
|
mTarget.onStateChanged(mOpenDeviceStates[0]);
|
||||||
assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
|
assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInitializationWithNoFoldSupport() throws Exception {
|
public void testInitializationWithNoFoldSupport() {
|
||||||
initialize(false /* supportFold */, false /* supportHalfFolded */);
|
initialize(false /* supportFold */, false /* supportHalfFolded */);
|
||||||
mFoldStateListener.onStateChanged(mFoldedStates[0]);
|
mTarget.onStateChanged(mFoldedStates[0]);
|
||||||
// Note that the folded state is ignored.
|
// Note that the folded state is ignored.
|
||||||
assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
|
assertEquals(DeviceStateController.DeviceState.UNKNOWN, mCurrentState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithFoldSupported() throws Exception {
|
public void testWithFoldSupported() {
|
||||||
initialize(true /* supportFold */, false /* supportHalfFolded */);
|
initialize(true /* supportFold */, false /* supportHalfFolded */);
|
||||||
mFoldStateListener.onStateChanged(mUnfoldedStates[0]);
|
mTarget.onStateChanged(mOpenDeviceStates[0]);
|
||||||
assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
|
assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
|
||||||
mFoldStateListener.onStateChanged(mFoldedStates[0]);
|
mTarget.onStateChanged(mFoldedStates[0]);
|
||||||
assertEquals(mCurrentState, DeviceStateController.FoldState.FOLDED);
|
assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
|
||||||
mFoldStateListener.onStateChanged(mHalfFoldedStates[0]);
|
mTarget.onStateChanged(mHalfFoldedStates[0]);
|
||||||
assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN); // Ignored
|
assertEquals(DeviceStateController.DeviceState.UNKNOWN, mCurrentState); // Ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithHalfFoldSupported() throws Exception {
|
public void testWithHalfFoldSupported() {
|
||||||
initialize(true /* supportFold */, true /* supportHalfFolded */);
|
initialize(true /* supportFold */, true /* supportHalfFolded */);
|
||||||
mFoldStateListener.onStateChanged(mUnfoldedStates[0]);
|
mTarget.onStateChanged(mOpenDeviceStates[0]);
|
||||||
assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
|
assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
|
||||||
mFoldStateListener.onStateChanged(mFoldedStates[0]);
|
mTarget.onStateChanged(mFoldedStates[0]);
|
||||||
assertEquals(mCurrentState, DeviceStateController.FoldState.FOLDED);
|
assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
|
||||||
mFoldStateListener.onStateChanged(mHalfFoldedStates[0]);
|
mTarget.onStateChanged(mHalfFoldedStates[0]);
|
||||||
assertEquals(mCurrentState, DeviceStateController.FoldState.HALF_FOLDED);
|
assertEquals(DeviceStateController.DeviceState.HALF_FOLDED, mCurrentState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private final int[] mFoldedStates = {0};
|
private final int[] mFoldedStates = {0};
|
||||||
private final int[] mUnfoldedStates = {1};
|
private final int[] mOpenDeviceStates = {1};
|
||||||
private final int[] mHalfFoldedStates = {2};
|
private final int[] mHalfFoldedStates = {2};
|
||||||
|
private final int[] mRearDisplayStates = {3};
|
||||||
|
|
||||||
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 class DeviceStateControllerBuilder {
|
private class DeviceStateControllerBuilder {
|
||||||
private boolean mSupportFold = false;
|
private boolean mSupportFold = false;
|
||||||
private boolean mSupportHalfFold = false;
|
private boolean mSupportHalfFold = false;
|
||||||
private Consumer<DeviceStateController.FoldState> mDelegate;
|
private Consumer<DeviceStateController.DeviceState> mDelegate;
|
||||||
|
|
||||||
DeviceStateControllerBuilder setSupportFold(
|
DeviceStateControllerBuilder setSupportFold(
|
||||||
boolean supportFold, boolean supportHalfFold) {
|
boolean supportFold, boolean supportHalfFold) {
|
||||||
@@ -143,34 +127,44 @@ public class DeviceStateControllerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DeviceStateControllerBuilder setDelegate(
|
DeviceStateControllerBuilder setDelegate(
|
||||||
Consumer<DeviceStateController.FoldState> delegate) {
|
Consumer<DeviceStateController.DeviceState> delegate) {
|
||||||
mDelegate = delegate;
|
mDelegate = delegate;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mockFold(boolean enableFold, boolean enableHalfFold) {
|
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) {
|
if (enableFold) {
|
||||||
when(mMockContext.getResources().getIntArray(
|
when(mMockContext.getResources()
|
||||||
com.android.internal.R.array.config_foldedDeviceStates))
|
.getIntArray(R.array.config_foldedDeviceStates))
|
||||||
.thenReturn(mFoldedStates);
|
.thenReturn(mFoldedStates);
|
||||||
}
|
}
|
||||||
if (enableHalfFold) {
|
if (enableHalfFold) {
|
||||||
when(mMockContext.getResources().getIntArray(
|
when(mMockContext.getResources()
|
||||||
com.android.internal.R.array.config_halfFoldedDeviceStates))
|
.getIntArray(R.array.config_halfFoldedDeviceStates))
|
||||||
.thenReturn(mHalfFoldedStates);
|
.thenReturn(mHalfFoldedStates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void build() throws Exception {
|
private void build() {
|
||||||
mMockContext = mock(Context.class);
|
mMockContext = mock(Context.class);
|
||||||
mMockRes = mock(Resources.class);
|
|
||||||
when(mMockContext.getResources()).thenReturn((mMockRes));
|
|
||||||
mMockDeviceStateManager = mock(DeviceStateManager.class);
|
mMockDeviceStateManager = mock(DeviceStateManager.class);
|
||||||
when(mMockContext.getSystemService(DeviceStateManager.class))
|
when(mMockContext.getSystemService(DeviceStateManager.class))
|
||||||
.thenReturn(mMockDeviceStateManager);
|
.thenReturn(mMockDeviceStateManager);
|
||||||
|
Resources mockRes = mock(Resources.class);
|
||||||
|
when(mMockContext.getResources()).thenReturn((mockRes));
|
||||||
mockFold(mSupportFold, mSupportHalfFold);
|
mockFold(mSupportFold, mSupportHalfFold);
|
||||||
mMockHandler = mock(Handler.class);
|
Handler mockHandler = mock(Handler.class);
|
||||||
mTarget = new DeviceStateController(mMockContext, mMockHandler, mDelegate);
|
mTarget = new DeviceStateController(mMockContext, mockHandler);
|
||||||
|
mTarget.registerDeviceStateCallback(mDelegate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -705,7 +705,7 @@ public class DisplayRotationTests {
|
|||||||
|
|
||||||
enableOrientationSensor();
|
enableOrientationSensor();
|
||||||
|
|
||||||
mTarget.foldStateChanged(DeviceStateController.FoldState.OPEN);
|
mTarget.foldStateChanged(DeviceStateController.DeviceState.OPEN);
|
||||||
freezeRotation(Surface.ROTATION_270);
|
freezeRotation(Surface.ROTATION_270);
|
||||||
|
|
||||||
mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_0));
|
mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_0));
|
||||||
@@ -715,7 +715,7 @@ public class DisplayRotationTests {
|
|||||||
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
|
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
|
||||||
|
|
||||||
// ... until half-fold
|
// ... until half-fold
|
||||||
mTarget.foldStateChanged(DeviceStateController.FoldState.HALF_FOLDED);
|
mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED);
|
||||||
assertTrue(waitForUiHandler());
|
assertTrue(waitForUiHandler());
|
||||||
verify(sMockWm).updateRotation(false, false);
|
verify(sMockWm).updateRotation(false, false);
|
||||||
assertTrue(waitForUiHandler());
|
assertTrue(waitForUiHandler());
|
||||||
@@ -723,7 +723,7 @@ public class DisplayRotationTests {
|
|||||||
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
|
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
|
||||||
|
|
||||||
// ... then transition back to flat
|
// ... then transition back to flat
|
||||||
mTarget.foldStateChanged(DeviceStateController.FoldState.OPEN);
|
mTarget.foldStateChanged(DeviceStateController.DeviceState.OPEN);
|
||||||
assertTrue(waitForUiHandler());
|
assertTrue(waitForUiHandler());
|
||||||
verify(sMockWm, atLeast(1)).updateRotation(false, false);
|
verify(sMockWm, atLeast(1)).updateRotation(false, false);
|
||||||
assertTrue(waitForUiHandler());
|
assertTrue(waitForUiHandler());
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ import androidx.test.filters.MediumTest;
|
|||||||
import com.android.internal.policy.SystemBarUtils;
|
import com.android.internal.policy.SystemBarUtils;
|
||||||
import com.android.internal.statusbar.LetterboxDetails;
|
import com.android.internal.statusbar.LetterboxDetails;
|
||||||
import com.android.server.statusbar.StatusBarManagerInternal;
|
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.DisableCompatChanges;
|
||||||
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
|
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
|
||||||
@@ -3186,9 +3186,9 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
private void setFoldablePosture(boolean isHalfFolded, boolean isTabletop) {
|
private void setFoldablePosture(boolean isHalfFolded, boolean isTabletop) {
|
||||||
final DisplayRotation r = mActivity.mDisplayContent.getDisplayRotation();
|
final DisplayRotation r = mActivity.mDisplayContent.getDisplayRotation();
|
||||||
doReturn(isHalfFolded).when(r).isDisplaySeparatingHinge();
|
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) {
|
if (isHalfFolded) {
|
||||||
doReturn(true).when(r).isDeviceInPosture(FoldState.HALF_FOLDED, isTabletop);
|
doReturn(true).when(r).isDeviceInPosture(DeviceState.HALF_FOLDED, isTabletop);
|
||||||
}
|
}
|
||||||
mActivity.recomputeConfiguration();
|
mActivity.recomputeConfiguration();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user