Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit edb6bdfa authored by Alec Mouri's avatar Alec Mouri
Browse files

Drive SurfaceView visibility on renderthread

In some scenarios, a SurfaceView:

1. May be moved offscreen by an app, such as through a ViewPager2
2. Have its RenderNode removed from the draw tree
3. The SurfaceView is remade visible on the UI thread

In this case, the view position is offscreen, but the SurfaceControl
position is at (0, 0). If there happens to be another SurfaceView at (0,
0), then this causes an accidental overlap.

To avoid this, visibility should be fully driven by RenderNode position
callbacks.

Bug: 269113414
Test: Test app with ViewPager2
Change-Id: Ia0abd56fe4be8b669d39864c5fc82e941fb3be8e
parent 3e49d76a
Loading
Loading
Loading
Loading
+11 −21
Original line number Diff line number Diff line
@@ -851,11 +851,15 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            }
            mParentSurfaceSequenceId = viewRoot.getSurfaceSequenceId();

            // Only control visibility if we're not hardware-accelerated. Otherwise we'll
            // let renderthread drive since offscreen SurfaceControls should not be visible.
            if (!isHardwareAccelerated()) {
                if (mViewVisibility) {
                    surfaceUpdateTransaction.show(mSurfaceControl);
                } else {
                    surfaceUpdateTransaction.hide(mSurfaceControl);
                }
            }

            updateBackgroundVisibility(surfaceUpdateTransaction);
            updateBackgroundColor(surfaceUpdateTransaction);
@@ -1417,12 +1421,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
    }

    private final Rect mRTLastReportedPosition = new Rect();
    private final Point mRTLastReportedSurfaceSize = new Point();

    private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener {
        private final int mRtSurfaceWidth;
        private final int mRtSurfaceHeight;
        private boolean mRtFirst = true;
        private final SurfaceControl.Transaction mPositionChangedTransaction =
                new SurfaceControl.Transaction();

@@ -1433,15 +1435,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall

        @Override
        public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
            if (!mRtFirst && (mRTLastReportedPosition.left == left
                    && mRTLastReportedPosition.top == top
                    && mRTLastReportedPosition.right == right
                    && mRTLastReportedPosition.bottom == bottom
                    && mRTLastReportedSurfaceSize.x == mRtSurfaceWidth
                    && mRTLastReportedSurfaceSize.y == mRtSurfaceHeight)) {
                return;
            }
            mRtFirst = false;
            try {
                if (DEBUG_POSITION) {
                    Log.d(TAG, String.format(
@@ -1452,8 +1445,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                }
                synchronized (mSurfaceControlLock) {
                    if (mSurfaceControl == null) return;

                    mRTLastReportedPosition.set(left, top, right, bottom);
                    mRTLastReportedSurfaceSize.set(mRtSurfaceWidth, mRtSurfaceHeight);
                    onSetSurfacePositionAndScale(mPositionChangedTransaction, mSurfaceControl,
                            mRTLastReportedPosition.left /*positionLeft*/,
                            mRTLastReportedPosition.top /*positionTop*/,
@@ -1461,11 +1454,9 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                                    / (float) mRtSurfaceWidth /*postScaleX*/,
                            mRTLastReportedPosition.height()
                                    / (float) mRtSurfaceHeight /*postScaleY*/);
                    if (mViewVisibility) {
                        // b/131239825

                    mPositionChangedTransaction.show(mSurfaceControl);
                }
                }
                applyOrMergeTransaction(mPositionChangedTransaction, frameNumber);
            } catch (Exception ex) {
                Log.e(TAG, "Exception from repositionChild", ex);
@@ -1490,7 +1481,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                        System.identityHashCode(this), frameNumber));
            }
            mRTLastReportedPosition.setEmpty();
            mRTLastReportedSurfaceSize.set(-1, -1);

            // positionLost can be called while UI thread is un-paused.
            synchronized (mSurfaceControlLock) {