Merge "Set stage outline layer to top" into sc-v2-dev am: 152f01c18f

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

Change-Id: I40163c730f833921d2d3d611c8190fa4829b8600
This commit is contained in:
Tony Huang
2021-07-12 23:42:47 +00:00
committed by Automerger Merge Worker
5 changed files with 55 additions and 33 deletions

View File

@@ -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<SurfaceControl> 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<SurfaceControl> 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);

View File

@@ -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);
});
}
}
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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,