diff options
| author | Vishnu Nair <vishnun@google.com> | 2019-06-18 11:14:01 -0700 |
|---|---|---|
| committer | Arthur Hsu <arthurhsu@google.com> | 2019-06-18 12:49:24 -0700 |
| commit | f7645aa9a968e2da227f1edceaa2b83054b451dd (patch) | |
| tree | b1aa5d7b87c7b9890a17091ca7a25dd59f53b123 /core/java/android/view/ViewRootImpl.java | |
| parent | 22dd194d6d1edc111f58e552d4bb2c8a45c09daa (diff) | |
Prevent SurfaceView from drawing over parent surface insets
Parent SurfaceView to a bounds layer that enforces a crop preventing it
from drawing over the surface insets. The bounds layer crop is set to the
surface insets and updated when the parent surface size changes or the
parent surface insets change.
If the SurfaceView children are reparented to another client surface
then ensure the SurfaceView relative layer info is updated correctly.
Bug: 132205507
Test: go/wm-smoke
Test: test preserve surfaces codepath with split screen and ensure relative z is preserved
Test: test surfaceview apps, youtube, maps & camera.
Test: try to repro maps pip issue described in bug
Change-Id: I14c2f7603345ad89f0af4db48150b05d8ada602a
Diffstat (limited to 'core/java/android/view/ViewRootImpl.java')
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 115 |
1 files changed, 70 insertions, 45 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 30bb2bbd3385..16de906b1085 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -68,6 +68,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; @@ -476,17 +477,19 @@ public final class ViewRootImpl implements ViewParent, @UnsupportedAppUsage public final Surface mSurface = new Surface(); private final SurfaceControl mSurfaceControl = new SurfaceControl(); + private IBinder mPreviousSurfaceControlHandle = null; + + private final Transaction mChangeSurfaceTransaction = new Transaction(); + private final SurfaceSession mSurfaceSession = new SurfaceSession(); /** - * Child surface of {@code mSurface} with the same bounds as its parent, and crop bounds - * are set to the parent's bounds adjusted for surface insets. This surface is created when - * {@link ViewRootImpl#createBoundsSurface(int)} is called. - * By parenting to this bounds surface, child surfaces can ensure they do not draw into the - * surface inset regions set by the parent window. + * Child container layer of {@code mSurface} with the same bounds as its parent, and cropped to + * the surface insets. This surface is created only if a client requests it via {@link + * #getBoundsLayer()}. By parenting to this bounds surface, child surfaces can ensure they do + * not draw into the surface inset regions set by the parent window. */ - public final Surface mBoundsSurface = new Surface(); - private SurfaceSession mSurfaceSession; - private SurfaceControl mBoundsSurfaceControl; + private SurfaceControl mBoundsLayer; + private final Transaction mTransaction = new Transaction(); @UnsupportedAppUsage @@ -1576,65 +1579,76 @@ public final class ViewRootImpl implements ViewParent, } } - /** - * Creates a surface as a child of {@code mSurface} with the same bounds as its parent and - * crop bounds set to the parent's bounds adjusted for surface insets. - * - * @param zOrderLayer Z order relative to the parent surface. - */ - public void createBoundsSurface(int zOrderLayer) { - if (mSurfaceSession == null) { - mSurfaceSession = new SurfaceSession(); - } - if (mBoundsSurfaceControl != null && mBoundsSurface.isValid()) { - return; // surface control for bounds surface already exists. + /** Register callback to be notified when the ViewRootImpl surface changes. */ + interface SurfaceChangedCallback { + void surfaceChangedCallback(SurfaceControl.Transaction transaction); + } + + private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>(); + void addSurfaceChangedCallback(SurfaceChangedCallback c) { + mSurfaceChangedCallbacks.add(c); + } + + void removeSurfaceChangedCallback(SurfaceChangedCallback c) { + mSurfaceChangedCallbacks.remove(c); + } + + private void notifySurfaceChanged(SurfaceControl.Transaction transaction) { + for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) { + mSurfaceChangedCallbacks.get(i).surfaceChangedCallback(transaction); } + } - mBoundsSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) + /** + * Returns a child layer with the same bounds as its parent {@code mSurface} and cropped to the + * surface insets. If the layer does not exist, it is created. + * + * <p>Parenting to this layer will ensure that its children are cropped by the view's surface + * insets. + */ + public SurfaceControl getBoundsLayer() { + if (mBoundsLayer == null) { + mBoundsLayer = new SurfaceControl.Builder(mSurfaceSession) + .setContainerLayer() .setName("Bounds for - " + getTitle().toString()) .setParent(mSurfaceControl) .build(); - setBoundsSurfaceCrop(); - mTransaction.setLayer(mBoundsSurfaceControl, zOrderLayer) - .show(mBoundsSurfaceControl) - .apply(); - mBoundsSurface.copyFrom(mBoundsSurfaceControl); + setBoundsLayerCrop(mTransaction); + mTransaction.show(mBoundsLayer).apply(); + } + return mBoundsLayer; } - private void setBoundsSurfaceCrop() { + private void setBoundsLayerCrop(Transaction t) { // mWinFrame is already adjusted for surface insets. So offset it and use it as // the cropping bounds. mTempBoundsRect.set(mWinFrame); mTempBoundsRect.offsetTo(mWindowAttributes.surfaceInsets.left, mWindowAttributes.surfaceInsets.top); - mTransaction.setWindowCrop(mBoundsSurfaceControl, mTempBoundsRect); + t.setWindowCrop(mBoundsLayer, mTempBoundsRect); } /** - * Called after window layout to update the bounds surface. If the surface insets have - * changed or the surface has resized, update the bounds surface. + * Called after window layout to update the bounds surface. If the surface insets have changed + * or the surface has resized, update the bounds surface. */ - private void updateBoundsSurface() { - if (mBoundsSurfaceControl != null && mSurface.isValid()) { - setBoundsSurfaceCrop(); - mTransaction.deferTransactionUntilSurface(mBoundsSurfaceControl, + private void updateBoundsLayer() { + if (mBoundsLayer != null) { + setBoundsLayerCrop(mTransaction); + mTransaction.deferTransactionUntilSurface(mBoundsLayer, mSurface, mSurface.getNextFrameNumber()) .apply(); } } private void destroySurface() { + if (mBoundsLayer != null) { + mBoundsLayer.release(); + mBoundsLayer = null; + } mSurface.release(); mSurfaceControl.release(); - - mSurfaceSession = null; - - if (mBoundsSurfaceControl != null) { - mBoundsSurfaceControl.remove(); - mBoundsSurface.release(); - mBoundsSurfaceControl = null; - } } /** @@ -2598,7 +2612,7 @@ public final class ViewRootImpl implements ViewParent, } if (surfaceSizeChanged) { - updateBoundsSurface(); + updateBoundsLayer(); } final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); @@ -3438,7 +3452,9 @@ public final class ViewRootImpl implements ViewParent, private void reportDrawFinished() { try { mDrawsNeededToReport = 0; - mWindowSession.finishDrawing(mWindow); + if (mSurfaceControl.isValid()) { + mWindowSession.finishDrawing(mWindow, mChangeSurfaceTransaction); + } } catch (RemoteException e) { // Have fun! } @@ -7089,6 +7105,9 @@ public final class ViewRootImpl implements ViewParent, frameNumber = mSurface.getNextFrameNumber(); } + mPreviousSurfaceControlHandle = mSurfaceControl.isValid() + ? mSurfaceControl.getHandle() : null; + int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, @@ -7102,6 +7121,11 @@ public final class ViewRootImpl implements ViewParent, destroySurface(); } + if (mPreviousSurfaceControlHandle != null && mSurfaceControl.isValid() + && mPreviousSurfaceControlHandle != mSurfaceControl.getHandle()) { + notifySurfaceChanged(mChangeSurfaceTransaction); + } + mPendingAlwaysConsumeSystemBars = (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0; @@ -7326,7 +7350,8 @@ public final class ViewRootImpl implements ViewParent, try { if ((relayoutWindow(mWindowAttributes, viewVisibility, false) & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { - mWindowSession.finishDrawing(mWindow); + mWindowSession.finishDrawing( + mWindow, null /* postDrawTransaction */); } } catch (RemoteException e) { } |
