Fix divider disappear when rotation on shell transition
When rotation, it will re-init the split divider for new rotation on DAinfoChanged callback, but when shell transition, we should do it on startAnimation to make transition smooth and make didider could release by specfic Transcation to avoid it hide immediately but didn't sync with transition. Fix: 222158856 Test: manual Test: pass existing tests Change-Id: I797ffd0ea35d89b4ec1e3ef4828ce36e18c860be
This commit is contained in:
@@ -217,9 +217,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user