Merge "SurfaceView: Synchronize all surface view changes with VRI draw" into tm-dev

This commit is contained in:
Chavi Weingarten
2022-03-03 17:57:05 +00:00
committed by Android (Google) Code Review
2 changed files with 78 additions and 109 deletions

View File

@@ -133,9 +133,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
private boolean mDisableBackgroundLayer = false; private boolean mDisableBackgroundLayer = false;
/** /**
* We use this lock to protect access to mSurfaceControl and * We use this lock to protect access to mSurfaceControl. Both are accessed on the UI
* SurfaceViewPositionUpdateListener#mPositionChangedTransaction. Both are accessed on the UI * thread and the render thread via RenderNode.PositionUpdateListener#positionLost.
* thread and the render thread.
*/ */
final Object mSurfaceControlLock = new Object(); final Object mSurfaceControlLock = new Object();
final Rect mTmpRect = new Rect(); final Rect mTmpRect = new Rect();
@@ -224,12 +223,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
private final SurfaceControl.Transaction mFrameCallbackTransaction = private final SurfaceControl.Transaction mFrameCallbackTransaction =
new SurfaceControl.Transaction(); new SurfaceControl.Transaction();
/**
* A temporary transaction holder that should only be used when applying right away. There
* should be no assumption about thread safety for this transaction.
*/
private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
private int mParentSurfaceSequenceId; private int mParentSurfaceSequenceId;
private RemoteAccessibilityController mRemoteAccessibilityController = private RemoteAccessibilityController mRemoteAccessibilityController =
@@ -760,7 +753,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mBlastBufferQueue = null; mBlastBufferQueue = null;
} }
Transaction transaction = new Transaction(); final Transaction transaction = new Transaction();
if (mSurfaceControl != null) { if (mSurfaceControl != null) {
transaction.remove(mSurfaceControl); transaction.remove(mSurfaceControl);
mSurfaceControl = null; mSurfaceControl = null;
@@ -790,22 +783,17 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
// synchronously otherwise we may see flickers. // synchronously otherwise we may see flickers.
// When the listener is updated, we will get at least a single position update call so we can // When the listener is updated, we will get at least a single position update call so we can
// guarantee any changes we post will be applied. // guarantee any changes we post will be applied.
private void replacePositionUpdateListener(int surfaceWidth, int surfaceHeight, private void replacePositionUpdateListener(int surfaceWidth, int surfaceHeight) {
Transaction geometryTransaction) {
if (mPositionListener != null) { if (mPositionListener != null) {
mRenderNode.removePositionUpdateListener(mPositionListener); mRenderNode.removePositionUpdateListener(mPositionListener);
synchronized (mSurfaceControlLock) {
geometryTransaction = mPositionListener.getTransaction().merge(geometryTransaction);
} }
} mPositionListener = new SurfaceViewPositionUpdateListener(surfaceWidth, surfaceHeight);
mPositionListener = new SurfaceViewPositionUpdateListener(surfaceWidth, surfaceHeight,
geometryTransaction);
mRenderNode.addPositionUpdateListener(mPositionListener); mRenderNode.addPositionUpdateListener(mPositionListener);
} }
private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator, private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
boolean creating, boolean sizeChanged, boolean hintChanged, boolean creating, boolean sizeChanged, boolean hintChanged,
Transaction geometryTransaction) { Transaction surfaceUpdateTransaction) {
boolean realSizeChanged = false; boolean realSizeChanged = false;
mSurfaceLock.lock(); mSurfaceLock.lock();
@@ -820,59 +808,60 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
// SurfaceChangedCallback to update the relative z. This is needed so that // SurfaceChangedCallback to update the relative z. This is needed so that
// we do not change the relative z before the server is ready to swap the // we do not change the relative z before the server is ready to swap the
// parent surface. // parent surface.
if (creating || (mParentSurfaceSequenceId == viewRoot.getSurfaceSequenceId())) { if (creating) {
updateRelativeZ(mTmpTransaction); updateRelativeZ(surfaceUpdateTransaction);
if (mSurfacePackage != null) {
reparentSurfacePackage(surfaceUpdateTransaction, mSurfacePackage);
}
} }
mParentSurfaceSequenceId = viewRoot.getSurfaceSequenceId(); mParentSurfaceSequenceId = viewRoot.getSurfaceSequenceId();
if (mViewVisibility) { if (mViewVisibility) {
geometryTransaction.show(mSurfaceControl); surfaceUpdateTransaction.show(mSurfaceControl);
} else { } else {
geometryTransaction.hide(mSurfaceControl); surfaceUpdateTransaction.hide(mSurfaceControl);
} }
if (mSurfacePackage != null) {
reparentSurfacePackage(mTmpTransaction, mSurfacePackage);
}
updateBackgroundVisibility(mTmpTransaction);
updateBackgroundColor(mTmpTransaction); updateBackgroundVisibility(surfaceUpdateTransaction);
updateBackgroundColor(surfaceUpdateTransaction);
if (mUseAlpha) { if (mUseAlpha) {
float alpha = getFixedAlpha(); float alpha = getFixedAlpha();
mTmpTransaction.setAlpha(mSurfaceControl, alpha); surfaceUpdateTransaction.setAlpha(mSurfaceControl, alpha);
mSurfaceAlpha = alpha; mSurfaceAlpha = alpha;
} }
geometryTransaction.setCornerRadius(mSurfaceControl, mCornerRadius); surfaceUpdateTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
if ((sizeChanged || hintChanged) && !creating) { if ((sizeChanged || hintChanged) && !creating) {
setBufferSize(geometryTransaction); setBufferSize(surfaceUpdateTransaction);
} }
if (sizeChanged || creating || !isHardwareAccelerated()) { if (sizeChanged || creating || !isHardwareAccelerated()) {
onSetSurfacePositionAndScaleRT(geometryTransaction, mSurfaceControl,
mScreenRect.left, /*positionLeft*/
mScreenRect.top /*positionTop*/ ,
mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
// Set a window crop when creating the surface or changing its size to // Set a window crop when creating the surface or changing its size to
// crop the buffer to the surface size since the buffer producer may // crop the buffer to the surface size since the buffer producer may
// use SCALING_MODE_SCALE and submit a larger size than the surface // use SCALING_MODE_SCALE and submit a larger size than the surface
// size. // size.
if (mClipSurfaceToBounds && mClipBounds != null) { if (mClipSurfaceToBounds && mClipBounds != null) {
geometryTransaction.setWindowCrop(mSurfaceControl, mClipBounds); surfaceUpdateTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
} else { } else {
geometryTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth, surfaceUpdateTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
mSurfaceHeight); mSurfaceHeight);
} }
geometryTransaction.setDesintationFrame(mBlastSurfaceControl, mSurfaceWidth, surfaceUpdateTransaction.setDesintationFrame(mBlastSurfaceControl, mSurfaceWidth,
mSurfaceHeight); mSurfaceHeight);
if (isHardwareAccelerated()) { if (isHardwareAccelerated()) {
// This will consume the passed in transaction and the transaction will be // This will consume the passed in transaction and the transaction will be
// applied on a render worker thread. // applied on a render worker thread.
replacePositionUpdateListener(mSurfaceWidth, mSurfaceHeight, replacePositionUpdateListener(mSurfaceWidth, mSurfaceHeight);
geometryTransaction); } else {
onSetSurfacePositionAndScale(surfaceUpdateTransaction, mSurfaceControl,
mScreenRect.left /*positionLeft*/,
mScreenRect.top /*positionTop*/,
mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
} }
if (DEBUG_POSITION) { if (DEBUG_POSITION) {
Log.d(TAG, String.format( Log.d(TAG, String.format(
@@ -884,8 +873,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mScreenRect.bottom, mSurfaceWidth, mSurfaceHeight)); mScreenRect.bottom, mSurfaceWidth, mSurfaceHeight));
} }
} }
mTmpTransaction.merge(geometryTransaction); applyTransactionOnVriDraw(surfaceUpdateTransaction);
mTmpTransaction.apply();
updateEmbeddedAccessibilityMatrix(); updateEmbeddedAccessibilityMatrix();
mSurfaceFrame.left = 0; mSurfaceFrame.left = 0;
@@ -993,17 +981,17 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mScreenRect.offset(surfaceInsets.left, surfaceInsets.top); mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
// Collect all geometry changes and apply these changes on the RenderThread worker // Collect all geometry changes and apply these changes on the RenderThread worker
// via the RenderNode.PositionUpdateListener. // via the RenderNode.PositionUpdateListener.
final Transaction geometryTransaction = new Transaction(); final Transaction surfaceUpdateTransaction = new Transaction();
if (creating) { if (creating) {
updateOpaqueFlag(); updateOpaqueFlag();
final String name = "SurfaceView[" + viewRoot.getTitle().toString() + "]"; final String name = "SurfaceView[" + viewRoot.getTitle().toString() + "]";
createBlastSurfaceControls(viewRoot, name, geometryTransaction); createBlastSurfaceControls(viewRoot, name, surfaceUpdateTransaction);
} else if (mSurfaceControl == null) { } else if (mSurfaceControl == null) {
return; return;
} }
final boolean realSizeChanged = performSurfaceTransaction(viewRoot, final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
translator, creating, sizeChanged, hintChanged, geometryTransaction); translator, creating, sizeChanged, hintChanged, surfaceUpdateTransaction);
final boolean redrawNeeded = sizeChanged || creating || hintChanged final boolean redrawNeeded = sizeChanged || creating || hintChanged
|| (mVisible && !mDrawFinished); || (mVisible && !mDrawFinished);
@@ -1139,7 +1127,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
* *
*/ */
private void createBlastSurfaceControls(ViewRootImpl viewRoot, String name, private void createBlastSurfaceControls(ViewRootImpl viewRoot, String name,
Transaction geometryTransaction) { Transaction surfaceUpdateTransaction) {
if (mSurfaceControl == null) { if (mSurfaceControl == null) {
mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
.setName(name) .setName(name)
@@ -1162,11 +1150,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
.build(); .build();
} else { } else {
// update blast layer // update blast layer
mTmpTransaction surfaceUpdateTransaction
.setOpaque(mBlastSurfaceControl, (mSurfaceFlags & SurfaceControl.OPAQUE) != 0) .setOpaque(mBlastSurfaceControl, (mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
.setSecure(mBlastSurfaceControl, (mSurfaceFlags & SurfaceControl.SECURE) != 0) .setSecure(mBlastSurfaceControl, (mSurfaceFlags & SurfaceControl.SECURE) != 0)
.show(mBlastSurfaceControl) .show(mBlastSurfaceControl);
.apply();
} }
if (mBackgroundControl == null) { if (mBackgroundControl == null) {
@@ -1213,7 +1200,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
* *
* @hide * @hide
*/ */
protected void onSetSurfacePositionAndScaleRT(@NonNull Transaction transaction, protected void onSetSurfacePositionAndScale(@NonNull Transaction transaction,
@NonNull SurfaceControl surface, int positionLeft, int positionTop, @NonNull SurfaceControl surface, int positionLeft, int positionTop,
float postScaleX, float postScaleY) { float postScaleX, float postScaleY) {
transaction.setPosition(surface, positionLeft, positionTop); transaction.setPosition(surface, positionLeft, positionTop);
@@ -1226,12 +1213,14 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
if (mSurfaceControl == null) { if (mSurfaceControl == null) {
return; return;
} }
onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl, final Transaction transaction = new Transaction();
onSetSurfacePositionAndScale(transaction, mSurfaceControl,
mScreenRect.left, /*positionLeft*/ mScreenRect.left, /*positionLeft*/
mScreenRect.top/*positionTop*/ , mScreenRect.top/*positionTop*/ ,
mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/, mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/); mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
mTmpTransaction.apply(); applyTransactionOnVriDraw(transaction);
invalidate();
} }
/** /**
@@ -1253,39 +1242,28 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
} }
} }
private Rect mRTLastReportedPosition = new Rect(); private final Rect mRTLastReportedPosition = new Rect();
private Point mRTLastReportedSurfaceSize = new Point(); private final Point mRTLastReportedSurfaceSize = new Point();
private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener { private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener {
int mRtSurfaceWidth = -1; private final int mRtSurfaceWidth;
int mRtSurfaceHeight = -1; private final int mRtSurfaceHeight;
private final SurfaceControl.Transaction mPositionChangedTransaction = private final SurfaceControl.Transaction mPositionChangedTransaction =
new SurfaceControl.Transaction(); new SurfaceControl.Transaction();
boolean mPendingTransaction = false;
SurfaceViewPositionUpdateListener(int surfaceWidth, int surfaceHeight, SurfaceViewPositionUpdateListener(int surfaceWidth, int surfaceHeight) {
@Nullable Transaction t) {
mRtSurfaceWidth = surfaceWidth; mRtSurfaceWidth = surfaceWidth;
mRtSurfaceHeight = surfaceHeight; mRtSurfaceHeight = surfaceHeight;
if (t != null) {
mPositionChangedTransaction.merge(t);
mPendingTransaction = true;
}
} }
@Override @Override
public void positionChanged(long frameNumber, int left, int top, int right, int bottom) { public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
synchronized(mSurfaceControlLock) {
if (mSurfaceControl == null) {
return;
}
if (mRTLastReportedPosition.left == left if (mRTLastReportedPosition.left == left
&& mRTLastReportedPosition.top == top && mRTLastReportedPosition.top == top
&& mRTLastReportedPosition.right == right && mRTLastReportedPosition.right == right
&& mRTLastReportedPosition.bottom == bottom && mRTLastReportedPosition.bottom == bottom
&& mRTLastReportedSurfaceSize.x == mRtSurfaceWidth && mRTLastReportedSurfaceSize.x == mRtSurfaceWidth
&& mRTLastReportedSurfaceSize.y == mRtSurfaceHeight && mRTLastReportedSurfaceSize.y == mRtSurfaceHeight) {
&& !mPendingTransaction) {
return; return;
} }
try { try {
@@ -1296,9 +1274,11 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
System.identityHashCode(SurfaceView.this), frameNumber, System.identityHashCode(SurfaceView.this), frameNumber,
left, top, right, bottom, mRtSurfaceWidth, mRtSurfaceHeight)); left, top, right, bottom, mRtSurfaceWidth, mRtSurfaceHeight));
} }
synchronized (mSurfaceControlLock) {
if (mSurfaceControl == null) return;
mRTLastReportedPosition.set(left, top, right, bottom); mRTLastReportedPosition.set(left, top, right, bottom);
mRTLastReportedSurfaceSize.set(mRtSurfaceWidth, mRtSurfaceHeight); mRTLastReportedSurfaceSize.set(mRtSurfaceWidth, mRtSurfaceHeight);
onSetSurfacePositionAndScaleRT(mPositionChangedTransaction, mSurfaceControl, onSetSurfacePositionAndScale(mPositionChangedTransaction, mSurfaceControl,
mRTLastReportedPosition.left /*positionLeft*/, mRTLastReportedPosition.left /*positionLeft*/,
mRTLastReportedPosition.top /*positionTop*/, mRTLastReportedPosition.top /*positionTop*/,
mRTLastReportedPosition.width() mRTLastReportedPosition.width()
@@ -1306,15 +1286,15 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mRTLastReportedPosition.height() mRTLastReportedPosition.height()
/ (float) mRtSurfaceHeight /*postScaleY*/); / (float) mRtSurfaceHeight /*postScaleY*/);
if (mViewVisibility) { if (mViewVisibility) {
// b/131239825
mPositionChangedTransaction.show(mSurfaceControl); mPositionChangedTransaction.show(mSurfaceControl);
} }
}
applyOrMergeTransaction(mPositionChangedTransaction, frameNumber); applyOrMergeTransaction(mPositionChangedTransaction, frameNumber);
mPendingTransaction = false;
} catch (Exception ex) { } catch (Exception ex) {
Log.e(TAG, "Exception from repositionChild", ex); Log.e(TAG, "Exception from repositionChild", ex);
} }
} }
}
@Override @Override
public void applyStretch(long frameNumber, float width, float height, public void applyStretch(long frameNumber, float width, float height,
@@ -1336,28 +1316,14 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mRTLastReportedPosition.setEmpty(); mRTLastReportedPosition.setEmpty();
mRTLastReportedSurfaceSize.set(-1, -1); mRTLastReportedSurfaceSize.set(-1, -1);
/** // positionLost can be called while UI thread is un-paused.
* positionLost can be called while UI thread is un-paused so we
* need to hold the lock here.
*/
synchronized (mSurfaceControlLock) { synchronized (mSurfaceControlLock) {
if (mPendingTransaction) { if (mSurfaceControl == null) return;
Log.w(TAG, System.identityHashCode(SurfaceView.this) // b/131239825
+ "Pending transaction cleared.");
mPositionChangedTransaction.clear();
mPendingTransaction = false;
}
if (mSurfaceControl == null) {
return;
}
mRtTransaction.hide(mSurfaceControl); mRtTransaction.hide(mSurfaceControl);
applyOrMergeTransaction(mRtTransaction, frameNumber); applyOrMergeTransaction(mRtTransaction, frameNumber);
} }
} }
public Transaction getTransaction() {
return mPositionChangedTransaction;
}
} }
private SurfaceViewPositionUpdateListener mPositionListener = null; private SurfaceViewPositionUpdateListener mPositionListener = null;
@@ -1404,8 +1370,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
* @hide * @hide
*/ */
public void setResizeBackgroundColor(int bgColor) { public void setResizeBackgroundColor(int bgColor) {
setResizeBackgroundColor(mTmpTransaction, bgColor); final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
mTmpTransaction.apply(); setResizeBackgroundColor(transaction, bgColor);
applyTransactionOnVriDraw(transaction);
invalidate();
} }
/** /**

View File

@@ -230,8 +230,9 @@ public class InlineContentView extends ViewGroup {
int defStyleAttr, int defStyleRes) { int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
mSurfaceView = new SurfaceView(context, attrs, defStyleAttr, defStyleRes) { mSurfaceView = new SurfaceView(context, attrs, defStyleAttr, defStyleRes) {
// b/219807628
@Override @Override
protected void onSetSurfacePositionAndScaleRT( protected void onSetSurfacePositionAndScale(
@NonNull SurfaceControl.Transaction transaction, @NonNull SurfaceControl.Transaction transaction,
@NonNull SurfaceControl surface, int positionLeft, int positionTop, @NonNull SurfaceControl surface, int positionLeft, int positionTop,
float postScaleX, float postScaleY) { float postScaleX, float postScaleY) {
@@ -248,7 +249,7 @@ public class InlineContentView extends ViewGroup {
postScaleX = InlineContentView.this.getScaleX(); postScaleX = InlineContentView.this.getScaleX();
postScaleY = InlineContentView.this.getScaleY(); postScaleY = InlineContentView.this.getScaleY();
super.onSetSurfacePositionAndScaleRT(transaction, surface, positionLeft, super.onSetSurfacePositionAndScale(transaction, surface, positionLeft,
positionTop, postScaleX, postScaleY); positionTop, postScaleX, postScaleY);
} }
}; };