Merge "SurfaceView: Ensure the Surface remains valid with SurfaceHolder#lockCanvas"

This commit is contained in:
Vishnu Nair
2022-07-25 17:04:42 +00:00
committed by Android (Google) Code Review

View File

@@ -119,6 +119,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
final int[] mLocation = new int[2];
@UnsupportedAppUsage
// Used to ensure the Surface remains valid between SurfaceHolder#lockCanvas and
// SurfaceHolder#unlockCanvasAndPost calls. This prevents SurfaceView from destroying or
// invalidating the Surface. This means this lock should be acquired when destroying the
// BlastBufferQueue.
final ReentrantLock mSurfaceLock = new ReentrantLock();
@UnsupportedAppUsage
final Surface mSurface = new Surface(); // Current surface in use
@@ -724,14 +728,18 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
private void releaseSurfaces(boolean releaseSurfacePackage) {
mSurfaceAlpha = 1f;
mSurface.destroy();
synchronized (mSurfaceControlLock) {
try {
mSurfaceLock.lock();
mSurface.destroy();
if (mBlastBufferQueue != null) {
mBlastBufferQueue.destroy();
mBlastBufferQueue = null;
}
} finally {
mSurfaceLock.unlock();
}
synchronized (mSurfaceControlLock) {
final Transaction transaction = new Transaction();
if (mSurfaceControl != null) {
transaction.remove(mSurfaceControl);
@@ -1232,16 +1240,21 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
.build();
}
// Always recreate the IGBP for compatibility. This can be optimized in the future but
// the behavior change will need to be gated by SDK version.
if (mBlastBufferQueue != null) {
mBlastBufferQueue.destroy();
}
mTransformHint = viewRoot.getBufferTransformHint();
mBlastSurfaceControl.setTransformHint(mTransformHint);
mBlastBufferQueue = new BLASTBufferQueue(name, false /* updateDestinationFrame */);
mBlastBufferQueue.update(mBlastSurfaceControl, mSurfaceWidth, mSurfaceHeight, mFormat);
// Always recreate the IGBP for compatibility. This can be optimized in the future but
// the behavior change will need to be gated by SDK version.
try {
mSurfaceLock.lock();
if (mBlastBufferQueue != null) {
mBlastBufferQueue.destroy();
}
mBlastBufferQueue = new BLASTBufferQueue(name, false /* updateDestinationFrame */);
mBlastBufferQueue.update(mBlastSurfaceControl, mSurfaceWidth, mSurfaceHeight, mFormat);
} finally {
mSurfaceLock.unlock();
}
mBlastBufferQueue.setTransactionHangCallback(ViewRootImpl.sTransactionHangCallback);
}
@@ -1814,7 +1827,14 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
// so the next connect will always work if we end up reusing
// the surface.
if (mSurface.isValid()) {
mSurface.forceScopedDisconnect();
// We need to grab this lock since mSurface.forceScopedDisconnect
// will free buffers from the queue.
try {
mSurfaceLock.lock();
mSurface.forceScopedDisconnect();
} finally {
mSurfaceLock.unlock();
}
}
}
}