summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/SurfaceControlViewHost.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java58
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java49
7 files changed, 112 insertions, 42 deletions
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 16c133523303..659dba3be13f 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -407,6 +407,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
* screen. It will be laid as if it were in a window of the passed in width and height.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 8e8facadfd5d..e8a6a159cb19 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -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);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index dfde7e6feff5..116af7094e13 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -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
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 5226eeebcaa2..0844948e56e3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -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
@@ -780,7 +780,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);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 67e99d73b811..af3fb0ead55c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -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
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 8b35694ff8fd..9a1b4ffbd50c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -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;
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index c1e53a90b7e0..fc4bfd9754a0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -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);
}