Fix wrong divider position after rotation
Ratating from 270 -> 0 -> 90 keeps wrong "mNonDecorInsets" in the DisplayLayout of split screen due to not updating insetsState when insetsChanged. Updates to stop house keeping DisplayLayout separately in split screen component by fetching it from DisplayController directly. Fix: 285854252 Test: atest WMShellUnitTests Test: manual by issue steps: 1) Launch apps to enter split-screen mode 2) Rotate to 270 3) Rotate to 0 4) Rotate to 90 5) Expect the position of split-tasks is right Merged-In: Ica32c817ef414f550931a50ec919e3114a075e2c Change-Id: Ica32c817ef414f550931a50ec919e3114a075e2c
This commit is contained in:
@@ -63,8 +63,10 @@ import com.android.internal.policy.DockedDividerUtils;
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.animation.Interpolators;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
import com.android.wm.shell.common.DisplayInsetsController;
|
||||
import com.android.wm.shell.common.DisplayLayout;
|
||||
import com.android.wm.shell.common.InteractionJankMonitorUtils;
|
||||
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
|
||||
|
||||
@@ -104,6 +106,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
private final Rect mWinBounds2 = new Rect();
|
||||
private final SplitLayoutHandler mSplitLayoutHandler;
|
||||
private final SplitWindowManager mSplitWindowManager;
|
||||
private final DisplayController mDisplayController;
|
||||
private final DisplayImeController mDisplayImeController;
|
||||
private final ImePositionProcessor mImePositionProcessor;
|
||||
private final ResizingEffectPolicy mSurfaceEffectPolicy;
|
||||
@@ -128,13 +131,14 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
public SplitLayout(String windowName, Context context, Configuration configuration,
|
||||
SplitLayoutHandler splitLayoutHandler,
|
||||
SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks,
|
||||
DisplayImeController displayImeController, ShellTaskOrganizer taskOrganizer,
|
||||
int parallaxType) {
|
||||
DisplayController displayController, DisplayImeController displayImeController,
|
||||
ShellTaskOrganizer taskOrganizer, int parallaxType) {
|
||||
mContext = context.createConfigurationContext(configuration);
|
||||
mOrientation = configuration.orientation;
|
||||
mRotation = configuration.windowConfiguration.getRotation();
|
||||
mDensity = configuration.densityDpi;
|
||||
mSplitLayoutHandler = splitLayoutHandler;
|
||||
mDisplayController = displayController;
|
||||
mDisplayImeController = displayImeController;
|
||||
mSplitWindowManager = new SplitWindowManager(windowName, mContext, configuration,
|
||||
parentContainerCallbacks);
|
||||
@@ -145,7 +149,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
updateDividerConfig(mContext);
|
||||
|
||||
mRootBounds.set(configuration.windowConfiguration.getBounds());
|
||||
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
|
||||
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
|
||||
resetDividerPosition();
|
||||
|
||||
mDimNonImeSide = mContext.getResources().getBoolean(R.bool.config_dimNonImeAttachedSide);
|
||||
@@ -314,7 +318,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
mRotation = rotation;
|
||||
mDensity = density;
|
||||
mUiMode = uiMode;
|
||||
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
|
||||
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
|
||||
updateDividerConfig(mContext);
|
||||
initDividerPosition(mTempRect);
|
||||
updateInvisibleRect();
|
||||
@@ -324,7 +328,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
|
||||
/** Rotate the layout to specific rotation and calculate new bounds. The stable insets value
|
||||
* should be calculated by display layout. */
|
||||
public void rotateTo(int newRotation, Rect stableInsets) {
|
||||
public void rotateTo(int newRotation) {
|
||||
final int rotationDelta = (newRotation - mRotation + 4) % 4;
|
||||
final boolean changeOrient = (rotationDelta % 2) != 0;
|
||||
|
||||
@@ -337,7 +341,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
// We only need new bounds here, other configuration should be update later.
|
||||
mTempRect.set(mRootBounds);
|
||||
mRootBounds.set(tmpRect);
|
||||
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, stableInsets);
|
||||
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
|
||||
initDividerPosition(mTempRect);
|
||||
}
|
||||
|
||||
@@ -548,10 +552,9 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
return mDividerSnapAlgorithm.calculateSnapTarget(position, velocity, hardDismiss);
|
||||
}
|
||||
|
||||
private DividerSnapAlgorithm getSnapAlgorithm(Context context, Rect rootBounds,
|
||||
@Nullable Rect stableInsets) {
|
||||
private DividerSnapAlgorithm getSnapAlgorithm(Context context, Rect rootBounds) {
|
||||
final boolean isLandscape = isLandscape(rootBounds);
|
||||
final Rect insets = stableInsets != null ? stableInsets : getDisplayInsets(context);
|
||||
final Rect insets = getDisplayStableInsets(context);
|
||||
|
||||
// Make split axis insets value same as the larger one to avoid bounds1 and bounds2
|
||||
// have difference for avoiding size-compat mode when switching unresizable apps in
|
||||
@@ -634,7 +637,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
public void splitSwitching(SurfaceControl.Transaction t, SurfaceControl leash1,
|
||||
SurfaceControl leash2, Consumer<Rect> finishCallback) {
|
||||
final boolean isLandscape = isLandscape();
|
||||
final Rect insets = getDisplayInsets(mContext);
|
||||
final Rect insets = getDisplayStableInsets(mContext);
|
||||
insets.set(isLandscape ? insets.left : 0, isLandscape ? 0 : insets.top,
|
||||
isLandscape ? insets.right : 0, isLandscape ? 0 : insets.bottom);
|
||||
|
||||
@@ -705,13 +708,17 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
return animator;
|
||||
}
|
||||
|
||||
private static Rect getDisplayInsets(Context context) {
|
||||
return context.getSystemService(WindowManager.class)
|
||||
.getMaximumWindowMetrics()
|
||||
.getWindowInsets()
|
||||
.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars()
|
||||
| WindowInsets.Type.displayCutout())
|
||||
.toRect();
|
||||
private Rect getDisplayStableInsets(Context context) {
|
||||
final DisplayLayout displayLayout =
|
||||
mDisplayController.getDisplayLayout(context.getDisplayId());
|
||||
return displayLayout != null
|
||||
? displayLayout.stableInsets()
|
||||
: context.getSystemService(WindowManager.class)
|
||||
.getMaximumWindowMetrics()
|
||||
.getWindowInsets()
|
||||
.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars()
|
||||
| WindowInsets.Type.displayCutout())
|
||||
.toRect();
|
||||
}
|
||||
|
||||
private static boolean isLandscape(Rect bounds) {
|
||||
@@ -784,7 +791,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
|
||||
private int getSmallestWidthDp(Rect bounds) {
|
||||
mTempRect.set(bounds);
|
||||
mTempRect.inset(getDisplayInsets(mContext));
|
||||
mTempRect.inset(getDisplayStableInsets(mContext));
|
||||
final int minWidth = Math.min(mTempRect.width(), mTempRect.height());
|
||||
final float density = mContext.getResources().getDisplayMetrics().density;
|
||||
return (int) (minWidth / density);
|
||||
|
||||
@@ -122,7 +122,6 @@ import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
import com.android.wm.shell.common.DisplayInsetsController;
|
||||
import com.android.wm.shell.common.DisplayLayout;
|
||||
import com.android.wm.shell.common.ScreenshotUtils;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
@@ -171,7 +170,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
private final StageListenerImpl mMainStageListener = new StageListenerImpl();
|
||||
private final SideStage mSideStage;
|
||||
private final StageListenerImpl mSideStageListener = new StageListenerImpl();
|
||||
private final DisplayLayout mDisplayLayout;
|
||||
@SplitPosition
|
||||
private int mSideStagePosition = SPLIT_POSITION_BOTTOM_OR_RIGHT;
|
||||
|
||||
@@ -311,7 +309,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
|
||||
this::onTransitionAnimationComplete, this);
|
||||
mDisplayController.addDisplayWindowListener(this);
|
||||
mDisplayLayout = new DisplayLayout(displayController.getDisplayLayout(displayId));
|
||||
transitions.addHandler(this);
|
||||
mSplitUnsupportedToast = Toast.makeText(mContext,
|
||||
R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
|
||||
@@ -345,7 +342,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
mMainExecutor = mainExecutor;
|
||||
mRecentTasks = recentTasks;
|
||||
mDisplayController.addDisplayWindowListener(this);
|
||||
mDisplayLayout = new DisplayLayout();
|
||||
transitions.addHandler(this);
|
||||
mSplitUnsupportedToast = Toast.makeText(mContext,
|
||||
R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
|
||||
@@ -1689,7 +1685,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
if (mSplitLayout == null) {
|
||||
mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
|
||||
mRootTaskInfo.configuration, this, mParentContainerCallbacks,
|
||||
mDisplayImeController, mTaskOrganizer,
|
||||
mDisplayController, mDisplayImeController, mTaskOrganizer,
|
||||
PARALLAX_ALIGN_CENTER /* parallaxType */);
|
||||
mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSplitLayout);
|
||||
}
|
||||
@@ -2153,8 +2149,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
if (displayId != DEFAULT_DISPLAY) {
|
||||
return;
|
||||
}
|
||||
mDisplayLayout.set(mDisplayController.getDisplayLayout(displayId));
|
||||
|
||||
if (mSplitLayout != null && mSplitLayout.isDensityChanged(newConfig.densityDpi)
|
||||
&& mMainStage.isActive()
|
||||
&& mSplitLayout.updateConfiguration(newConfig)
|
||||
@@ -2171,10 +2165,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
|
||||
private void onDisplayChange(int displayId, int fromRotation, int toRotation,
|
||||
@Nullable DisplayAreaInfo newDisplayAreaInfo, WindowContainerTransaction wct) {
|
||||
if (!mMainStage.isActive()) return;
|
||||
if (displayId != DEFAULT_DISPLAY || !mMainStage.isActive()) return;
|
||||
|
||||
mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
|
||||
mSplitLayout.rotateTo(toRotation, mDisplayLayout.stableInsets());
|
||||
mSplitLayout.rotateTo(toRotation);
|
||||
if (newDisplayAreaInfo != null) {
|
||||
mSplitLayout.updateConfiguration(newDisplayAreaInfo.configuration);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
@@ -41,6 +42,7 @@ import com.android.internal.policy.DividerSnapAlgorithm;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.ShellTestCase;
|
||||
import com.android.wm.shell.TestRunningTaskInfoBuilder;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -57,6 +59,7 @@ import org.mockito.MockitoAnnotations;
|
||||
public class SplitLayoutTests extends ShellTestCase {
|
||||
@Mock SplitLayout.SplitLayoutHandler mSplitLayoutHandler;
|
||||
@Mock SplitWindowManager.ParentContainerCallbacks mCallbacks;
|
||||
@Mock DisplayController mDisplayController;
|
||||
@Mock DisplayImeController mDisplayImeController;
|
||||
@Mock ShellTaskOrganizer mTaskOrganizer;
|
||||
@Mock WindowContainerTransaction mWct;
|
||||
@@ -72,6 +75,7 @@ public class SplitLayoutTests extends ShellTestCase {
|
||||
getConfiguration(),
|
||||
mSplitLayoutHandler,
|
||||
mCallbacks,
|
||||
mDisplayController,
|
||||
mDisplayImeController,
|
||||
mTaskOrganizer,
|
||||
SplitLayout.PARALLAX_NONE));
|
||||
@@ -100,6 +104,10 @@ public class SplitLayoutTests extends ShellTestCase {
|
||||
// Verify updateConfiguration returns true if the density changed.
|
||||
config.densityDpi = 123;
|
||||
assertThat(mSplitLayout.updateConfiguration(config)).isTrue();
|
||||
|
||||
// Verify updateConfiguration checks the current DisplayLayout
|
||||
verify(mDisplayController, times(5)) // init * 1 + updateConfiguration * 4
|
||||
.getDisplayLayout(anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -168,6 +176,14 @@ public class SplitLayoutTests extends ShellTestCase {
|
||||
verify(mWct).setSmallestScreenWidthDp(eq(task2.token), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoateTo_checksDisplayLayout() {
|
||||
mSplitLayout.rotateTo(90);
|
||||
|
||||
verify(mDisplayController, times(2)) // init * 1 + rotateTo * 1
|
||||
.getDisplayLayout(anyInt());
|
||||
}
|
||||
|
||||
private void waitDividerFlingFinished() {
|
||||
verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), anyInt(),
|
||||
mRunnableCaptor.capture());
|
||||
|
||||
Reference in New Issue
Block a user