Merge "Fix divider disappear when rotation on shell transition" into tm-dev

This commit is contained in:
Tony Huang
2022-03-15 07:25:57 +00:00
committed by Android (Google) Code Review
5 changed files with 69 additions and 18 deletions

View File

@@ -218,9 +218,13 @@ public class WindowlessWindowManager implements IWindowSession {
throw new IllegalArgumentException(
"Invalid window token (never added or removed already)");
}
removeSurface(state.mSurfaceControl);
}
/** Separate from {@link #remove} so that subclasses can put removal on a sync transaction. */
protected void removeSurface(SurfaceControl sc) {
try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
t.remove(state.mSurfaceControl).apply();
t.remove(sc).apply();
}
}

View File

@@ -98,6 +98,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
private WindowContainerToken mWinToken2;
private int mDividePosition;
private boolean mInitialized = false;
private boolean mFreezeDividerWindow = false;
private int mOrientation;
private int mRotation;
@@ -225,11 +226,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
initDividerPosition(mTempRect);
if (mInitialized) {
release();
init();
}
return true;
}
@@ -298,20 +294,37 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
}
/** Releases the surface holding the current {@link DividerView}. */
public void release() {
public void release(SurfaceControl.Transaction t) {
if (!mInitialized) return;
mInitialized = false;
mSplitWindowManager.release();
mSplitWindowManager.release(t);
mDisplayImeController.removePositionProcessor(mImePositionProcessor);
mImePositionProcessor.reset();
}
public void release() {
release(null /* t */);
}
/** Releases and re-inflates {@link DividerView} on the root surface. */
public void update(SurfaceControl.Transaction t) {
if (!mInitialized) return;
mSplitWindowManager.release(t);
mImePositionProcessor.reset();
mSplitWindowManager.init(this, mInsetsState);
}
@Override
public void insetsChanged(InsetsState insetsState) {
mInsetsState.set(insetsState);
if (!mInitialized) {
return;
}
if (mFreezeDividerWindow) {
// DO NOT change its layout before transition actually run because it might cause
// flicker.
return;
}
mSplitWindowManager.onInsetsChanged(insetsState);
}
@@ -323,6 +336,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
}
}
public void setFreezeDividerWindow(boolean freezeDividerWindow) {
mFreezeDividerWindow = freezeDividerWindow;
}
/**
* Updates bounds with the passing position. Usually used to update recording bounds while
* performing animation or dragging divider bar to resize the splits.

View File

@@ -58,6 +58,9 @@ public final class SplitWindowManager extends WindowlessWindowManager {
private SurfaceControl mLeash;
private DividerView mDividerView;
// Used to "pass" a transaction to WWM.remove so that view removal can be synchronized.
private SurfaceControl.Transaction mSyncTransaction = null;
public interface ParentContainerCallbacks {
void attachToParentSurface(SurfaceControl.Builder b);
void onLeashReady(SurfaceControl leash);
@@ -130,22 +133,38 @@ public final class SplitWindowManager extends WindowlessWindowManager {
* Releases the surface control of the current {@link DividerView} and tear down the view
* hierarchy.
*/
void release() {
void release(@Nullable SurfaceControl.Transaction t) {
if (mDividerView != null) {
mDividerView = null;
}
if (mViewHost != null){
mSyncTransaction = t;
mViewHost.release();
mSyncTransaction = null;
mViewHost = null;
}
if (mLeash != null) {
new SurfaceControl.Transaction().remove(mLeash).apply();
if (t == null) {
new SurfaceControl.Transaction().remove(mLeash).apply();
} else {
t.remove(mLeash);
}
mLeash = null;
}
}
@Override
protected void removeSurface(SurfaceControl sc) {
// This gets called via SurfaceControlViewHost.release()
if (mSyncTransaction != null) {
mSyncTransaction.remove(sc);
} else {
super.removeSurface(sc);
}
}
void setInteractive(boolean interactive) {
if (mDividerView == null) return;
mDividerView.setInteractive(interactive);

View File

@@ -29,6 +29,7 @@ import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -1171,6 +1172,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
updateUnfoldBounds();
return;
}
mSplitLayout.update(null /* t */);
onLayoutSizeChanged(mSplitLayout);
}
}
@@ -1198,7 +1201,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (!ENABLE_SHELL_TRANSITIONS) return;
final SurfaceControl.Transaction t = mTransactionPool.acquire();
setDividerVisibility(false, t);
mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
mSplitLayout.rotateTo(toRotation, mDisplayLayout.stableInsets());
updateWindowBounds(mSplitLayout, wct);
@@ -1255,8 +1257,15 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Nullable TransitionRequestInfo request) {
final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
if (triggerTask == null) {
// Still want to monitor everything while in split-screen, so return non-null.
return mMainStage.isActive() ? new WindowContainerTransaction() : null;
if (mMainStage.isActive()) {
if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null) {
mSplitLayout.setFreezeDividerWindow(true);
}
// Still want to monitor everything while in split-screen, so return non-null.
return new WindowContainerTransaction();
} else {
return null;
}
} else if (triggerTask.displayId != mDisplayId) {
// Skip handling task on the other display.
return null;
@@ -1352,8 +1361,14 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// If we're not in split-mode, just abort so something else can handle it.
if (!mMainStage.isActive()) return false;
mSplitLayout.setFreezeDividerWindow(false);
for (int iC = 0; iC < info.getChanges().size(); ++iC) {
final TransitionInfo.Change change = info.getChanges().get(iC);
if (change.getMode() == TRANSIT_CHANGE
&& (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
mSplitLayout.update(startTransaction);
}
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
if (taskInfo == null || !taskInfo.hasParentTask()) continue;
final StageTaskListener stage = getStageOfTask(taskInfo);
@@ -1368,10 +1383,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
+ " with " + taskInfo.taskId + " before startAnimation().");
}
} else if (info.getType() == TRANSIT_CHANGE
&& change.getStartRotation() != change.getEndRotation()) {
// Show the divider after transition finished.
setDividerVisibility(true, finishTransaction);
}
}
if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {

View File

@@ -61,7 +61,7 @@ public class SplitWindowManagerTests extends ShellTestCase {
public void testInitRelease() {
mSplitWindowManager.init(mSplitLayout, new InsetsState());
assertThat(mSplitWindowManager.getSurfaceControl()).isNotNull();
mSplitWindowManager.release();
mSplitWindowManager.release(null /* t */);
assertThat(mSplitWindowManager.getSurfaceControl()).isNull();
}
}