private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
        boolean creating, boolean sizeChanged, boolean hintChanged,
        Transaction geometryTransaction) {
    boolean realSizeChanged = false;

    mSurfaceLock.lock();
    try {
        mDrawingStopped = !mVisible;

        if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                + "Cur surface: " + mSurface);

        // If we are creating the surface control or the parent surface has not
        // changed, then set relative z. Otherwise allow the parent
        // 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
        // parent surface.
        if (creating || (mParentSurfaceSequenceId == viewRoot.getSurfaceSequenceId())) {
            updateRelativeZ(mTmpTransaction);
        }
        mParentSurfaceSequenceId = viewRoot.getSurfaceSequenceId();

        if (mViewVisibility) {
            geometryTransaction.show(mSurfaceControl);
        } else {
            geometryTransaction.hide(mSurfaceControl);
        }

        if (mSurfacePackage != null) {
            reparentSurfacePackage(mTmpTransaction, mSurfacePackage);
        }

        updateBackgroundVisibility(mTmpTransaction);
        updateBackgroundColor(mTmpTransaction);
        if (mUseAlpha) {
            float alpha = getFixedAlpha();
            mTmpTransaction.setAlpha(mSurfaceControl, alpha);
            mSurfaceAlpha = alpha;
        }

        geometryTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
        if ((sizeChanged || hintChanged) && !creating) {
            setBufferSize(geometryTransaction);
        }
        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
            // crop the buffer to the surface size since the buffer producer may
            // use SCALING_MODE_SCALE and submit a larger size than the surface
            // size.
            if (mClipSurfaceToBounds && mClipBounds != null) {
                geometryTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
            } else {
                geometryTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
                        mSurfaceHeight);
            }

            if (isHardwareAccelerated()) {
                // This will consume the passed in transaction and the transaction will be
                // applied on a render worker thread.
                replacePositionUpdateListener(mSurfaceWidth, mSurfaceHeight,
                        geometryTransaction);
            }
            if (DEBUG_POSITION) {
                Log.d(TAG, String.format(
                        "%d performSurfaceTransaction %s "
                            + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
                        System.identityHashCode(this),
                        isHardwareAccelerated() ? "RenderWorker" : "UI Thread",
                        mScreenRect.left, mScreenRect.top, mScreenRect.right,
                        mScreenRect.bottom, mSurfaceWidth, mSurfaceHeight));
            }
        }
        mTmpTransaction.merge(geometryTransaction);
        mTmpTransaction.apply();
        updateEmbeddedAccessibilityMatrix();

        mSurfaceFrame.left = 0;
        mSurfaceFrame.top = 0;
        if (translator == null) {
            mSurfaceFrame.right = mSurfaceWidth;
            mSurfaceFrame.bottom = mSurfaceHeight;
        } else {
            float appInvertedScale = translator.applicationInvertedScale;
            mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f);
            mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f);
        }
        final int surfaceWidth = mSurfaceFrame.right;
        final int surfaceHeight = mSurfaceFrame.bottom;
        realSizeChanged = mLastSurfaceWidth != surfaceWidth
                || mLastSurfaceHeight != surfaceHeight;
        mLastSurfaceWidth = surfaceWidth;
        mLastSurfaceHeight = surfaceHeight;
    } finally {
        mSurfaceLock.unlock();
    }
    return realSizeChanged;
}