Merge "Apply the window decor transaction in sync with the View's draw" into udc-dev
This commit is contained in:
@@ -409,6 +409,13 @@ public class SurfaceControlViewHost {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public @NonNull AttachedSurfaceControl getRootSurfaceControl() {
|
||||
return mViewRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the root view of the SurfaceControlViewHost. This view will render in to
|
||||
* the SurfaceControl, and receive input based on the SurfaceControls positioning on
|
||||
|
||||
@@ -127,7 +127,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
||||
if (decoration == null) {
|
||||
createWindowDecoration(taskInfo, taskSurface, startT, finishT);
|
||||
} else {
|
||||
decoration.relayout(taskInfo, startT, finishT);
|
||||
decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
||||
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
|
||||
if (decoration == null) return;
|
||||
|
||||
decoration.relayout(taskInfo, startT, finishT);
|
||||
decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -192,7 +192,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
||||
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
||||
windowDecoration.setDragPositioningCallback(taskPositioner);
|
||||
windowDecoration.setDragDetector(touchEventListener.mDragDetector);
|
||||
windowDecoration.relayout(taskInfo, startT, finishT);
|
||||
windowDecoration.relayout(taskInfo, startT, finishT,
|
||||
false /* applyStartTransactionOnDraw */);
|
||||
setupCaptionColor(taskInfo, windowDecoration);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,15 +90,15 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
||||
@Override
|
||||
void relayout(RunningTaskInfo taskInfo) {
|
||||
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
relayout(taskInfo, t, t);
|
||||
mSyncQueue.runInSync(transaction -> {
|
||||
transaction.merge(t);
|
||||
t.close();
|
||||
});
|
||||
// Use |applyStartTransactionOnDraw| so that the transaction (that applies task crop) is
|
||||
// synced with the buffer transaction (that draws the View). Both will be shown on screen
|
||||
// at the same, whereas applying them independently causes flickering. See b/270202228.
|
||||
relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */);
|
||||
}
|
||||
|
||||
void relayout(RunningTaskInfo taskInfo,
|
||||
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
|
||||
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
|
||||
boolean applyStartTransactionOnDraw) {
|
||||
final int shadowRadiusID = taskInfo.isFocused
|
||||
? R.dimen.freeform_decor_shadow_focused_thickness
|
||||
: R.dimen.freeform_decor_shadow_unfocused_thickness;
|
||||
@@ -115,6 +115,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
||||
mRelayoutParams.mLayoutResId = R.layout.caption_window_decor;
|
||||
mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
|
||||
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
|
||||
mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
|
||||
|
||||
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
|
||||
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
|
||||
|
||||
@@ -247,7 +247,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
|
||||
if (decoration == null) {
|
||||
createWindowDecoration(taskInfo, taskSurface, startT, finishT);
|
||||
} else {
|
||||
decoration.relayout(taskInfo, startT, finishT);
|
||||
decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
|
||||
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
|
||||
if (decoration == null) return;
|
||||
|
||||
decoration.relayout(taskInfo, startT, finishT);
|
||||
decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -781,7 +781,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
|
||||
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
||||
windowDecoration.setDragPositioningCallback(taskPositioner);
|
||||
windowDecoration.setDragDetector(touchEventListener.mDragDetector);
|
||||
windowDecoration.relayout(taskInfo, startT, finishT);
|
||||
windowDecoration.relayout(taskInfo, startT, finishT,
|
||||
false /* applyStartTransactionOnDraw */);
|
||||
incrementEventReceiverTasks(taskInfo.displayId);
|
||||
}
|
||||
|
||||
|
||||
@@ -173,15 +173,15 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
|
||||
@Override
|
||||
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
relayout(taskInfo, t, t);
|
||||
mSyncQueue.runInSync(transaction -> {
|
||||
transaction.merge(t);
|
||||
t.close();
|
||||
});
|
||||
// Use |applyStartTransactionOnDraw| so that the transaction (that applies task crop) is
|
||||
// synced with the buffer transaction (that draws the View). Both will be shown on screen
|
||||
// at the same, whereas applying them independently causes flickering. See b/270202228.
|
||||
relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */);
|
||||
}
|
||||
|
||||
void relayout(ActivityManager.RunningTaskInfo taskInfo,
|
||||
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
|
||||
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
|
||||
boolean applyStartTransactionOnDraw) {
|
||||
final int shadowRadiusID = taskInfo.isFocused
|
||||
? R.dimen.freeform_decor_shadow_focused_thickness
|
||||
: R.dimen.freeform_decor_shadow_unfocused_thickness;
|
||||
@@ -216,6 +216,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
|
||||
mRelayoutParams.mLayoutResId = windowDecorLayoutId;
|
||||
mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
|
||||
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
|
||||
mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
|
||||
|
||||
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
|
||||
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
|
||||
|
||||
@@ -238,30 +238,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
||||
startT.setWindowCrop(mCaptionContainerSurface, captionWidth, captionHeight)
|
||||
.show(mCaptionContainerSurface);
|
||||
|
||||
if (mCaptionWindowManager == null) {
|
||||
// Put caption under a container surface because ViewRootImpl sets the destination frame
|
||||
// of windowless window layers and BLASTBufferQueue#update() doesn't support offset.
|
||||
mCaptionWindowManager = new WindowlessWindowManager(
|
||||
mTaskInfo.getConfiguration(), mCaptionContainerSurface,
|
||||
null /* hostInputToken */);
|
||||
}
|
||||
|
||||
// Caption view
|
||||
mCaptionWindowManager.setConfiguration(taskConfig);
|
||||
final WindowManager.LayoutParams lp =
|
||||
new WindowManager.LayoutParams(captionWidth, captionHeight,
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
|
||||
lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
|
||||
lp.setTrustedOverlay();
|
||||
if (mViewHost == null) {
|
||||
mViewHost = mSurfaceControlViewHostFactory.create(mDecorWindowContext, mDisplay,
|
||||
mCaptionWindowManager);
|
||||
mViewHost.setView(outResult.mRootView, lp);
|
||||
} else {
|
||||
mViewHost.relayout(lp);
|
||||
}
|
||||
|
||||
if (ViewRootImpl.CAPTION_ON_SHELL) {
|
||||
outResult.mRootView.setTaskFocusState(mTaskInfo.isFocused);
|
||||
|
||||
@@ -287,6 +263,36 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
||||
.show(mTaskSurface);
|
||||
finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
|
||||
.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
|
||||
|
||||
if (mCaptionWindowManager == null) {
|
||||
// Put caption under a container surface because ViewRootImpl sets the destination frame
|
||||
// of windowless window layers and BLASTBufferQueue#update() doesn't support offset.
|
||||
mCaptionWindowManager = new WindowlessWindowManager(
|
||||
mTaskInfo.getConfiguration(), mCaptionContainerSurface,
|
||||
null /* hostInputToken */);
|
||||
}
|
||||
|
||||
// Caption view
|
||||
mCaptionWindowManager.setConfiguration(taskConfig);
|
||||
final WindowManager.LayoutParams lp =
|
||||
new WindowManager.LayoutParams(captionWidth, captionHeight,
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
|
||||
lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
|
||||
lp.setTrustedOverlay();
|
||||
if (mViewHost == null) {
|
||||
mViewHost = mSurfaceControlViewHostFactory.create(mDecorWindowContext, mDisplay,
|
||||
mCaptionWindowManager);
|
||||
if (params.mApplyStartTransactionOnDraw) {
|
||||
mViewHost.getRootSurfaceControl().applyTransactionOnDraw(startT);
|
||||
}
|
||||
mViewHost.setView(outResult.mRootView, lp);
|
||||
} else {
|
||||
if (params.mApplyStartTransactionOnDraw) {
|
||||
mViewHost.getRootSurfaceControl().applyTransactionOnDraw(startT);
|
||||
}
|
||||
mViewHost.relayout(lp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -411,6 +417,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
||||
int mCaptionX;
|
||||
int mCaptionY;
|
||||
|
||||
boolean mApplyStartTransactionOnDraw;
|
||||
|
||||
void reset() {
|
||||
mLayoutResId = Resources.ID_NULL;
|
||||
mCaptionHeightId = Resources.ID_NULL;
|
||||
@@ -419,6 +427,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
||||
|
||||
mCaptionX = 0;
|
||||
mCaptionY = 0;
|
||||
|
||||
mApplyStartTransactionOnDraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.same;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
@@ -42,6 +43,7 @@ import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.AttachedSurfaceControl;
|
||||
import android.view.Display;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControlViewHost;
|
||||
@@ -97,6 +99,8 @@ public class WindowDecorationTests extends ShellTestCase {
|
||||
@Mock
|
||||
private SurfaceControlViewHost mMockSurfaceControlViewHost;
|
||||
@Mock
|
||||
private AttachedSurfaceControl mMockRootSurfaceControl;
|
||||
@Mock
|
||||
private TestView mMockView;
|
||||
@Mock
|
||||
private WindowContainerTransaction mMockWindowContainerTransaction;
|
||||
@@ -129,6 +133,8 @@ public class WindowDecorationTests extends ShellTestCase {
|
||||
|
||||
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
|
||||
.create(any(), any(), any());
|
||||
when(mMockSurfaceControlViewHost.getRootSurfaceControl())
|
||||
.thenReturn(mMockRootSurfaceControl);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -461,6 +467,43 @@ public class WindowDecorationTests extends ShellTestCase {
|
||||
verify(mMockSurfaceControlStartT).show(captionContainerSurface);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRelayout_applyTransactionInSyncWithDraw() {
|
||||
final Display defaultDisplay = mock(Display.class);
|
||||
doReturn(defaultDisplay).when(mMockDisplayController)
|
||||
.getDisplay(Display.DEFAULT_DISPLAY);
|
||||
|
||||
final SurfaceControl decorContainerSurface = mock(SurfaceControl.class);
|
||||
final SurfaceControl.Builder decorContainerSurfaceBuilder =
|
||||
createMockSurfaceControlBuilder(decorContainerSurface);
|
||||
mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder);
|
||||
final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
|
||||
final SurfaceControl.Builder captionContainerSurfaceBuilder =
|
||||
createMockSurfaceControlBuilder(captionContainerSurface);
|
||||
mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
|
||||
|
||||
final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
|
||||
mMockSurfaceControlTransactions.add(t);
|
||||
final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
|
||||
new ActivityManager.TaskDescription.Builder()
|
||||
.setBackgroundColor(Color.YELLOW);
|
||||
final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
|
||||
.setDisplayId(Display.DEFAULT_DISPLAY)
|
||||
.setTaskDescriptionBuilder(taskDescriptionBuilder)
|
||||
.setBounds(TASK_BOUNDS)
|
||||
.setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
|
||||
.setVisible(true)
|
||||
.build();
|
||||
taskInfo.isFocused = true;
|
||||
taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
|
||||
final SurfaceControl taskSurface = mock(SurfaceControl.class);
|
||||
final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
|
||||
|
||||
windowDecor.relayout(taskInfo, true /* applyStartTransactionOnDraw */);
|
||||
|
||||
verify(mMockRootSurfaceControl).applyTransactionOnDraw(mMockSurfaceControlStartT);
|
||||
}
|
||||
|
||||
private TestWindowDecoration createWindowDecoration(
|
||||
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
|
||||
return new TestWindowDecoration(InstrumentationRegistry.getInstrumentation().getContext(),
|
||||
@@ -516,6 +559,12 @@ public class WindowDecorationTests extends ShellTestCase {
|
||||
|
||||
@Override
|
||||
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
relayout(taskInfo, false /* applyStartTransactionOnDraw */);
|
||||
}
|
||||
|
||||
void relayout(ActivityManager.RunningTaskInfo taskInfo,
|
||||
boolean applyStartTransactionOnDraw) {
|
||||
mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
|
||||
relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT,
|
||||
mMockWindowContainerTransaction, mMockView, mRelayoutResult);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user