diff options
| author | Robert Carr <racarr@google.com> | 2017-03-03 10:48:11 -0800 |
|---|---|---|
| committer | Robert Carr <racarr@google.com> | 2017-03-03 13:06:59 -0800 |
| commit | cd4aeef88052571365d4e193a2c41e2e6d145491 (patch) | |
| tree | 5c4a115dafe671bcd3b200013c73328243488a92 /core/java/android | |
| parent | 1ec752f2dac36b2bf32a9d3fdf5f1f022a09228c (diff) | |
Modify SurfaceView to use SurfaceFlinger child surfaces.
Here we have SurfaceView bypass the WindowManager and speak
directly to SurfaceFlinger using child surfaces. We also
implement some logic in the WM to handle child surfaces
in various Surface replacement scenarios.
For those following along in the revert Saga, this
also includes the follow up CLs to the original CL.
- Surface inset calculation
- Animation fixes.
The error causing revert was a deferTransactionUntil(-1)...-1
cast to uint, defer transaction until MAX_UINT.
Bug: 28858420
Bug: 31518219
Bug: 34888808
Bug: 35588318
Bug: 35396882
Test: Existing tests still pass (except for the ones that don't and will be deleted).
Change-Id: Ib37236950a1dd3c4f9f4b58fd41ef9003c0557ef
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 23 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceSession.java | 5 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 451 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 10 |
4 files changed, 220 insertions, 269 deletions
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index b718696b2202..519c1e2454df 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -95,6 +95,11 @@ public class SurfaceControl { IBinder displayToken, int mode); private static native void nativeDeferTransactionUntil(long nativeObject, IBinder handle, long frame); + private static native void nativeDeferTransactionUntilSurface(long nativeObject, + long surfaceObject, long frame); + private static native void nativeReparentChildren(long nativeObject, + IBinder handle); + private static native void nativeSeverChildren(long nativeObject); private static native void nativeSetOverrideScalingMode(long nativeObject, int scalingMode); private static native IBinder nativeGetHandle(long nativeObject); @@ -418,7 +423,23 @@ public class SurfaceControl { } public void deferTransactionUntil(IBinder handle, long frame) { - nativeDeferTransactionUntil(mNativeObject, handle, frame); + if (frame > 0) { + nativeDeferTransactionUntil(mNativeObject, handle, frame); + } + } + + public void deferTransactionUntil(Surface barrier, long frame) { + if (frame > 0) { + nativeDeferTransactionUntilSurface(mNativeObject, barrier.mNativeObject, frame); + } + } + + public void reparentChildren(IBinder newParentHandle) { + nativeReparentChildren(mNativeObject, newParentHandle); + } + + public void detachChildren() { + nativeSeverChildren(mNativeObject); } public void setOverrideScalingMode(int scalingMode) { diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java index 3cf5af484625..b5912bc1e1c8 100644 --- a/core/java/android/view/SurfaceSession.java +++ b/core/java/android/view/SurfaceSession.java @@ -27,6 +27,7 @@ public final class SurfaceSession { private long mNativeClient; // SurfaceComposerClient* private static native long nativeCreate(); + private static native long nativeCreateScoped(long surfacePtr); private static native void nativeDestroy(long ptr); private static native void nativeKill(long ptr); @@ -35,6 +36,10 @@ public final class SurfaceSession { mNativeClient = nativeCreate(); } + public SurfaceSession(Surface root) { + mNativeClient = nativeCreateScoped(root.mNativeObject); + } + /* no user serviceable parts here ... */ @Override protected void finalize() throws Throwable { diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index d2577d48c3d1..61b12475d542 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -16,6 +16,10 @@ package android.view; +import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_SUBLAYER; +import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_OVERLAY_SUBLAYER; +import static android.view.WindowManagerPolicy.APPLICATION_PANEL_SUBLAYER; + import android.content.Context; import android.content.res.CompatibilityInfo.Translator; import android.content.res.Configuration; @@ -26,16 +30,12 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.Handler; import android.os.Message; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; -import com.android.internal.view.BaseIWindow; import com.android.internal.view.SurfaceCallbackHelper; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.concurrent.locks.ReentrantLock; @@ -92,8 +92,8 @@ import java.util.concurrent.locks.ReentrantLock; * positioned asynchronously.</p> */ public class SurfaceView extends View { - static private final String TAG = "SurfaceView"; - static private final boolean DEBUG = false; + private static final String TAG = "SurfaceView"; + private static final boolean DEBUG = false; final ArrayList<SurfaceHolder.Callback> mCallbacks = new ArrayList<SurfaceHolder.Callback>(); @@ -102,28 +102,23 @@ public class SurfaceView extends View { final ReentrantLock mSurfaceLock = new ReentrantLock(); final Surface mSurface = new Surface(); // Current surface in use - final Surface mNewSurface = new Surface(); // New surface we are switching to boolean mDrawingStopped = true; + // We use this to track if the application has produced a frame + // in to the Surface. Up until that point, we should be careful not to punch + // holes. + boolean mDrawFinished = false; + + final Rect mScreenRect = new Rect(); + SurfaceSession mSurfaceSession; - final WindowManager.LayoutParams mLayout - = new WindowManager.LayoutParams(); - IWindowSession mSession; - MyWindow mWindow; - final Rect mVisibleInsets = new Rect(); - final Rect mWinFrame = new Rect(); - final Rect mOverscanInsets = new Rect(); - final Rect mContentInsets = new Rect(); - final Rect mStableInsets = new Rect(); - final Rect mOutsets = new Rect(); - final Rect mBackdropFrame = new Rect(); + SurfaceControl mSurfaceControl; final Rect mTmpRect = new Rect(); final Configuration mConfiguration = new Configuration(); static final int KEEP_SCREEN_ON_MSG = 1; - static final int GET_NEW_SURFACE_MSG = 2; - static final int UPDATE_WINDOW_MSG = 3; + static final int DRAW_FINISHED_MSG = 2; - int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; + int mSubLayer = APPLICATION_MEDIA_SUBLAYER; boolean mIsCreating = false; private volatile boolean mRtHandlingPositionUpdates = false; @@ -135,11 +130,9 @@ public class SurfaceView extends View { case KEEP_SCREEN_ON_MSG: { setKeepScreenOn(msg.arg1 != 0); } break; - case GET_NEW_SURFACE_MSG: { - handleGetNewSurface(); - } break; - case UPDATE_WINDOW_MSG: { - updateWindow(); + case DRAW_FINISHED_MSG: { + mDrawFinished = true; + invalidate(); } break; } } @@ -149,7 +142,7 @@ public class SurfaceView extends View { = new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { - updateWindow(); + updateSurface(); } }; @@ -159,13 +152,14 @@ public class SurfaceView extends View { public boolean onPreDraw() { // reposition ourselves where the surface is mHaveFrame = getWidth() > 0 && getHeight() > 0; - updateWindow(); + updateSurface(); return true; } }; boolean mRequestedVisible = false; boolean mWindowVisibility = false; + boolean mLastWindowVisibility = false; boolean mViewVisibility = false; int mRequestedWidth = -1; int mRequestedHeight = -1; @@ -181,19 +175,17 @@ public class SurfaceView extends View { boolean mVisible = false; int mWindowSpaceLeft = -1; int mWindowSpaceTop = -1; - int mWindowSpaceWidth = -1; - int mWindowSpaceHeight = -1; + int mSurfaceWidth = -1; + int mSurfaceHeight = -1; int mFormat = -1; final Rect mSurfaceFrame = new Rect(); int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1; - boolean mUpdateWindowNeeded; - boolean mReportDrawNeeded; private Translator mTranslator; - private int mWindowInsetLeft; - private int mWindowInsetTop; private boolean mGlobalListenersAdded; + private int mSurfaceFlags = SurfaceControl.HIDDEN; + public SurfaceView(Context context) { this(context, null); } @@ -227,11 +219,8 @@ public class SurfaceView extends View { protected void onAttachedToWindow() { super.onAttachedToWindow(); mParent.requestTransparentRegion(this); - mSession = getWindowSession(); - mLayout.token = getWindowToken(); - mLayout.setTitle("SurfaceView - " + getViewRootImpl().getTitle()); - mLayout.packageName = mContext.getOpPackageName(); mViewVisibility = getVisibility() == VISIBLE; + mRequestedVisible = mViewVisibility && mWindowVisibility; if (!mGlobalListenersAdded) { ViewTreeObserver observer = getViewTreeObserver(); @@ -246,7 +235,7 @@ public class SurfaceView extends View { super.onWindowVisibilityChanged(visibility); mWindowVisibility = visibility == VISIBLE; mRequestedVisible = mWindowVisibility && mViewVisibility; - updateWindow(); + updateSurface(); } @Override @@ -264,7 +253,7 @@ public class SurfaceView extends View { requestLayout(); } mRequestedVisible = newRequestedVisible; - updateWindow(); + updateSurface(); } @Override @@ -277,19 +266,14 @@ public class SurfaceView extends View { } mRequestedVisible = false; - updateWindow(); - mHaveFrame = false; - if (mWindow != null) { - try { - mSession.remove(mWindow); - } catch (RemoteException ex) { - // Not much we can do here... - } - mWindow = null; + + updateSurface(); + if (mSurfaceControl != null) { + mSurfaceControl.destroy(); } - mSession = null; - mLayout.token = null; + mSurfaceControl = null; + mHaveFrame = false; super.onDetachedFromWindow(); } @@ -308,13 +292,13 @@ public class SurfaceView extends View { @Override protected boolean setFrame(int left, int top, int right, int bottom) { boolean result = super.setFrame(left, top, right, bottom); - updateWindow(); + updateSurface(); return result; } @Override public boolean gatherTransparentRegion(Region region) { - if (mWindowType == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { + if (isAboveParent()) { return super.gatherTransparentRegion(region); } @@ -341,7 +325,7 @@ public class SurfaceView extends View { @Override public void draw(Canvas canvas) { - if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { + if (mDrawFinished && !isAboveParent()) { // draw() is not called when SKIP_DRAW is set if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) { // punch a whole in the view-hierarchy below us @@ -353,8 +337,8 @@ public class SurfaceView extends View { @Override protected void dispatchDraw(Canvas canvas) { - if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { - // if SKIP_DRAW is cleared, draw() has already punched a hole + if (mDrawFinished && !isAboveParent()) { + // draw() is not called when SKIP_DRAW is set if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { // punch a whole in the view-hierarchy below us canvas.drawColor(0, PorterDuff.Mode.CLEAR); @@ -375,9 +359,8 @@ public class SurfaceView extends View { * <p>Calling this overrides any previous call to {@link #setZOrderOnTop}. */ public void setZOrderMediaOverlay(boolean isMediaOverlay) { - mWindowType = isMediaOverlay - ? WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY - : WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; + mSubLayer = isMediaOverlay + ? APPLICATION_MEDIA_OVERLAY_SUBLAYER : APPLICATION_MEDIA_SUBLAYER; } /** @@ -395,12 +378,9 @@ public class SurfaceView extends View { */ public void setZOrderOnTop(boolean onTop) { if (onTop) { - mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; - // ensures the surface is placed below the IME - mLayout.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + mSubLayer = APPLICATION_PANEL_SUBLAYER; } else { - mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; - mLayout.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + mSubLayer = APPLICATION_MEDIA_SUBLAYER; } } @@ -418,31 +398,32 @@ public class SurfaceView extends View { */ public void setSecure(boolean isSecure) { if (isSecure) { - mLayout.flags |= WindowManager.LayoutParams.FLAG_SECURE; + mSurfaceFlags |= SurfaceControl.SECURE; } else { - mLayout.flags &= ~WindowManager.LayoutParams.FLAG_SECURE; + mSurfaceFlags &= ~SurfaceControl.SECURE; } } - /** - * Hack to allow special layering of windows. The type is one of the - * types in WindowManager.LayoutParams. This is a hack so: - * @hide - */ - public void setWindowType(int type) { - mWindowType = type; + private Rect getParentSurfaceInsets() { + final ViewRootImpl root = getViewRootImpl(); + if (root == null) { + return null; + } else { + return root.mWindowAttributes.surfaceInsets; + } } /** @hide */ - protected void updateWindow() { + protected void updateSurface() { if (!mHaveFrame) { return; } ViewRootImpl viewRoot = getViewRootImpl(); - if (viewRoot != null) { - mTranslator = viewRoot.mTranslator; + if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) { + return; } + mTranslator = viewRoot.mTranslator; if (mTranslator != null) { mSurface.setCompatibilityTranslator(mTranslator); } @@ -452,17 +433,15 @@ public class SurfaceView extends View { int myHeight = mRequestedHeight; if (myHeight <= 0) myHeight = getHeight(); - final boolean creating = mWindow == null; final boolean formatChanged = mFormat != mRequestedFormat; - final boolean sizeChanged = mWindowSpaceWidth != myWidth || mWindowSpaceHeight != myHeight; + final boolean creating = (mSurfaceControl == null || formatChanged) + && mRequestedVisible; + final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight; final boolean visibleChanged = mVisible != mRequestedVisible; - final boolean layoutSizeChanged = getWidth() != mLayout.width - || getHeight() != mLayout.height; - + final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility; boolean redrawNeeded = false; - if (creating || formatChanged || sizeChanged || visibleChanged - || mUpdateWindowNeeded || mReportDrawNeeded) { + if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) { getLocationInWindow(mLocation); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " @@ -476,93 +455,77 @@ public class SurfaceView extends View { final boolean visible = mVisible = mRequestedVisible; mWindowSpaceLeft = mLocation[0]; mWindowSpaceTop = mLocation[1]; - mWindowSpaceWidth = myWidth; - mWindowSpaceHeight = myHeight; + mSurfaceWidth = myWidth; + mSurfaceHeight = myHeight; mFormat = mRequestedFormat; + mLastWindowVisibility = mWindowVisibility; - // Scaling/Translate window's layout here because mLayout is not used elsewhere. - - // Places the window relative - mLayout.x = mWindowSpaceLeft; - mLayout.y = mWindowSpaceTop; - mLayout.width = getWidth(); - mLayout.height = getHeight(); + mScreenRect.left = mWindowSpaceLeft; + mScreenRect.top = mWindowSpaceTop; + mScreenRect.right = mWindowSpaceLeft + getWidth(); + mScreenRect.bottom = mWindowSpaceTop + getHeight(); if (mTranslator != null) { - mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout); + mTranslator.translateRectInAppWindowToScreen(mScreenRect); } - mLayout.format = mRequestedFormat; - mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE - | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS - | WindowManager.LayoutParams.FLAG_SCALED - | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE - ; - if (!creating && !sizeChanged) { - mLayout.privateFlags |= - WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY; - } else { - mLayout.privateFlags &= - ~WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY; - } + final Rect surfaceInsets = getParentSurfaceInsets(); + mScreenRect.offset(surfaceInsets.left, surfaceInsets.top); - if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) { - mLayout.privateFlags |= - WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; - } - mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION - | WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME; - - if (mWindow == null) { - Display display = getDisplay(); - mWindow = new MyWindow(this); - mLayout.type = mWindowType; - mLayout.gravity = Gravity.START|Gravity.TOP; - mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout, - mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets, - mStableInsets); + if (creating) { + mSurfaceSession = new SurfaceSession(viewRoot.mSurface); + mSurfaceControl = new SurfaceControl(mSurfaceSession, + "SurfaceView - " + viewRoot.getTitle().toString(), + mSurfaceWidth, mSurfaceHeight, mFormat, + mSurfaceFlags); } - boolean realSizeChanged; - boolean reportDrawNeeded; - - int relayoutResult; + boolean realSizeChanged = false; mSurfaceLock.lock(); try { - mUpdateWindowNeeded = false; - reportDrawNeeded = mReportDrawNeeded; - mReportDrawNeeded = false; mDrawingStopped = !visible; if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Cur surface: " + mSurface); - relayoutResult = mSession.relayout( - mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight, - visible ? VISIBLE : GONE, - WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY, - mWinFrame, mOverscanInsets, mContentInsets, - mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame, - mConfiguration, mNewSurface); - if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { - reportDrawNeeded = true; + SurfaceControl.openTransaction(); + try { + mSurfaceControl.setLayer(mSubLayer); + if (mViewVisibility) { + mSurfaceControl.show(); + } else { + mSurfaceControl.hide(); + } + + // While creating the surface, we will set it's initial + // geometry. Outside of that though, we should generally + // leave it to the RenderThread. + if (creating || !mRtHandlingPositionUpdates) { + mSurfaceControl.setPosition(mScreenRect.left, mScreenRect.top); + mSurfaceControl.setMatrix(mScreenRect.width() / (float) mSurfaceWidth, + 0.0f, 0.0f, + mScreenRect.height() / (float) mSurfaceHeight); + } + if (sizeChanged) { + mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight); + } + } finally { + SurfaceControl.closeTransaction(); } - if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " - + "New surface: " + mNewSurface - + ", vis=" + visible + ", frame=" + mWinFrame); + if (sizeChanged || creating) { + redrawNeeded = true; + } mSurfaceFrame.left = 0; mSurfaceFrame.top = 0; if (mTranslator == null) { - mSurfaceFrame.right = mWinFrame.width(); - mSurfaceFrame.bottom = mWinFrame.height(); + mSurfaceFrame.right = mSurfaceWidth; + mSurfaceFrame.bottom = mSurfaceHeight; } else { float appInvertedScale = mTranslator.applicationInvertedScale; - mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f); - mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f); + mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f); + mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f); } final int surfaceWidth = mSurfaceFrame.right; @@ -576,12 +539,11 @@ public class SurfaceView extends View { } try { - redrawNeeded |= creating | reportDrawNeeded; + redrawNeeded |= visible && !mDrawFinished; SurfaceHolder.Callback callbacks[] = null; - final boolean surfaceChanged = (relayoutResult - & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0; + final boolean surfaceChanged = creating; if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) { mSurfaceCreated = false; if (mSurface.isValid()) { @@ -608,7 +570,10 @@ public class SurfaceView extends View { } } - mSurface.transferFrom(mNewSurface); + if (creating) { + mSurface.copyFrom(mSurfaceControl); + } + if (visible && mSurface.isValid()) { if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) { mSurfaceCreated = true; @@ -641,53 +606,55 @@ public class SurfaceView extends View { callbacks = getSurfaceCallbacks(); } SurfaceCallbackHelper sch = - new SurfaceCallbackHelper(mSession, mWindow); + new SurfaceCallbackHelper(this::onDrawFinished); sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks); } } } finally { mIsCreating = false; - mSession.performDeferredDestroy(mWindow); + if (mSurfaceControl != null && !mSurfaceCreated) { + mSurfaceControl.destroy(); + mSurfaceControl = null; + } } - } catch (RemoteException ex) { + } catch (Exception ex) { Log.e(TAG, "Exception from relayout", ex); } if (DEBUG) Log.v( - TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y + - " w=" + mLayout.width + " h=" + mLayout.height + - ", frame=" + mSurfaceFrame); + TAG, "Layout: x=" + mScreenRect.left + " y=" + mScreenRect.top + + " w=" + mScreenRect.width() + " h=" + mScreenRect.height() + + ", frame=" + mSurfaceFrame); } else { // Calculate the window position in case RT loses the window // and we need to fallback to a UI-thread driven position update - getLocationInWindow(mLocation); + getLocationInSurface(mLocation); final boolean positionChanged = mWindowSpaceLeft != mLocation[0] || mWindowSpaceTop != mLocation[1]; + final boolean layoutSizeChanged = getWidth() != mScreenRect.width() + || getHeight() != mScreenRect.height(); if (positionChanged || layoutSizeChanged) { // Only the position has changed mWindowSpaceLeft = mLocation[0]; mWindowSpaceTop = mLocation[1]; - // For our size changed check, we keep mLayout.width and mLayout.height + // For our size changed check, we keep mScreenRect.width() and mScreenRect.height() // in view local space. - mLocation[0] = mLayout.width = getWidth(); - mLocation[1] = mLayout.height = getHeight(); - - transformFromViewToWindowSpace(mLocation); + mLocation[0] = getWidth(); + mLocation[1] = getHeight(); - mTmpRect.set(mWindowSpaceLeft, mWindowSpaceTop, + mScreenRect.set(mWindowSpaceLeft, mWindowSpaceTop, mLocation[0], mLocation[1]); if (mTranslator != null) { - mTranslator.translateRectInAppWindowToScreen(mTmpRect); + mTranslator.translateRectInAppWindowToScreen(mScreenRect); } if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) { try { - if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition UI, " + + if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " + "postion = [%d, %d, %d, %d]", System.identityHashCode(this), - mTmpRect.left, mTmpRect.top, - mTmpRect.right, mTmpRect.bottom)); - mSession.repositionChild(mWindow, mTmpRect.left, mTmpRect.top, - mTmpRect.right, mTmpRect.bottom, -1, mTmpRect); - } catch (RemoteException ex) { + mScreenRect.left, mScreenRect.top, + mScreenRect.right, mScreenRect.bottom)); + setParentSpaceRectangle(mScreenRect, -1); + } catch (Exception ex) { Log.e(TAG, "Exception from relayout", ex); } } @@ -695,20 +662,43 @@ public class SurfaceView extends View { } } + private void onDrawFinished() { + if (DEBUG) { + Log.i(TAG, System.identityHashCode(this) + " " + + "finishedDrawing"); + } + mHandler.sendEmptyMessage(DRAW_FINISHED_MSG); + } + + private void setParentSpaceRectangle(Rect position, long frameNumber) { + ViewRootImpl viewRoot = getViewRootImpl(); + + SurfaceControl.openTransaction(); + try { + if (frameNumber > 0) { + mSurfaceControl.deferTransactionUntil(viewRoot.mSurface, frameNumber); + } + mSurfaceControl.setPosition(position.left, position.top); + mSurfaceControl.setMatrix(position.width() / (float) mSurfaceWidth, + 0.0f, 0.0f, + position.height() / (float) mSurfaceHeight); + } finally { + SurfaceControl.closeTransaction(); + } + } + private Rect mRTLastReportedPosition = new Rect(); /** * Called by native by a Rendering Worker thread to update the window position * @hide */ - public final void updateWindowPosition_renderWorker(long frameNumber, + public final void updateSurfacePosition_renderWorker(long frameNumber, int left, int top, int right, int bottom) { - IWindowSession session = mSession; - MyWindow window = mWindow; - if (session == null || window == null) { - // Guess we got detached, that sucks + 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 @@ -726,35 +716,29 @@ public class SurfaceView extends View { } try { if (DEBUG) { - Log.d(TAG, String.format("%d updateWindowPosition RenderWorker, frameNr = %d, " + + Log.d(TAG, String.format("%d updateSurfacePosition RenderWorker, frameNr = %d, " + "postion = [%d, %d, %d, %d]", System.identityHashCode(this), frameNumber, left, top, right, bottom)); } - // Just using mRTLastReportedPosition as a dummy rect here - session.repositionChild(window, left, top, right, bottom, - frameNumber, - mRTLastReportedPosition); - // Now overwrite mRTLastReportedPosition with our values mRTLastReportedPosition.set(left, top, right, bottom); - } catch (RemoteException ex) { + setParentSpaceRectangle(mRTLastReportedPosition, frameNumber); + // Now overwrite mRTLastReportedPosition with our values + } catch (Exception ex) { Log.e(TAG, "Exception from repositionChild", ex); } } /** - * Called by native on RenderThread to notify that the window is no longer in the + * Called by native on RenderThread to notify that the view is no longer in the * draw tree. UI thread is blocked at this point. * @hide */ - public final void windowPositionLost_uiRtSync(long frameNumber) { + public final void surfacePositionLost_uiRtSync(long frameNumber) { if (DEBUG) { Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d", System.identityHashCode(this), frameNumber)); } - IWindowSession session = mSession; - MyWindow window = mWindow; - if (session == null || window == null) { - // We got detached prior to receiving this, abort + if (mSurfaceControl == null) { return; } if (mRtHandlingPositionUpdates) { @@ -763,19 +747,14 @@ public class SurfaceView extends View { // safely access other member variables at this time. // So do what the UI thread would have done if RT wasn't handling position // updates. - mTmpRect.set(mLayout.x, mLayout.y, - mLayout.x + mLayout.width, - mLayout.y + mLayout.height); - - if (!mTmpRect.isEmpty() && !mTmpRect.equals(mRTLastReportedPosition)) { + if (!mScreenRect.isEmpty() && !mScreenRect.equals(mRTLastReportedPosition)) { try { - if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition, " + + if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition, " + "postion = [%d, %d, %d, %d]", System.identityHashCode(this), - mTmpRect.left, mTmpRect.top, - mTmpRect.right, mTmpRect.bottom)); - session.repositionChild(window, mTmpRect.left, mTmpRect.top, - mTmpRect.right, mTmpRect.bottom, frameNumber, mWinFrame); - } catch (RemoteException ex) { + mScreenRect.left, mScreenRect.top, + mScreenRect.right, mScreenRect.bottom)); + setParentSpaceRectangle(mScreenRect, frameNumber); + } catch (Exception ex) { Log.e(TAG, "Exception from relayout", ex); } } @@ -792,10 +771,6 @@ public class SurfaceView extends View { return callbacks; } - void handleGetNewSurface() { - updateWindow(); - } - /** * Check to see if the surface has fixed size dimensions or if the surface's * dimensions are dimensions are dependent on its current layout. @@ -807,65 +782,8 @@ public class SurfaceView extends View { return (mRequestedWidth != -1 || mRequestedHeight != -1); } - private static class MyWindow extends BaseIWindow { - private final WeakReference<SurfaceView> mSurfaceView; - - public MyWindow(SurfaceView surfaceView) { - mSurfaceView = new WeakReference<SurfaceView>(surfaceView); - } - - @Override - public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, - Configuration newConfig, Rect backDropRect, boolean forceLayout, - boolean alwaysConsumeNavBar, int displayId) { - SurfaceView surfaceView = mSurfaceView.get(); - if (surfaceView != null) { - if (DEBUG) Log.v(TAG, surfaceView + " got resized: w=" + frame.width() - + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight); - surfaceView.mSurfaceLock.lock(); - try { - if (reportDraw) { - surfaceView.mUpdateWindowNeeded = true; - surfaceView.mReportDrawNeeded = true; - surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG); - } else if (surfaceView.mWinFrame.width() != frame.width() - || surfaceView.mWinFrame.height() != frame.height() - || forceLayout) { - surfaceView.mUpdateWindowNeeded = true; - surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG); - } - } finally { - surfaceView.mSurfaceLock.unlock(); - } - } - } - - @Override - public void dispatchAppVisibility(boolean visible) { - // The point of SurfaceView is to let the app control the surface. - } - - @Override - public void dispatchGetNewSurface() { - SurfaceView surfaceView = mSurfaceView.get(); - if (surfaceView != null) { - Message msg = surfaceView.mHandler.obtainMessage(GET_NEW_SURFACE_MSG); - surfaceView.mHandler.sendMessage(msg); - } - } - - @Override - public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) { - Log.w("SurfaceView", "Unexpected focus in surface: focus=" + hasFocus + ", touchEnabled=" + touchEnabled); - } - - @Override - public void executeCommand(String command, String parameters, ParcelFileDescriptor out) { - } - - int mCurWidth = -1; - int mCurHeight = -1; + private boolean isAboveParent() { + return mSubLayer >= 0; } private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() { @@ -913,15 +831,14 @@ public class SurfaceView extends View { @Override public void setFormat(int format) { - // for backward compatibility reason, OPAQUE always // means 565 for SurfaceView if (format == PixelFormat.OPAQUE) format = PixelFormat.RGB_565; mRequestedFormat = format; - if (mWindow != null) { - updateWindow(); + if (mSurfaceControl != null) { + updateSurface(); } } @@ -982,10 +899,10 @@ public class SurfaceView extends View { mSurfaceLock.lock(); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped=" - + mDrawingStopped + ", win=" + mWindow); + + mDrawingStopped + ", surfaceControl=" + mSurfaceControl); Canvas c = null; - if (!mDrawingStopped && mWindow != null) { + if (!mDrawingStopped && mSurfaceControl != null) { try { if (hardware) { c = mSurface.lockHardwareCanvas(); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 20d960fff661..f9863b0a6761 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2632,6 +2632,14 @@ public final class ViewRootImpl implements ViewParent, } } + private void onDrawFinished() { + try { + mWindowSession.finishDrawing(mWindow); + } catch (RemoteException e) { + // Have fun! + } + } + private void performDraw() { if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) { return; @@ -2682,7 +2690,7 @@ public final class ViewRootImpl implements ViewParent, } if (mSurfaceHolder != null && mSurface.isValid()) { - SurfaceCallbackHelper sch = new SurfaceCallbackHelper(mWindowSession, mWindow); + SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::onDrawFinished); SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks); |
