From efbc8c102838ac20ec7116b60cd0dbbe0a4ac251 Mon Sep 17 00:00:00 2001 From: Tony Huang Date: Tue, 6 Jul 2021 14:22:21 +0800 Subject: [PATCH] Set stage outline layer to top Outline do not set layer before so it will show behind tasks layer then it will be invisible. Set its layer to top to ensure it's visible. Also fix context error message bug by replacing display context to window context. Fix: 192902371 Fix: 192527238 Test: Enable spilt and disable it many times and check outline display Test: Check ContextImpl log Change-Id: Ic1796965d7254d2276d4c05c662e940820c8d995 --- .../wm/shell/splitscreen/OutlineManager.java | 62 ++++++++++--------- .../wm/shell/splitscreen/SideStage.java | 17 ++++- .../shell/splitscreen/StageTaskListener.java | 2 +- .../wm/shell/splitscreen/SideStageTests.java | 3 +- .../splitscreen/SplitTransitionTests.java | 4 +- 5 files changed, 55 insertions(+), 33 deletions(-) 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 5d5a6e50341af..f74cb03424d67 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,6 +22,7 @@ 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; @@ -51,7 +52,8 @@ class OutlineManager extends WindowlessWindowManager { private final Rect mOutlineBounds = new Rect(); private final Rect mTmpBounds = new Rect(); private final Supplier mOutlineSurfaceSupplier; - private SurfaceControlViewHost mViewHost; + private final SurfaceControlViewHost mViewHost; + private final SurfaceControl mLeash; /** * Constructs {@link #OutlineManager} with indicated outline color for the provided root @@ -60,9 +62,27 @@ class OutlineManager extends WindowlessWindowManager { OutlineManager(Context context, Configuration configuration, Supplier outlineSurfaceSupplier, int color) { super(configuration, null /* rootSurface */, null /* hostInputToken */); - mContext = context.createDisplayContext(context.getDisplay()); + mContext = context.createWindowContext(context.getDisplay(), TYPE_APPLICATION_OVERLAY, + null /* options */); mOutlineSurfaceSupplier = outlineSurfaceSupplier; mOutlineColor = color; + + mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this); + final OutlineRoot rootView = (OutlineRoot) LayoutInflater.from(mContext) + .inflate(R.layout.split_outline, null); + rootView.updateOutlineBounds(mOutlineBounds, mOutlineColor); + + final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + 0 /* width */, 0 /* height */, TYPE_APPLICATION_OVERLAY, + FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT); + 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); + + mLeash = getSurfaceControl(mViewHost.getWindowToken()); } @Override @@ -77,37 +97,21 @@ class OutlineManager extends WindowlessWindowManager { } mOutlineBounds.set(mTmpBounds); - if (mViewHost == null) { - mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this); - } - if (mViewHost.getView() == null) { - final OutlineRoot rootView = (OutlineRoot) LayoutInflater.from(mContext) - .inflate(R.layout.split_outline, null); - rootView.updateOutlineBounds(mOutlineBounds, mOutlineColor); - - final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - rootBounds.width(), rootBounds.height(), - TYPE_APPLICATION_OVERLAY, - FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, - PixelFormat.TRANSLUCENT); - 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); - } else { - ((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); - } + ((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; } + @Nullable + SurfaceControl getLeash() { + return mLeash; + } + private static void computeOutlineBounds(Context context, Rect rootBounds, Rect outBounds) { computeDisplayStableBounds(context, outBounds); outBounds.intersect(rootBounds); 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 a0bdcc3edd5f1..5d29535ca2973 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 @@ -26,6 +26,7 @@ import android.view.SurfaceSession; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; +import com.android.internal.annotations.VisibleForTesting; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.SyncTransactionQueue; @@ -47,6 +48,14 @@ class SideStage extends StageTaskListener { mContext = context; } + @VisibleForTesting + SideStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId, + StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue, + SurfaceSession surfaceSession, OutlineManager outlineManager) { + this(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession); + mOutlineManager = outlineManager; + } + void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds, WindowContainerTransaction wct) { final WindowContainerToken rootToken = mRootTaskInfo.token; @@ -82,10 +91,16 @@ class SideStage extends StageTaskListener { @CallSuper public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { super.onTaskAppeared(taskInfo, leash); - if (mRootTaskInfo != null && mRootTaskInfo.taskId == taskInfo.taskId) { + if (mRootTaskInfo != null && mRootTaskInfo.taskId == taskInfo.taskId + && mOutlineManager == null) { mOutlineManager = new OutlineManager(mContext, mRootTaskInfo.configuration, () -> mRootLeash, Color.YELLOW); + if (mOutlineManager.getLeash() != null) { + mSyncQueue.runInSync(t -> { + t.setLayer(mOutlineManager.getLeash(), Integer.MAX_VALUE); + }); + } } } 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 0fd8eca6290e6..4f73feec750d2 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 @@ -71,8 +71,8 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } private final StageListenerCallbacks mCallbacks; - private final SyncTransactionQueue mSyncQueue; private final SurfaceSession mSurfaceSession; + protected final SyncTransactionQueue mSyncQueue; protected ActivityManager.RunningTaskInfo mRootTaskInfo; protected SurfaceControl mRootLeash; 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..2aad38f33efbe 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 @@ -53,6 +53,7 @@ public class SideStageTests extends ShellTestCase { @Mock private SyncTransactionQueue mSyncQueue; @Mock private ActivityManager.RunningTaskInfo mRootTask; @Mock private SurfaceControl mRootLeash; + @Mock private OutlineManager mOutlineManager; @Spy private WindowContainerTransaction mWct; private SurfaceSession mSurfaceSession = new SurfaceSession(); private SideStage mSideStage; @@ -62,7 +63,7 @@ public class SideStageTests extends ShellTestCase { MockitoAnnotations.initMocks(this); mRootTask = new TestRunningTaskInfoBuilder().build(); mSideStage = new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks, - mSyncQueue, mSurfaceSession); + mSyncQueue, mSurfaceSession, mOutlineManager); mSideStage.onTaskAppeared(mRootTask, mRootLeash); } 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 b6da8681d8503..44444ad255a3f 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 @@ -82,6 +82,7 @@ public class SplitTransitionTests extends ShellTestCase { @Mock private TransactionPool mTransactionPool; @Mock private Transitions mTransitions; @Mock private SurfaceSession mSurfaceSession; + @Mock private OutlineManager mOutlineManager; private SplitLayout mSplitLayout; private MainStage mMainStage; private SideStage mSideStage; @@ -103,7 +104,8 @@ public class SplitTransitionTests extends ShellTestCase { StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession); mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface()); mSideStage = new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock( - StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession); + StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession, + mOutlineManager); mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface()); mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage,