Merge "Add TabletopModeController in WMShell" into tm-qpr-dev
This commit is contained in:
@@ -39,6 +39,9 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* Note that most of the implementation here inherits from
|
* Note that most of the implementation here inherits from
|
||||||
* {@link com.android.systemui.statusbar.policy.DevicePostureController}.
|
* {@link com.android.systemui.statusbar.policy.DevicePostureController}.
|
||||||
|
*
|
||||||
|
* Use the {@link TabletopModeController} if you are interested in tabletop mode change only,
|
||||||
|
* which is more common.
|
||||||
*/
|
*/
|
||||||
public class DevicePostureController {
|
public class DevicePostureController {
|
||||||
@IntDef(prefix = {"DEVICE_POSTURE_"}, value = {
|
@IntDef(prefix = {"DEVICE_POSTURE_"}, value = {
|
||||||
|
|||||||
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.wm.shell.common;
|
||||||
|
|
||||||
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
|
||||||
|
import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_HALF_OPENED;
|
||||||
|
import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_UNKNOWN;
|
||||||
|
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_FOLDABLE;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.app.WindowConfiguration;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
import android.view.Surface;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.internal.protolog.common.ProtoLog;
|
||||||
|
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||||
|
import com.android.wm.shell.sysui.ShellInit;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class to track the tabletop (aka. flex) mode change on Fold-ables.
|
||||||
|
* See also <a
|
||||||
|
* href="https://developer.android.com/guide/topics/large-screens/learn-about-foldables
|
||||||
|
* #foldable_postures">Foldable states and postures</a> for reference.
|
||||||
|
*
|
||||||
|
* Use the {@link DevicePostureController} for more detailed posture changes.
|
||||||
|
*/
|
||||||
|
public class TabletopModeController implements
|
||||||
|
DevicePostureController.OnDevicePostureChangedListener,
|
||||||
|
DisplayController.OnDisplaysChangedListener {
|
||||||
|
private static final long TABLETOP_MODE_DELAY_MILLIS = 1_000;
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
private final DevicePostureController mDevicePostureController;
|
||||||
|
|
||||||
|
private final DisplayController mDisplayController;
|
||||||
|
|
||||||
|
private final ShellExecutor mMainExecutor;
|
||||||
|
|
||||||
|
private final Set<Integer> mTabletopModeRotations = new ArraySet<>();
|
||||||
|
|
||||||
|
private final List<OnTabletopModeChangedListener> mListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
final Runnable mOnEnterTabletopModeCallback = () -> {
|
||||||
|
if (isInTabletopMode()) {
|
||||||
|
// We are still in tabletop mode, go ahead.
|
||||||
|
mayBroadcastOnTabletopModeChange(true /* isInTabletopMode */);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@DevicePostureController.DevicePostureInt
|
||||||
|
private int mDevicePosture = DEVICE_POSTURE_UNKNOWN;
|
||||||
|
|
||||||
|
@Surface.Rotation
|
||||||
|
private int mDisplayRotation = WindowConfiguration.ROTATION_UNDEFINED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track the last callback value for {@link OnTabletopModeChangedListener}.
|
||||||
|
* This is to avoid duplicated {@code false} callback to {@link #mListeners}.
|
||||||
|
*/
|
||||||
|
private Boolean mLastIsInTabletopModeForCallback;
|
||||||
|
|
||||||
|
public TabletopModeController(Context context,
|
||||||
|
ShellInit shellInit,
|
||||||
|
DevicePostureController postureController,
|
||||||
|
DisplayController displayController,
|
||||||
|
@ShellMainThread ShellExecutor mainExecutor) {
|
||||||
|
mContext = context;
|
||||||
|
mDevicePostureController = postureController;
|
||||||
|
mDisplayController = displayController;
|
||||||
|
mMainExecutor = mainExecutor;
|
||||||
|
shellInit.addInitCallback(this::onInit, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void onInit() {
|
||||||
|
mDevicePostureController.registerOnDevicePostureChangedListener(this);
|
||||||
|
mDisplayController.addDisplayWindowListener(this);
|
||||||
|
// Aligns with what's in {@link com.android.server.wm.DisplayRotation}.
|
||||||
|
final int[] deviceTabletopRotations = mContext.getResources().getIntArray(
|
||||||
|
com.android.internal.R.array.config_deviceTabletopRotations);
|
||||||
|
if (deviceTabletopRotations == null || deviceTabletopRotations.length == 0) {
|
||||||
|
ProtoLog.e(WM_SHELL_FOLDABLE,
|
||||||
|
"No valid config_deviceTabletopRotations, can not tell"
|
||||||
|
+ " tabletop mode in WMShell");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int angle : deviceTabletopRotations) {
|
||||||
|
switch (angle) {
|
||||||
|
case 0:
|
||||||
|
mTabletopModeRotations.add(Surface.ROTATION_0);
|
||||||
|
break;
|
||||||
|
case 90:
|
||||||
|
mTabletopModeRotations.add(Surface.ROTATION_90);
|
||||||
|
break;
|
||||||
|
case 180:
|
||||||
|
mTabletopModeRotations.add(Surface.ROTATION_180);
|
||||||
|
break;
|
||||||
|
case 270:
|
||||||
|
mTabletopModeRotations.add(Surface.ROTATION_270);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProtoLog.e(WM_SHELL_FOLDABLE,
|
||||||
|
"Invalid surface rotation angle in "
|
||||||
|
+ "config_deviceTabletopRotations: %d",
|
||||||
|
angle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Register {@link OnTabletopModeChangedListener} to listen for tabletop mode change. */
|
||||||
|
public void registerOnTabletopModeChangedListener(
|
||||||
|
@NonNull OnTabletopModeChangedListener listener) {
|
||||||
|
if (listener == null || mListeners.contains(listener)) return;
|
||||||
|
mListeners.add(listener);
|
||||||
|
listener.onTabletopModeChanged(isInTabletopMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unregister {@link OnTabletopModeChangedListener} for tabletop mode change. */
|
||||||
|
public void unregisterOnTabletopModeChangedListener(
|
||||||
|
@NonNull OnTabletopModeChangedListener listener) {
|
||||||
|
mListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDevicePostureChanged(@DevicePostureController.DevicePostureInt int posture) {
|
||||||
|
if (mDevicePosture != posture) {
|
||||||
|
onDevicePostureOrDisplayRotationChanged(posture, mDisplayRotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
|
||||||
|
final int newDisplayRotation = newConfig.windowConfiguration.getDisplayRotation();
|
||||||
|
if (displayId == DEFAULT_DISPLAY && newDisplayRotation != mDisplayRotation) {
|
||||||
|
onDevicePostureOrDisplayRotationChanged(mDevicePosture, newDisplayRotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDevicePostureOrDisplayRotationChanged(
|
||||||
|
@DevicePostureController.DevicePostureInt int newPosture,
|
||||||
|
@Surface.Rotation int newDisplayRotation) {
|
||||||
|
final boolean wasInTabletopMode = isInTabletopMode();
|
||||||
|
mDevicePosture = newPosture;
|
||||||
|
mDisplayRotation = newDisplayRotation;
|
||||||
|
final boolean couldBeInTabletopMode = isInTabletopMode();
|
||||||
|
mMainExecutor.removeCallbacks(mOnEnterTabletopModeCallback);
|
||||||
|
if (!wasInTabletopMode && couldBeInTabletopMode) {
|
||||||
|
// May enter tabletop mode, but we need to wait for additional time since this
|
||||||
|
// could be an intermediate state.
|
||||||
|
mMainExecutor.executeDelayed(mOnEnterTabletopModeCallback, TABLETOP_MODE_DELAY_MILLIS);
|
||||||
|
} else {
|
||||||
|
// Cancel entering tabletop mode if any condition's changed.
|
||||||
|
mayBroadcastOnTabletopModeChange(false /* isInTabletopMode */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isHalfOpened(@DevicePostureController.DevicePostureInt int posture) {
|
||||||
|
return posture == DEVICE_POSTURE_HALF_OPENED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInTabletopMode() {
|
||||||
|
return isHalfOpened(mDevicePosture) && mTabletopModeRotations.contains(mDisplayRotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mayBroadcastOnTabletopModeChange(boolean isInTabletopMode) {
|
||||||
|
if (mLastIsInTabletopModeForCallback == null
|
||||||
|
|| mLastIsInTabletopModeForCallback != isInTabletopMode) {
|
||||||
|
mListeners.forEach(l -> l.onTabletopModeChanged(isInTabletopMode));
|
||||||
|
mLastIsInTabletopModeForCallback = isInTabletopMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener interface for tabletop mode change.
|
||||||
|
*/
|
||||||
|
public interface OnTabletopModeChangedListener {
|
||||||
|
/**
|
||||||
|
* Callback when tabletop mode changes. Expect duplicated callbacks with {@code false}.
|
||||||
|
* @param isInTabletopMode {@code true} if enters tabletop mode, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
void onTabletopModeChanged(boolean isInTabletopMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,6 +51,7 @@ import com.android.wm.shell.common.FloatingContentCoordinator;
|
|||||||
import com.android.wm.shell.common.ShellExecutor;
|
import com.android.wm.shell.common.ShellExecutor;
|
||||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
import com.android.wm.shell.common.SyncTransactionQueue;
|
||||||
import com.android.wm.shell.common.SystemWindows;
|
import com.android.wm.shell.common.SystemWindows;
|
||||||
|
import com.android.wm.shell.common.TabletopModeController;
|
||||||
import com.android.wm.shell.common.TaskStackListenerImpl;
|
import com.android.wm.shell.common.TaskStackListenerImpl;
|
||||||
import com.android.wm.shell.common.TransactionPool;
|
import com.android.wm.shell.common.TransactionPool;
|
||||||
import com.android.wm.shell.common.annotations.ShellAnimationThread;
|
import com.android.wm.shell.common.annotations.ShellAnimationThread;
|
||||||
@@ -169,6 +170,18 @@ public abstract class WMShellBaseModule {
|
|||||||
return new DevicePostureController(context, shellInit, mainExecutor);
|
return new DevicePostureController(context, shellInit, mainExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WMSingleton
|
||||||
|
@Provides
|
||||||
|
static TabletopModeController provideTabletopModeController(
|
||||||
|
Context context,
|
||||||
|
ShellInit shellInit,
|
||||||
|
DevicePostureController postureController,
|
||||||
|
DisplayController displayController,
|
||||||
|
@ShellMainThread ShellExecutor mainExecutor) {
|
||||||
|
return new TabletopModeController(
|
||||||
|
context, shellInit, postureController, displayController, mainExecutor);
|
||||||
|
}
|
||||||
|
|
||||||
@WMSingleton
|
@WMSingleton
|
||||||
@Provides
|
@Provides
|
||||||
static DragAndDropController provideDragAndDropController(Context context,
|
static DragAndDropController provideDragAndDropController(Context context,
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ public enum ShellProtoLogGroup implements IProtoLogGroup {
|
|||||||
Consts.TAG_WM_SHELL),
|
Consts.TAG_WM_SHELL),
|
||||||
WM_SHELL_FLOATING_APPS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
|
WM_SHELL_FLOATING_APPS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
|
||||||
Consts.TAG_WM_SHELL),
|
Consts.TAG_WM_SHELL),
|
||||||
|
WM_SHELL_FOLDABLE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
|
||||||
|
Consts.TAG_WM_SHELL),
|
||||||
TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest");
|
TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest");
|
||||||
|
|
||||||
private final boolean mEnabled;
|
private final boolean mEnabled;
|
||||||
|
|||||||
@@ -0,0 +1,270 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.wm.shell.common;
|
||||||
|
|
||||||
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
|
||||||
|
import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_CLOSED;
|
||||||
|
import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_HALF_OPENED;
|
||||||
|
import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_OPENED;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.testing.AndroidTestingRunner;
|
||||||
|
import android.testing.TestableLooper;
|
||||||
|
import android.view.Surface;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.wm.shell.ShellTestCase;
|
||||||
|
import com.android.wm.shell.TestShellExecutor;
|
||||||
|
import com.android.wm.shell.sysui.ShellInit;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link TabletopModeController}.
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidTestingRunner.class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
@SmallTest
|
||||||
|
public class TabletopModeControllerTest extends ShellTestCase {
|
||||||
|
// It's considered tabletop mode if the display rotation angle matches what's in this array.
|
||||||
|
// It's defined as com.android.internal.R.array.config_deviceTabletopRotations on real devices.
|
||||||
|
private static final int[] TABLETOP_MODE_ROTATIONS = new int[] {
|
||||||
|
90 /* Surface.ROTATION_90 */,
|
||||||
|
270 /* Surface.ROTATION_270 */
|
||||||
|
};
|
||||||
|
|
||||||
|
private TestShellExecutor mMainExecutor;
|
||||||
|
|
||||||
|
private Configuration mConfiguration;
|
||||||
|
|
||||||
|
private TabletopModeController mPipTabletopController;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ShellInit mShellInit;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Resources mResources;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DevicePostureController mDevicePostureController;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DisplayController mDisplayController;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private TabletopModeController.OnTabletopModeChangedListener mOnTabletopModeChangedListener;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
when(mResources.getIntArray(com.android.internal.R.array.config_deviceTabletopRotations))
|
||||||
|
.thenReturn(TABLETOP_MODE_ROTATIONS);
|
||||||
|
when(mContext.getResources()).thenReturn(mResources);
|
||||||
|
mMainExecutor = new TestShellExecutor();
|
||||||
|
mConfiguration = new Configuration();
|
||||||
|
mPipTabletopController = new TabletopModeController(mContext, mShellInit,
|
||||||
|
mDevicePostureController, mDisplayController, mMainExecutor);
|
||||||
|
mPipTabletopController.onInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void instantiateController_addInitCallback() {
|
||||||
|
verify(mShellInit, times(1)).addInitCallback(any(), eq(mPipTabletopController));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registerOnTabletopModeChangedListener_notInTabletopMode_callbackFalse() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.registerOnTabletopModeChangedListener(
|
||||||
|
mOnTabletopModeChangedListener);
|
||||||
|
|
||||||
|
verify(mOnTabletopModeChangedListener, times(1))
|
||||||
|
.onTabletopModeChanged(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registerOnTabletopModeChangedListener_inTabletopMode_callbackTrue() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.registerOnTabletopModeChangedListener(
|
||||||
|
mOnTabletopModeChangedListener);
|
||||||
|
|
||||||
|
verify(mOnTabletopModeChangedListener, times(1))
|
||||||
|
.onTabletopModeChanged(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registerOnTabletopModeChangedListener_notInTabletopModeTwice_callbackOnce() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.registerOnTabletopModeChangedListener(
|
||||||
|
mOnTabletopModeChangedListener);
|
||||||
|
clearInvocations(mOnTabletopModeChangedListener);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
verifyZeroInteractions(mOnTabletopModeChangedListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test cases starting from folded state (DEVICE_POSTURE_CLOSED)
|
||||||
|
@Test
|
||||||
|
public void foldedRotation90_halfOpen_scheduleTabletopModeChange() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
|
||||||
|
assertTrue(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void foldedRotation0_halfOpen_noScheduleTabletopModeChange() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
|
||||||
|
assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void foldedRotation90_halfOpenThenUnfold_cancelTabletopModeChange() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
|
||||||
|
|
||||||
|
assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void foldedRotation90_halfOpenThenFold_cancelTabletopModeChange() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
|
||||||
|
|
||||||
|
assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void foldedRotation90_halfOpenThenRotate_cancelTabletopModeChange() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test cases starting from unfolded state (DEVICE_POSTURE_OPENED)
|
||||||
|
@Test
|
||||||
|
public void unfoldedRotation90_halfOpen_scheduleTabletopModeChange() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
|
||||||
|
assertTrue(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unfoldedRotation0_halfOpen_noScheduleTabletopModeChange() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
|
||||||
|
assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unfoldedRotation90_halfOpenThenUnfold_cancelTabletopModeChange() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
|
||||||
|
|
||||||
|
assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unfoldedRotation90_halfOpenThenFold_cancelTabletopModeChange() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
|
||||||
|
|
||||||
|
assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unfoldedRotation90_halfOpenThenRotate_cancelTabletopModeChange() {
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
|
||||||
|
mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
|
||||||
|
|
||||||
|
assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user