Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49bb6aa5 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[2/N] WindowDecorViewHost: move async relayout to RelayoutParams" into main

parents fb86b64f 53be2af4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -91,7 +91,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
            @ShellBackgroundThread ShellExecutor bgExecutor,
            Choreographer choreographer,
            SyncTransactionQueue syncQueue) {
        super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface);
        super(context, userContext, displayController, taskOrganizer, handler, taskInfo,
                taskSurface);
        mHandler = handler;
        mBgExecutor = bgExecutor;
        mChoreographer = choreographer;
+10 −84
Original line number Diff line number Diff line
@@ -43,7 +43,6 @@ import static com.android.wm.shell.windowdecor.DragPositioningCallbackUtility.Dr

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.WindowConfiguration.WindowingMode;
import android.app.assist.AssistContent;
@@ -158,14 +157,11 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    private Function0<Unit> mOnMaximizeHoverListener;
    private DragPositioningCallback mDragPositioningCallback;
    private DragResizeInputListener mDragResizeListener;
    private Runnable mCurrentViewHostRunnable = null;
    private RelayoutParams mRelayoutParams = new RelayoutParams();
    private DisabledEdge mDisabledResizingEdge =
            NONE;
    private final WindowDecoration.RelayoutResult<WindowDecorLinearLayout> mResult =
            new WindowDecoration.RelayoutResult<>();
    private final Runnable mViewHostRunnable =
            () -> updateViewHost(mRelayoutParams, null /* onDrawTransaction */, mResult);

    private final Point mPositionInParent = new Point();
    private HandleMenu mHandleMenu;
@@ -269,8 +265,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            MultiInstanceHelper multiInstanceHelper,
            WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
            DesktopModeEventLogger desktopModeEventLogger) {
        super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
                surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
        super(context, userContext, displayController, taskOrganizer, handler, taskInfo,
                taskSurface, surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
                windowContainerTransactionSupplier, surfaceControlSupplier,
                surfaceControlViewHostFactory, desktopModeEventLogger);
        mSplitScreenController = splitScreenController;
@@ -451,78 +447,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop,
            boolean hasGlobalFocus, @NonNull Region displayExclusionRegion) {
        Trace.beginSection("DesktopModeWindowDecoration#relayout");
        if (taskInfo.isFreeform()) {
            // The Task is in Freeform mode -> show its header in sync since it's an integral part
            // of the window itself - a delayed header might cause bad UX.
            relayoutInSync(taskInfo, startT, finishT, applyStartTransactionOnDraw,
                    shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus, displayExclusionRegion);
        } else {
            // The Task is outside Freeform mode -> allow the handle view to be delayed since the
            // handle is just a small addition to the window.
            relayoutWithDelayedViewHost(taskInfo, startT, finishT, applyStartTransactionOnDraw,
                    shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus, displayExclusionRegion);
        }
        Trace.endSection();
    }

    /** Run the whole relayout phase immediately without delay. */
    private void relayoutInSync(ActivityManager.RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop,
            boolean hasGlobalFocus, @NonNull Region displayExclusionRegion) {
        // Clear the current ViewHost runnable as we will update the ViewHost here
        clearCurrentViewHostRunnable();
        updateRelayoutParamsAndSurfaces(taskInfo, startT, finishT, applyStartTransactionOnDraw,
                shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus, displayExclusionRegion);
        if (mResult.mRootView != null) {
            updateViewHost(mRelayoutParams, startT, mResult);
        }
    }

    /**
     * Clear the current ViewHost runnable - to ensure it doesn't run once relayout params have been
     * updated.
     */
    private void clearCurrentViewHostRunnable() {
        if (mCurrentViewHostRunnable != null) {
            mHandler.removeCallbacks(mCurrentViewHostRunnable);
            mCurrentViewHostRunnable = null;
        }
    }

    /**
     * Relayout the window decoration but repost some of the work, to unblock the current callstack.
     */
    private void relayoutWithDelayedViewHost(ActivityManager.RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop,
            boolean hasGlobalFocus,
            @NonNull Region displayExclusionRegion) {
        if (applyStartTransactionOnDraw) {
            throw new IllegalArgumentException(
                    "We cannot both sync viewhost ondraw and delay viewhost creation.");
        }
        // Clear the current ViewHost runnable as we will update the ViewHost here
        clearCurrentViewHostRunnable();
        updateRelayoutParamsAndSurfaces(taskInfo, startT, finishT,
                false /* applyStartTransactionOnDraw */, shouldSetTaskVisibilityPositionAndCrop,
                hasGlobalFocus, displayExclusionRegion);
        if (mResult.mRootView == null) {
            // This means something blocks the window decor from showing, e.g. the task is hidden.
            // Nothing is set up in this case including the decoration surface.
            return;
        }
        // Store the current runnable so it can be removed if we start a new relayout.
        mCurrentViewHostRunnable = mViewHostRunnable;
        mHandler.post(mCurrentViewHostRunnable);
    }

    @SuppressLint("MissingPermission")
    private void updateRelayoutParamsAndSurfaces(ActivityManager.RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
            boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop,
            boolean hasGlobalFocus, @NonNull Region displayExclusionRegion) {
        Trace.beginSection("DesktopModeWindowDecoration#updateRelayoutParamsAndSurfaces");
        if (Flags.enableDesktopWindowingAppToWeb()) {
            setCapturedLink(taskInfo.capturedLink, taskInfo.capturedLinkTimestamp);
        }
@@ -553,9 +478,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
        final WindowContainerTransaction wct = new WindowContainerTransaction();

        Trace.beginSection("DesktopModeWindowDecoration#relayout-updateViewsAndSurfaces");
        updateViewsAndSurfaces(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
        Trace.endSection();
        relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
        // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo

        Trace.beginSection("DesktopModeWindowDecoration#relayout-applyWCT");
@@ -570,7 +493,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            }
            mExclusionRegionListener.onExclusionRegionDismissed(mTaskInfo.taskId);
            disposeStatusBarInputLayer();
            Trace.endSection(); // DesktopModeWindowDecoration#updateRelayoutParamsAndSurfaces
            Trace.endSection(); // DesktopModeWindowDecoration#relayout
            return;
        }

@@ -578,7 +501,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            disposeStatusBarInputLayer();
            mWindowDecorViewHolder = createViewHolder();
        }
        Trace.beginSection("DesktopModeWindowDecoration#relayout-binding");

        final Point position = new Point();
        if (isAppHandle(mWindowDecorViewHolder)) {
@@ -588,6 +510,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            notifyCaptionStateChanged();
        }

        Trace.beginSection("DesktopModeWindowDecoration#relayout-bindData");
        if (isAppHandle(mWindowDecorViewHolder)) {
            mWindowDecorViewHolder.bindData(new AppHandleViewHolder.HandleData(
                    mTaskInfo, position, mResult.mCaptionWidth, mResult.mCaptionHeight,
@@ -612,7 +535,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        }
        updateDragResizeListener(oldDecorationSurface, inFullImmersive);
        updateMaximizeMenu(startT, inFullImmersive);
        Trace.endSection(); // DesktopModeWindowDecoration#updateRelayoutParamsAndSurfaces
        Trace.endSection(); // DesktopModeWindowDecoration#relayout
    }

    private boolean isCaptionVisible() {
@@ -897,6 +820,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId);
        relayoutParams.mHasGlobalFocus = hasGlobalFocus;
        relayoutParams.mDisplayExclusionRegion.set(displayExclusionRegion);
        // Allow the handle view to be delayed since the handle is just a small addition to the
        // window, whereas the header cannot be delayed because it is expected to be visible from
        // the first frame.
        relayoutParams.mAsyncViewHost = isAppHandle;

        final boolean showCaption;
        if (Flags.enableFullyImmersiveInDesktop()) {
@@ -1703,7 +1630,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        mExclusionRegionListener.onExclusionRegionDismissed(mTaskInfo.taskId);
        disposeResizeVeil();
        disposeStatusBarInputLayer();
        clearCurrentViewHostRunnable();
        if (canEnterDesktopMode(mContext) && isEducationEnabled()) {
            notifyNoCaptionHandle();
        }
+137 −106

File changed.

Preview size limit exceeded, changes collapsed.

+42 −64
Original line number Diff line number Diff line
@@ -51,7 +51,6 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.kotlin.VerificationKt.times;

import android.app.ActivityManager;
import android.app.assist.AssistContent;
@@ -1052,61 +1051,70 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
    }

    @Test
    public void relayout_fullscreenTask_appliesTransactionImmediately() {
    public void updateRelayoutParams_handle_requestsAsyncViewHostRendering() {
        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
        // Make the task fullscreen so that its decoration is an App Handle.
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        final RelayoutParams relayoutParams = new RelayoutParams();

        spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
        DesktopModeWindowDecoration.updateRelayoutParams(
                relayoutParams,
                mTestableContext,
                taskInfo,
                mMockSplitScreenController,
                /* applyStartTransactionOnDraw= */ true,
                /* shouldSetTaskPositionAndCrop= */ false,
                /* isStatusBarVisible= */ true,
                /* isKeyguardVisibleAndOccluded= */ false,
                /* inFullImmersiveMode= */ false,
                new InsetsState(),
                /* hasGlobalFocus= */ true,
                mExclusionRegion);

        verify(mMockTransaction).apply();
        verify(mMockRootSurfaceControl, never()).applyTransactionOnDraw(any());
        // App Handles don't need to be rendered in sync with the task animation, per UX.
        assertThat(relayoutParams.mAsyncViewHost).isTrue();
    }

    @Test
    @Ignore("TODO(b/367235906): Due to MONITOR_INPUT permission error")
    public void relayout_freeformTask_appliesTransactionOnDraw() {
    public void updateRelayoutParams_header_requestsSyncViewHostRendering() {
        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
        // Make the task freeform so that its decoration is an App Header.
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
        // Make non-resizable to avoid dealing with input-permissions (MONITOR_INPUT)
        taskInfo.isResizeable = false;

        spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);

        verify(mMockTransaction, never()).apply();
        verify(mMockRootSurfaceControl).applyTransactionOnDraw(mMockTransaction);
    }

    @Test
    public void relayout_fullscreenTask_doesNotCreateViewHostImmediately() {
        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        final RelayoutParams relayoutParams = new RelayoutParams();

        spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
        DesktopModeWindowDecoration.updateRelayoutParams(
                relayoutParams,
                mTestableContext,
                taskInfo,
                mMockSplitScreenController,
                /* applyStartTransactionOnDraw= */ true,
                /* shouldSetTaskPositionAndCrop= */ false,
                /* isStatusBarVisible= */ true,
                /* isKeyguardVisibleAndOccluded= */ false,
                /* inFullImmersiveMode= */ false,
                new InsetsState(),
                /* hasGlobalFocus= */ true,
                mExclusionRegion);

        verify(mMockSurfaceControlViewHostFactory, never()).create(any(), any(), any());
        // App Headers must be rendered in sync with the task animation, so it cannot be delayed.
        assertThat(relayoutParams.mAsyncViewHost).isFalse();
    }

    @Test
    public void relayout_fullscreenTask_postsViewHostCreation() {
    public void relayout_fullscreenTask_appliesTransactionImmediately() {
        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);

        ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
        spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);

        // Once for view host, the other for the AppHandle input layer.
        verify(mMockHandler, times(2)).post(runnableArgument.capture());
        runnableArgument.getValue().run();
        verify(mMockSurfaceControlViewHostFactory).create(any(), any(), any());
        verify(mMockTransaction).apply();
        verify(mMockRootSurfaceControl, never()).applyTransactionOnDraw(any());
    }

    @Test
    @Ignore("TODO(b/367235906): Due to MONITOR_INPUT permission error")
    public void relayout_freeformTask_createsViewHostImmediately() {
    public void relayout_freeformTask_appliesTransactionOnDraw() {
        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
@@ -1115,38 +1123,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {

        spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);

        verify(mMockSurfaceControlViewHostFactory).create(any(), any(), any());
        verify(mMockHandler, never()).post(any());
    }

    @Test
    public void relayout_removesExistingHandlerCallback() {
        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
        spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
        // Once for view host, the other for the AppHandle input layer.
        verify(mMockHandler, times(2)).post(runnableArgument.capture());

        spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);

        verify(mMockHandler).removeCallbacks(runnableArgument.getValue());
    }

    @Test
    public void close_removesExistingHandlerCallback() {
        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
        spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
        // Once for view host, the other for the AppHandle input layer.
        verify(mMockHandler, times(2)).post(runnableArgument.capture());

        spyWindowDecor.close();

        verify(mMockHandler).removeCallbacks(runnableArgument.getValue());
        verify(mMockTransaction, never()).apply();
        verify(mMockRootSurfaceControl).applyTransactionOnDraw(mMockTransaction);
    }

    @Test
+60 −22
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Handler;
import android.platform.test.flag.junit.SetFlagsRule;
import android.testing.AndroidTestingRunner;
import android.util.DisplayMetrics;
@@ -143,6 +144,8 @@ public class WindowDecorationTests extends ShellTestCase {
    private SurfaceControl mMockTaskSurface;
    @Mock
    private DesktopModeEventLogger mDesktopModeEventLogger;
    @Mock
    private Handler mMockHandler;

    private final List<SurfaceControl.Transaction> mMockSurfaceControlTransactions =
            new ArrayList<>();
@@ -901,37 +904,71 @@ public class WindowDecorationTests extends ShellTestCase {
    }

    @Test
    public void updateViewHost_applyTransactionOnDrawIsTrue_surfaceControlIsUpdated() {
    public void relayout_applyTransactionOnDrawIsTrue_updatesViewWithDrawTransaction() {
        final TestWindowDecoration windowDecor = createWindowDecoration(
                new TestRunningTaskInfoBuilder().build());
                new TestRunningTaskInfoBuilder()
                        .setVisible(true)
                        .setWindowingMode(WINDOWING_MODE_FREEFORM)
                        .build());
        mRelayoutParams.mApplyStartTransactionOnDraw = true;
        mRelayoutResult.mRootView = mMockView;

        windowDecor.updateViewHost(mRelayoutParams, mMockSurfaceControlStartT, mRelayoutResult);
        windowDecor.relayout(
                windowDecor.mTaskInfo,
                /* hasGlobalFocus= */ true,
                Region.obtain());

        verify(mMockRootSurfaceControl).applyTransactionOnDraw(mMockSurfaceControlStartT);
        windowDecor.close();
    }

    @Test
    public void updateViewHost_nullDrawTransaction_applyTransactionOnDrawIsTrue_throwsException() {
    public void relayout_applyTransactionOnDrawIsTrue_asyncViewHostRendering_throwsException() {
        final TestWindowDecoration windowDecor = createWindowDecoration(
                new TestRunningTaskInfoBuilder().build());
                new TestRunningTaskInfoBuilder()
                        .setVisible(true)
                        .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
                        .build());
        mRelayoutParams.mApplyStartTransactionOnDraw = true;
        mRelayoutParams.mAsyncViewHost = true;
        mRelayoutResult.mRootView = mMockView;

        windowDecor.relayout(
                windowDecor.mTaskInfo,
                /* hasGlobalFocus= */ true,
                Region.obtain());
        final ArgumentCaptor<Runnable> updateViewHostCaptor =
                ArgumentCaptor.forClass(Runnable.class);
        verify(mMockHandler).post(updateViewHostCaptor.capture());
        assertThrows(IllegalArgumentException.class,
                () -> windowDecor.updateViewHost(
                        mRelayoutParams, null /* onDrawTransaction */, mRelayoutResult));
                () -> updateViewHostCaptor.getValue().run());
        windowDecor.close();
    }

    @Test
    public void updateViewHost_nullDrawTransaction_applyTransactionOnDrawIsFalse_doesNotThrow() {
    public void relayout_asyncViewHostRendering() {
        final TestWindowDecoration windowDecor = createWindowDecoration(
                new TestRunningTaskInfoBuilder().build());
                new TestRunningTaskInfoBuilder()
                        .setVisible(true)
                        .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
                        .build());
        mRelayoutParams.mApplyStartTransactionOnDraw = false;
        mRelayoutParams.mAsyncViewHost = true;
        mRelayoutResult.mRootView = mMockView;

        windowDecor.updateViewHost(mRelayoutParams, null /* onDrawTransaction */, mRelayoutResult);
        windowDecor.relayout(
                windowDecor.mTaskInfo,
                /* hasGlobalFocus= */ true,
                Region.obtain());

        final ArgumentCaptor<Runnable> updateViewHostCaptor =
                ArgumentCaptor.forClass(Runnable.class);
        verify(mMockHandler).post(updateViewHostCaptor.capture());

        updateViewHostCaptor.getValue().run();

        verify(mMockSurfaceControlViewHost).setView(eq(mMockView), any());
        windowDecor.close();
    }

    @Test
@@ -1009,7 +1046,7 @@ public class WindowDecorationTests extends ShellTestCase {

    private TestWindowDecoration createWindowDecoration(ActivityManager.RunningTaskInfo taskInfo) {
        return new TestWindowDecoration(mContext, mContext, mMockDisplayController,
                mMockShellTaskOrganizer, taskInfo, mMockTaskSurface,
                mMockShellTaskOrganizer, mMockHandler, taskInfo, mMockTaskSurface,
                new MockObjectSupplier<>(mMockSurfaceControlBuilders,
                        () -> createMockSurfaceControlBuilder(mock(SurfaceControl.class))),
                new MockObjectSupplier<>(mMockSurfaceControlTransactions,
@@ -1049,7 +1086,9 @@ public class WindowDecorationTests extends ShellTestCase {
    private class TestWindowDecoration extends WindowDecoration<TestView> {
        TestWindowDecoration(Context context, @NonNull Context userContext,
                DisplayController displayController,
                ShellTaskOrganizer taskOrganizer, ActivityManager.RunningTaskInfo taskInfo,
                ShellTaskOrganizer taskOrganizer,
                Handler handler,
                ActivityManager.RunningTaskInfo taskInfo,
                SurfaceControl taskSurface,
                Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
                Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
@@ -1057,8 +1096,8 @@ public class WindowDecorationTests extends ShellTestCase {
                Supplier<SurfaceControl> surfaceControlSupplier,
                SurfaceControlViewHostFactory surfaceControlViewHostFactory,
                DesktopModeEventLogger desktopModeEventLogger) {
            super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
                    surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
            super(context, userContext, displayController, taskOrganizer, handler, taskInfo,
                    taskSurface, surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
                    windowContainerTransactionSupplier, surfaceControlSupplier,
                    surfaceControlViewHostFactory, desktopModeEventLogger);
        }
@@ -1071,8 +1110,12 @@ public class WindowDecorationTests extends ShellTestCase {
        @Override
        void relayout(ActivityManager.RunningTaskInfo taskInfo, boolean hasGlobalFocus,
                @NonNull Region displayExclusionRegion) {
            relayout(taskInfo, false /* applyStartTransactionOnDraw */, hasGlobalFocus,
                    displayExclusionRegion);
            mRelayoutParams.mRunningTaskInfo = taskInfo;
            mRelayoutParams.mHasGlobalFocus = hasGlobalFocus;
            mRelayoutParams.mDisplayExclusionRegion.set(displayExclusionRegion);
            mRelayoutParams.mLayoutResId = R.layout.caption_layout;
            relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT,
                    mMockWindowContainerTransaction, mMockView, mRelayoutResult);
        }

        @Override
@@ -1096,13 +1139,8 @@ public class WindowDecorationTests extends ShellTestCase {
        void relayout(ActivityManager.RunningTaskInfo taskInfo,
                boolean applyStartTransactionOnDraw, boolean hasGlobalFocus,
                @NonNull Region displayExclusionRegion) {
            mRelayoutParams.mRunningTaskInfo = taskInfo;
            mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
            mRelayoutParams.mLayoutResId = R.layout.caption_layout;
            mRelayoutParams.mHasGlobalFocus = hasGlobalFocus;
            mRelayoutParams.mDisplayExclusionRegion.set(displayExclusionRegion);
            relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT,
                    mMockWindowContainerTransaction, mMockView, mRelayoutResult);
            relayout(taskInfo, hasGlobalFocus, displayExclusionRegion);
        }

        private AdditionalViewContainer addTestViewContainer() {