From 08ac74f125f3f17a02536095528859950244a7f8 Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Fri, 24 Sep 2021 13:03:52 +0800 Subject: [PATCH] Consolidate the behavior and style of side stage outline Update the style of side stage outline to match the current design. And make sure the outline will interact properly with task bar expanding, collapsing, swipe up, drag to split, recents shortcut to split and drag divider bar to resize gestures. Bug: 200850654 Test: atest WMShellUnitTests Test: enable side stage outline, observed it behaves properly. Change-Id: I3f0795adc34a0efb19d35b78d54364da4189a043 --- .../Shell/res/layout/split_outline.xml | 4 +- .../wm/shell/splitscreen/OutlineManager.java | 132 ++++++++++++------ .../wm/shell/splitscreen/OutlineRoot.java | 62 -------- .../wm/shell/splitscreen/OutlineView.java | 66 +++++---- .../wm/shell/splitscreen/SideStage.java | 75 +++++++--- .../splitscreen/SplitScreenController.java | 9 +- .../shell/splitscreen/StageCoordinator.java | 29 ++++ .../shell/splitscreen/StageTaskListener.java | 7 +- .../wm/shell/splitscreen/SideStageTests.java | 2 + .../splitscreen/SplitTransitionTests.java | 2 + .../splitscreen/StageTaskListenerTests.java | 6 +- 11 files changed, 230 insertions(+), 164 deletions(-) delete mode 100644 libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineRoot.java diff --git a/libs/WindowManager/Shell/res/layout/split_outline.xml b/libs/WindowManager/Shell/res/layout/split_outline.xml index 4e2a77f213a00..13a30f5a04233 100644 --- a/libs/WindowManager/Shell/res/layout/split_outline.xml +++ b/libs/WindowManager/Shell/res/layout/split_outline.xml @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - @@ -23,4 +23,4 @@ android:layout_height="match_parent" android:layout_width="match_parent" /> - + diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java index 0b763f2d05f7a..a459c8dbfa345 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java @@ -22,19 +22,23 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMA import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; +import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Binder; import android.view.IWindow; +import android.view.InsetsSource; +import android.view.InsetsState; import android.view.LayoutInflater; import android.view.SurfaceControl; import android.view.SurfaceControlViewHost; -import android.view.WindowInsets; +import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; -import android.view.WindowMetrics; import android.view.WindowlessWindowManager; +import android.widget.FrameLayout; import com.android.wm.shell.R; @@ -45,17 +49,22 @@ import com.android.wm.shell.R; class OutlineManager extends WindowlessWindowManager { private static final String WINDOW_NAME = "SplitOutlineLayer"; private final Context mContext; - private final Rect mOutlineBounds = new Rect(); - private final Rect mTmpBounds = new Rect(); + private final Rect mRootBounds = new Rect(); + private final Rect mTempRect = new Rect(); + private final Rect mLastOutlineBounds = new Rect(); + private final InsetsState mInsetsState = new InsetsState(); + private final int mExpandedTaskBarHeight; + private OutlineView mOutlineView; private SurfaceControlViewHost mViewHost; private SurfaceControl mHostLeash; private SurfaceControl mLeash; - private int mOutlineColor; OutlineManager(Context context, Configuration configuration) { super(configuration, null /* rootSurface */, null /* hostInputToken */); mContext = context.createWindowContext(context.getDisplay(), TYPE_APPLICATION_OVERLAY, null /* options */); + mExpandedTaskBarHeight = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.taskbar_frame_height); } @Override @@ -63,65 +72,110 @@ class OutlineManager extends WindowlessWindowManager { b.setParent(mHostLeash); } - boolean drawOutlineBounds(Rect rootBounds) { - if (mLeash == null || mViewHost == null) return false; - - computeOutlineBounds(mContext, rootBounds, mTmpBounds); - if (mOutlineBounds.equals(mTmpBounds)) { - return false; - } - mOutlineBounds.set(mTmpBounds); - - ((OutlineRoot) mViewHost.getView()).updateOutlineBounds(mOutlineBounds, mOutlineColor); - final WindowManager.LayoutParams lp = - (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams(); - lp.width = rootBounds.width(); - lp.height = rootBounds.height(); - mViewHost.relayout(lp); - - return true; - } - - void inflate(SurfaceControl.Transaction t, SurfaceControl hostLeash, int color) { + void inflate(SurfaceControl rootLeash, Rect rootBounds) { if (mLeash != null || mViewHost != null) return; - mHostLeash = hostLeash; - mOutlineColor = color; + mHostLeash = rootLeash; + mRootBounds.set(rootBounds); mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this); - final OutlineRoot rootView = (OutlineRoot) LayoutInflater.from(mContext) + + final FrameLayout rootLayout = (FrameLayout) LayoutInflater.from(mContext) .inflate(R.layout.split_outline, null); + mOutlineView = rootLayout.findViewById(R.id.split_outline); final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 0 /* width */, 0 /* height */, TYPE_APPLICATION_OVERLAY, FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT); + lp.width = mRootBounds.width(); + lp.height = mRootBounds.height(); lp.token = new Binder(); lp.setTitle(WINDOW_NAME); lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY; // TODO(b/189839391): Set INPUT_FEATURE_NO_INPUT_CHANNEL after WM supports // TRUSTED_OVERLAY for windowless window without input channel. - mViewHost.setView(rootView, lp); + mViewHost.setView(rootLayout, lp); mLeash = getSurfaceControl(mViewHost.getWindowToken()); - t.setLayer(mLeash, Integer.MAX_VALUE); + + drawOutline(); } void release() { if (mViewHost != null) { mViewHost.release(); + mViewHost = null; + } + mRootBounds.setEmpty(); + mLastOutlineBounds.setEmpty(); + mOutlineView = null; + mHostLeash = null; + mLeash = null; + } + + @Nullable + SurfaceControl getOutlineLeash() { + return mLeash; + } + + void setVisibility(boolean visible) { + if (mOutlineView != null) { + mOutlineView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); } } - private static void computeOutlineBounds(Context context, Rect rootBounds, Rect outBounds) { - computeDisplayStableBounds(context, outBounds); - outBounds.intersect(rootBounds); + void setRootBounds(Rect rootBounds) { + if (mViewHost == null || mViewHost.getView() == null) { + return; + } + + if (!mRootBounds.equals(rootBounds)) { + WindowManager.LayoutParams lp = + (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams(); + lp.width = rootBounds.width(); + lp.height = rootBounds.height(); + mViewHost.relayout(lp); + mRootBounds.set(rootBounds); + drawOutline(); + } + } + + void onInsetsChanged(InsetsState insetsState) { + if (!mInsetsState.equals(insetsState)) { + mInsetsState.set(insetsState); + drawOutline(); + } + } + + private void computeOutlineBounds(Rect rootBounds, InsetsState insetsState, Rect outBounds) { + outBounds.set(rootBounds); + final InsetsSource taskBarInsetsSource = + insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR); + // Only insets the divider bar with task bar when it's expanded so that the rounded corners + // will be drawn against task bar. + if (taskBarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) { + outBounds.inset(taskBarInsetsSource.calculateVisibleInsets(outBounds)); + } + // Offset the coordinate from screen based to surface based. outBounds.offset(-rootBounds.left, -rootBounds.top); } - private static void computeDisplayStableBounds(Context context, Rect outBounds) { - final WindowMetrics windowMetrics = - context.getSystemService(WindowManager.class).getMaximumWindowMetrics(); - outBounds.set(windowMetrics.getBounds()); - outBounds.inset(windowMetrics.getWindowInsets().getInsets( - WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout())); + void drawOutline() { + if (mOutlineView == null) { + return; + } + + computeOutlineBounds(mRootBounds, mInsetsState, mTempRect); + if (mTempRect.equals(mLastOutlineBounds)) { + return; + } + + ViewGroup.MarginLayoutParams lp = + (ViewGroup.MarginLayoutParams) mOutlineView.getLayoutParams(); + lp.leftMargin = mTempRect.left; + lp.topMargin = mTempRect.top; + lp.width = mTempRect.width(); + lp.height = mTempRect.height(); + mOutlineView.setLayoutParams(lp); + mLastOutlineBounds.set(mTempRect); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineRoot.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineRoot.java deleted file mode 100644 index 71d48eeca71df..0000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineRoot.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.splitscreen; - -import android.content.Context; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.widget.FrameLayout; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.wm.shell.R; - -/** Root layout for holding split outline. */ -public class OutlineRoot extends FrameLayout { - public OutlineRoot(@NonNull Context context) { - super(context); - } - - public OutlineRoot(@NonNull Context context, - @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public OutlineRoot(@NonNull Context context, @Nullable AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public OutlineRoot(@NonNull Context context, @Nullable AttributeSet attrs, - int defStyleAttr, - int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - private OutlineView mOutlineView; - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mOutlineView = findViewById(R.id.split_outline); - } - - void updateOutlineBounds(Rect bounds, int color) { - mOutlineView.updateOutlineBounds(bounds, color); - } -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java index ea66180e3dd22..94dd9b24875a8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java @@ -16,13 +16,17 @@ package com.android.wm.shell.splitscreen; +import static android.view.RoundedCorner.POSITION_BOTTOM_LEFT; +import static android.view.RoundedCorner.POSITION_BOTTOM_RIGHT; +import static android.view.RoundedCorner.POSITION_TOP_LEFT; +import static android.view.RoundedCorner.POSITION_TOP_RIGHT; + import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; -import android.graphics.Rect; -import android.graphics.Region; import android.util.AttributeSet; +import android.view.RoundedCorner; import android.view.View; import androidx.annotation.NonNull; @@ -33,44 +37,46 @@ import com.android.internal.R; /** View for drawing split outline. */ public class OutlineView extends View { private final Paint mPaint = new Paint(); - private final Rect mBounds = new Rect(); + private final Path mPath = new Path(); + private final float[] mRadii = new float[8]; - public OutlineView(@NonNull Context context) { - super(context); - } - - public OutlineView(@NonNull Context context, - @Nullable AttributeSet attrs) { + public OutlineView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); - } - - public OutlineView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public OutlineView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, - int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth( + getResources().getDimension(R.dimen.accessibility_focus_highlight_stroke_width)); + mPaint.setColor(getResources().getColor(R.color.system_accent1_100, null)); } @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mPaint.setStyle(Paint.Style.STROKE); - mPaint.setStrokeWidth(getResources() - .getDimension(R.dimen.accessibility_focus_highlight_stroke_width)); + protected void onAttachedToWindow() { + // TODO(b/200850654): match the screen corners with the actual display decor. + mRadii[0] = mRadii[1] = getCornerRadius(POSITION_TOP_LEFT); + mRadii[2] = mRadii[3] = getCornerRadius(POSITION_TOP_RIGHT); + mRadii[4] = mRadii[5] = getCornerRadius(POSITION_BOTTOM_RIGHT); + mRadii[6] = mRadii[7] = getCornerRadius(POSITION_BOTTOM_LEFT); } - void updateOutlineBounds(Rect bounds, int color) { - if (mBounds.equals(bounds) && mPaint.getColor() == color) return; - mBounds.set(bounds); - mPaint.setColor(color); + private int getCornerRadius(@RoundedCorner.Position int position) { + final RoundedCorner roundedCorner = getDisplay().getRoundedCorner(position); + return roundedCorner == null ? 0 : roundedCorner.getRadius(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (changed) { + mPath.reset(); + mPath.addRoundRect(0, 0, getWidth(), getHeight(), mRadii, Path.Direction.CW); + } } @Override protected void onDraw(Canvas canvas) { - if (mBounds.isEmpty()) return; - final Path path = new Region(mBounds).getBoundaryPath(); - canvas.drawPath(path, mPaint); + canvas.drawPath(mPath, mPaint); + } + + @Override + public boolean hasOverlappingRendering() { + return false; } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java index 2b19bb965fed0..0e7ccd3515c48 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java @@ -17,15 +17,19 @@ package com.android.wm.shell.splitscreen; import android.annotation.CallSuper; +import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Context; -import android.graphics.Color; import android.graphics.Rect; +import android.view.InsetsSourceControl; +import android.view.InsetsState; +import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.SyncTransactionQueue; /** @@ -34,7 +38,8 @@ import com.android.wm.shell.common.SyncTransactionQueue; * * @see StageCoordinator */ -class SideStage extends StageTaskListener { +class SideStage extends StageTaskListener implements + DisplayInsetsController.OnInsetsChangedListener { private static final String TAG = SideStage.class.getSimpleName(); private final Context mContext; private OutlineManager mOutlineManager; @@ -77,33 +82,61 @@ class SideStage extends StageTaskListener { return true; } - void enableOutline(boolean enable) { - if (enable) { - if (mOutlineManager == null && mRootTaskInfo != null) { - mOutlineManager = new OutlineManager(mContext, mRootTaskInfo.configuration); - mSyncQueue.runInSync(t -> mOutlineManager.inflate(t, mRootLeash, Color.YELLOW)); - updateOutlineBounds(); - } - } else { - if (mOutlineManager != null) { - mOutlineManager.release(); - mOutlineManager = null; - } - } + @Nullable + public SurfaceControl getOutlineLeash() { + return mOutlineManager.getOutlineLeash(); } - private void updateOutlineBounds() { - if (mOutlineManager == null || mRootTaskInfo == null || !mRootTaskInfo.isVisible) return; - mOutlineManager.drawOutlineBounds( - mRootTaskInfo.configuration.windowConfiguration.getBounds()); + @Override + @CallSuper + public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { + super.onTaskAppeared(taskInfo, leash); + if (isRootTask(taskInfo)) { + mOutlineManager = new OutlineManager(mContext, taskInfo.configuration); + enableOutline(true); + } } @Override @CallSuper public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { super.onTaskInfoChanged(taskInfo); - if (mRootTaskInfo != null && mRootTaskInfo.taskId == taskInfo.taskId) { - updateOutlineBounds(); + if (isRootTask(taskInfo)) { + mOutlineManager.setRootBounds(taskInfo.configuration.windowConfiguration.getBounds()); } } + + private boolean isRootTask(ActivityManager.RunningTaskInfo taskInfo) { + return mRootTaskInfo != null && mRootTaskInfo.taskId == taskInfo.taskId; + } + + void enableOutline(boolean enable) { + if (mOutlineManager == null) { + return; + } + + if (enable) { + if (mRootTaskInfo != null) { + mOutlineManager.inflate(mRootLeash, + mRootTaskInfo.configuration.windowConfiguration.getBounds()); + } + } else { + mOutlineManager.release(); + } + } + + void setOutlineVisibility(boolean visible) { + mOutlineManager.setVisibility(visible); + } + + @Override + public void insetsChanged(InsetsState insetsState) { + mOutlineManager.onInsetsChanged(insetsState); + } + + @Override + public void insetsControlChanged(InsetsState insetsState, + InsetsSourceControl[] activeControls) { + insetsChanged(insetsState); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 6527cabb0d347..ac68b3b8a6a9a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -257,11 +257,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } - final RemoteAnimationTarget divider = mStageCoordinator.getDividerBarLegacyTarget(); - if (divider.leash != null) { - t.show(divider.leash); - } - t.apply(); if (finishedCallback != null) { try { @@ -300,7 +295,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } transaction.apply(); transaction.close(); - return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()}; + return new RemoteAnimationTarget[]{ + mStageCoordinator.getDividerBarLegacyTarget(), + mStageCoordinator.getOutlineLegacyTarget()}; } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index a046c42b2391c..d7a6cfff6c6fb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -201,6 +201,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSurfaceSession); mDisplayImeController = displayImeController; mDisplayInsetsController = displayInsetsController; + mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSideStage); mRootTDAOrganizer.registerListener(displayId, this); final DeviceStateManager deviceStateManager = mContext.getSystemService(DeviceStateManager.class); @@ -682,6 +683,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, t.setVisibility(mSideStage.mRootLeash, bothStageVisible) .setVisibility(mMainStage.mRootLeash, bothStageVisible); applyDividerVisibility(t); + applyOutlineVisibility(t); } }); } @@ -703,6 +705,19 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } + private void applyOutlineVisibility(SurfaceControl.Transaction t) { + final SurfaceControl outlineLeash = mSideStage.getOutlineLeash(); + if (outlineLeash == null) { + return; + } + + if (mDividerVisible) { + t.show(outlineLeash).setLayer(outlineLeash, SPLIT_DIVIDER_LAYER); + } else { + t.hide(outlineLeash); + } + } + private void onStageHasChildrenChanged(StageListenerImpl stageListener) { final boolean hasChildren = stageListener.mHasChildren; final boolean isSideStage = stageListener == mSideStageListener; @@ -762,6 +777,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Override public void onLayoutChanging(SplitLayout layout) { mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t)); + mSideStage.setOutlineVisibility(false); } @Override @@ -770,6 +786,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, updateWindowBounds(layout, wct); mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t)); + mSideStage.setOutlineVisibility(true); mLogger.logResize(mSplitLayout.getDividerPositionAsFraction()); } @@ -1145,6 +1162,18 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, null /* taskInfo */, false /* allowEnterPip */, TYPE_DOCK_DIVIDER); } + RemoteAnimationTarget getOutlineLegacyTarget() { + final Rect bounds = mSideStage.mRootTaskInfo.configuration.windowConfiguration.getBounds(); + // Leverage TYPE_DOCK_DIVIDER type when wrapping outline remote animation target in order to + // distinguish as a split auxiliary target in Launcher. + return new RemoteAnimationTarget(-1 /* taskId */, -1 /* mode */, + mSideStage.getOutlineLeash(), false /* isTranslucent */, null /* clipRect */, + null /* contentInsets */, Integer.MAX_VALUE /* prefixOrderIndex */, + new android.graphics.Point(0, 0) /* position */, bounds, bounds, + new WindowConfiguration(), true, null /* startLeash */, null /* startBounds */, + null /* taskInfo */, false /* allowEnterPip */, TYPE_DOCK_DIVIDER); + } + @Override public void dump(@NonNull PrintWriter pw, String prefix) { final String innerPrefix = prefix + " "; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index 15b4ff9702038..4140332f50a3a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -138,8 +138,11 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { mRootTaskInfo = taskInfo; mCallbacks.onRootTaskAppeared(); sendStatusChanged(); - mSyncQueue.runInSync(t -> mDimLayer = - SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession)); + mSyncQueue.runInSync(t -> { + t.hide(mRootLeash); + mDimLayer = + SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession); + }); } else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) { final int taskId = taskInfo.taskId; mChildrenLeashes.put(taskId, leash); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java index 69ead3ac9cf95..3a2516ec9366a 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java @@ -29,6 +29,7 @@ import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.WindowContainerTransaction; +import androidx.test.annotation.UiThreadTest; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -58,6 +59,7 @@ public class SideStageTests extends ShellTestCase { private SideStage mSideStage; @Before + @UiThreadTest public void setup() { MockitoAnnotations.initMocks(this); mRootTask = new TestRunningTaskInfoBuilder().build(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java index d357e778fe35a..8dce454eb0782 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java @@ -51,6 +51,7 @@ import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; +import androidx.test.annotation.UiThreadTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -96,6 +97,7 @@ public class SplitTransitionTests extends ShellTestCase { private ActivityManager.RunningTaskInfo mSideChild; @Before + @UiThreadTest public void setup() { MockitoAnnotations.initMocks(this); final ShellExecutor mockExecutor = mock(ShellExecutor.class); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java index 1a30f164f9a85..0916dd1f71bd9 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java @@ -62,6 +62,7 @@ public final class StageTaskListenerTests { @Mock private SyncTransactionQueue mSyncQueue; @Captor private ArgumentCaptor mRunnableCaptor; private SurfaceSession mSurfaceSession = new SurfaceSession(); + private SurfaceControl mSurfaceControl; private ActivityManager.RunningTaskInfo mRootTask; private StageTaskListener mStageTaskListener; @@ -76,7 +77,8 @@ public final class StageTaskListenerTests { mSurfaceSession); mRootTask = new TestRunningTaskInfoBuilder().build(); mRootTask.parentTaskId = INVALID_TASK_ID; - mStageTaskListener.onTaskAppeared(mRootTask, new SurfaceControl()); + mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession).setName("test").build(); + mStageTaskListener.onTaskAppeared(mRootTask, mSurfaceControl); } @Test @@ -103,7 +105,7 @@ public final class StageTaskListenerTests { final ActivityManager.RunningTaskInfo childTask = new TestRunningTaskInfoBuilder().setParentTaskId(mRootTask.taskId).build(); - mStageTaskListener.onTaskAppeared(childTask, new SurfaceControl()); + mStageTaskListener.onTaskAppeared(childTask, mSurfaceControl); assertThat(mStageTaskListener.mChildrenTaskInfo.contains(childTask.taskId)).isTrue(); verify(mCallbacks).onStatusChanged(eq(mRootTask.isVisible), eq(true));