summaryrefslogtreecommitdiff
path: root/core/java/android/view/SurfaceView.java
diff options
context:
space:
mode:
authorVishnu Nair <vishnun@google.com>2021-09-09 19:56:40 -0700
committerVishnu Nair <vishnun@google.com>2021-09-13 17:21:06 +0000
commit28ab86f0d47aa008258f368fde2506ac0ea108cc (patch)
tree49c5a0f438aa2ee4f177406587ef795648c4beb5 /core/java/android/view/SurfaceView.java
parent6c740e9394f761ba98aa94bd99068051c0045906 (diff)
SurfaceView: Fix SurfaceControl synchronization issues
Hold the surface control lock in PositionUpdateListener callbacks before checking if the SurfaceControl will be null. UI tread might release it after the checks causing crashes. Also fix a case where the ViewRootImpl may be null in the positionChanged callback. Bug: 199261027 Test: run steps in bug Test: go/wm-smoke Change-Id: I5a4cac35fe14356389b29268fddf9703b25c03aa (cherry picked from commit 2cafd8b44d0b4c13b16fdcd2557352ec5496fcc3)
Diffstat (limited to 'core/java/android/view/SurfaceView.java')
-rw-r--r--core/java/android/view/SurfaceView.java38
1 files changed, 20 insertions, 18 deletions
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 51910e09735d..60bb99d37c39 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1464,19 +1464,18 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
@Override
public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
- if (mSurfaceControl == null) {
- return;
- }
-
- // TODO: This is teensy bit racey in that a brand new SurfaceView moving on
- // its 2nd frame if RenderThread is running slowly could potentially see
- // this as false, enter the branch, get pre-empted, then this comes along
- // and reports a new position, then the UI thread resumes and reports
- // its position. This could therefore be de-sync'd in that interval, but
- // the synchronization would violate the rule that RT must never block
- // on the UI thread which would open up potential deadlocks. The risk of
- // a single-frame desync is therefore preferable for now.
synchronized(mSurfaceControlLock) {
+ if (mSurfaceControl == null) {
+ return;
+ }
+ // TODO: This is teensy bit racey in that a brand new SurfaceView moving on
+ // its 2nd frame if RenderThread is running slowly could potentially see
+ // this as false, enter the branch, get pre-empted, then this comes along
+ // and reports a new position, then the UI thread resumes and reports
+ // its position. This could therefore be de-sync'd in that interval, but
+ // the synchronization would violate the rule that RT must never block
+ // on the UI thread which would open up potential deadlocks. The risk of
+ // a single-frame desync is therefore preferable for now.
mRtHandlingPositionUpdates = true;
}
if (mRTLastReportedPosition.left == left
@@ -1506,8 +1505,11 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
if (mViewVisibility) {
mPositionChangedTransaction.show(mSurfaceControl);
}
- applyChildSurfaceTransaction_renderWorker(mPositionChangedTransaction,
- getViewRootImpl().mSurface, frameNumber);
+ final ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot != null) {
+ applyChildSurfaceTransaction_renderWorker(mPositionChangedTransaction,
+ viewRoot.mSurface, frameNumber);
+ }
applyOrMergeTransaction(mPositionChangedTransaction, frameNumber);
mPendingTransaction = false;
} catch (Exception ex) {
@@ -1528,7 +1530,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
@Override
public void positionLost(long frameNumber) {
- if (DEBUG) {
+ if (DEBUG_POSITION) {
Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
System.identityHashCode(this), frameNumber));
}
@@ -1540,15 +1542,15 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mPositionChangedTransaction.clear();
mPendingTransaction = false;
}
- if (mSurfaceControl == null) {
- return;
- }
/**
* positionLost can be called while UI thread is un-paused so we
* need to hold the lock here.
*/
synchronized (mSurfaceControlLock) {
+ if (mSurfaceControl == null) {
+ return;
+ }
mRtTransaction.hide(mSurfaceControl);
if (mRtReleaseSurfaces) {
mRtReleaseSurfaces = false;