Use passed in Transaction when creating bounds layer in VRI

When the bounds layer is created, the visibility and initial bounds are set
using a new transaction that is applied immediately. This can cause a
race condition because the initial bounds are sent using a different
apply token than the buffer updates. When the crop for the bounds layer is
updated, that is sent in sync with the BBQ frame which has a separate
apply token. This means the updated bounds can be applied before the
intial bounds, causing unexpected behavior.

Test: testCropWithChildBoundingInsets 100 times
Bug: 288339794
Change-Id: I61776050e99d8fa9524a7b6e4fe6034c171d49a7
This commit is contained in:
Chavi Weingarten
2023-06-29 16:26:30 +00:00
parent 7baeec3cac
commit 215c18cfc8
2 changed files with 9 additions and 8 deletions

View File

@@ -1340,7 +1340,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
.setName(name)
.setLocalOwnerView(this)
.setParent(viewRoot.getBoundsLayer())
.setParent(viewRoot.updateAndGetBoundsLayer(surfaceUpdateTransaction))
.setCallsite("SurfaceView.updateSurface")
.setContainerLayer()
.build();

View File

@@ -716,9 +716,9 @@ public final class ViewRootImpl implements ViewParent,
/**
* Child container layer of {@code mSurface} with the same bounds as its parent, and cropped to
* the surface insets. This surface is created only if a client requests it via {@link
* #getBoundsLayer()}. By parenting to this bounds surface, child surfaces can ensure they do
* not draw into the surface inset region set by the parent window.
* the surface insets. This surface is created only if a client requests it via
* {@link #updateAndGetBoundsLayer(Transaction)}. By parenting to this bounds surface, child
* surfaces can ensure they do not draw into the surface inset region set by the parent window.
*/
private SurfaceControl mBoundsLayer;
private final SurfaceSession mSurfaceSession = new SurfaceSession();
@@ -2262,7 +2262,7 @@ public final class ViewRootImpl implements ViewParent,
* <p>Parenting to this layer will ensure that its children are cropped by the view's surface
* insets.
*/
public SurfaceControl getBoundsLayer() {
public SurfaceControl updateAndGetBoundsLayer(Transaction t) {
if (mBoundsLayer == null) {
mBoundsLayer = new SurfaceControl.Builder(mSurfaceSession)
.setContainerLayer()
@@ -2270,8 +2270,8 @@ public final class ViewRootImpl implements ViewParent,
.setParent(getSurfaceControl())
.setCallsite("ViewRootImpl.getBoundsLayer")
.build();
setBoundsLayerCrop(mTransaction);
mTransaction.show(mBoundsLayer).apply();
setBoundsLayerCrop(t);
t.show(mBoundsLayer);
}
return mBoundsLayer;
}
@@ -11180,7 +11180,8 @@ public final class ViewRootImpl implements ViewParent,
@Nullable public SurfaceControl.Transaction buildReparentTransaction(
@NonNull SurfaceControl child) {
if (mSurfaceControl.isValid()) {
return new SurfaceControl.Transaction().reparent(child, getBoundsLayer());
Transaction t = new Transaction();
return t.reparent(child, updateAndGetBoundsLayer(t));
}
return null;
}