summaryrefslogtreecommitdiff
path: root/core/java/android/view/ViewRootImpl.java
diff options
context:
space:
mode:
authorVishnu Nair <vishnun@google.com>2019-06-18 11:14:01 -0700
committerArthur Hsu <arthurhsu@google.com>2019-06-18 12:49:24 -0700
commitf7645aa9a968e2da227f1edceaa2b83054b451dd (patch)
treeb1aa5d7b87c7b9890a17091ca7a25dd59f53b123 /core/java/android/view/ViewRootImpl.java
parent22dd194d6d1edc111f58e552d4bb2c8a45c09daa (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.java115
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) {
}