Merge "Fix flicker when task move to back" into sc-v2-dev am: d2f034f1d5

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15810446

Change-Id: I1e0f846612b97975ac1e9313f7bd4dbd632f48d4
This commit is contained in:
TreeHugger Robot
2021-09-17 20:41:58 +00:00
committed by Automerger Merge Worker

View File

@@ -18,8 +18,6 @@ package com.android.wm.shell.splitscreen;
import static android.app.ActivityOptions.KEY_LAUNCH_ROOT_TASK_TOKEN; import static android.app.ActivityOptions.KEY_LAUNCH_ROOT_TASK_TOKEN;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_BACK;
@@ -515,7 +513,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSideStage.removeAllTasks(wct, childrenToTop == mSideStage); mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
mMainStage.deactivate(wct, childrenToTop == mMainStage); mMainStage.deactivate(wct, childrenToTop == mMainStage);
mTaskOrganizer.applyTransaction(wct); mTaskOrganizer.applyTransaction(wct);
// Reset divider position. // Hide divider and reset its position.
setDividerVisibility(false);
mSplitLayout.resetDividerPosition(); mSplitLayout.resetDividerPosition();
mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED; mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
if (childrenToTop != null) { if (childrenToTop != null) {
@@ -649,10 +648,15 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void onStageVisibilityChanged(StageListenerImpl stageListener) { private void onStageVisibilityChanged(StageListenerImpl stageListener) {
final boolean sideStageVisible = mSideStageListener.mVisible; final boolean sideStageVisible = mSideStageListener.mVisible;
final boolean mainStageVisible = mMainStageListener.mVisible; final boolean mainStageVisible = mMainStageListener.mVisible;
// Divider is only visible if both the main stage and side stages are visible final boolean bothStageVisible = sideStageVisible && mainStageVisible;
setDividerVisibility(isSplitScreenVisible()); final boolean sameVisibility = sideStageVisible == mainStageVisible;
// Only add or remove divider when both visible or both invisible to avoid sometimes we only
// got one stage visibility changed for a moment and it will cause flicker.
if (sameVisibility) {
setDividerVisibility(bothStageVisible);
}
if (!mainStageVisible && !sideStageVisible) { if (!bothStageVisible) {
if (mExitSplitScreenOnHide if (mExitSplitScreenOnHide
// Don't dismiss staged split when both stages are not visible due to sleeping display, // Don't dismiss staged split when both stages are not visible due to sleeping display,
// like the cases keyguard showing or screen off. // like the cases keyguard showing or screen off.
@@ -669,59 +673,32 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
exitSplitScreen(toTop, SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP); exitSplitScreen(toTop, SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP);
} }
// When both stage's visibility changed to visible, main stage might receives visibility
// changed before side stage if it has higher z-order than side stage. Make sure we only
// update main stage's windowing mode with the visibility changed of side stage to prevent
// stacking multiple windowing mode transactions which result to flicker issue.
if (mainStageVisible && stageListener == mSideStageListener) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (sideStageVisible) {
// The main stage configuration should to follow split layout when side stage is
// visible.
mMainStage.updateConfiguration(
WINDOWING_MODE_MULTI_WINDOW, getMainStageBounds(), wct);
} else if (!mSideStage.mRootTaskInfo.isSleeping) {
// We want the main stage configuration to be fullscreen when the side stage isn't
// visible.
// We should not do it when side stage are not visible due to sleeping display too.
mMainStage.updateConfiguration(WINDOWING_MODE_FULLSCREEN, null, wct);
}
// TODO: Change to `mSyncQueue.queue(wct)` once BLAST is stable.
mTaskOrganizer.applyTransaction(wct);
}
mSyncQueue.runInSync(t -> { mSyncQueue.runInSync(t -> {
final SurfaceControl sideStageLeash = mSideStage.mRootLeash; final SurfaceControl sideStageLeash = mSideStage.mRootLeash;
final SurfaceControl mainStageLeash = mMainStage.mRootLeash; final SurfaceControl mainStageLeash = mMainStage.mRootLeash;
if (sideStageVisible) { if (sideStageVisible) {
final Rect sideStageBounds = getSideStageBounds(); final Rect sideStageBounds = getSideStageBounds();
t.show(sideStageLeash) t.setPosition(sideStageLeash,
.setPosition(sideStageLeash,
sideStageBounds.left, sideStageBounds.top) sideStageBounds.left, sideStageBounds.top)
.setWindowCrop(sideStageLeash, .setWindowCrop(sideStageLeash,
sideStageBounds.width(), sideStageBounds.height()); sideStageBounds.width(), sideStageBounds.height());
} else {
t.hide(sideStageLeash);
} }
if (mainStageVisible) { if (mainStageVisible) {
final Rect mainStageBounds = getMainStageBounds(); final Rect mainStageBounds = getMainStageBounds();
t.show(mainStageLeash);
if (sideStageVisible) {
t.setPosition(mainStageLeash, mainStageBounds.left, mainStageBounds.top) t.setPosition(mainStageLeash, mainStageBounds.left, mainStageBounds.top)
.setWindowCrop(mainStageLeash, .setWindowCrop(mainStageLeash,
mainStageBounds.width(), mainStageBounds.height()); mainStageBounds.width(), mainStageBounds.height());
} else {
// Clear window crop and position if side stage isn't visible.
t.setPosition(mainStageLeash, 0, 0)
.setWindowCrop(mainStageLeash, null);
}
} else {
t.hide(mainStageLeash);
} }
// Same above, we only set root tasks and divider leash visibility when both stage
// change to visible or invisible to avoid flicker.
if (sameVisibility) {
t.setVisibility(sideStageLeash, bothStageVisible)
.setVisibility(mainStageLeash, bothStageVisible);
applyDividerVisibility(t); applyDividerVisibility(t);
}
}); });
} }