summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author chaviw <chaviw@google.com> 2020-07-09 16:39:04 -0700
committer Chavi Weingarten <chaviw@google.com> 2020-07-10 00:32:46 +0000
commitc1dcac956838818a57b9334332df21ac55e91c02 (patch)
tree1898e72e9bbe1d459114a85ebf10a2da37f81ed3
parenta711165637a784b77c1c484703230a929c5ea4b7 (diff)
Reparent bounds layer if surface was replaced.
In a normal case, the app will get either a visibility changed to false or stopped from system server to indicate that the content should be cleaned up. In those cases, it will request a relayout to WM, which will notify VRI that the surface is gone. Since the VRI surface is removed, the SV and bounds layer will get notified that they should be destroyed. On the next relayout, the VRI will get a new surface and notify SV and the bounds layer to create new surfaces. The scenario in the bug happens when VRI receives a visibility change to false, but doesn't process the information fast enough. By the time it calls relayout, WMS is in the state where the client is visible again. This time the relayout will return a valid surface so the SV and bounds layer will not get cleaned up. The reason this causes issues is VRI now has a new main surface. The bounds layer is parented to the old layer that's been deleted so it's not parented to anything. The SurfaceView is a child of the bounds layer so it also renders offscreen. The reparent needs to be done on the client side since WMS won't reparent the children to the new surface if it thinks the app is closing. WMS gets the signal that the app is stopping, but on the client side, it doesn't get stopped since it's restarted quick enough. WMS doesn't want to keep around old children since they will leak when the client creates new children. This change will reparent the bounds layer to the new VRI surface. It's possible WMS will take care of this in certain cases where the app isn't stopped. But for those cases, the reparent will not have any effect since the bounds layer will be correctly parented. Fixes: 159545768 Test: Can no longer repro black SV in maps Test: Test app with SV and delay in onPause no longer has the same issue Change-Id: I616652e1cc4380ebbcb386586d8d5889fcc19497
-rw-r--r--core/java/android/view/ViewRootImpl.java25
1 files changed, 20 insertions, 5 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a58642517a20..814293a8d8b7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1824,13 +1824,19 @@ public final class ViewRootImpl implements ViewParent,
/**
* Called after window layout to update the bounds surface. If the surface insets have changed
* or the surface has resized, update the bounds surface.
+ *
+ * @param shouldReparent Whether it should reparent the bounds layer to the main SurfaceControl.
*/
- private void updateBoundsLayer() {
+ private void updateBoundsLayer(boolean shouldReparent) {
if (mBoundsLayer != null) {
setBoundsLayerCrop();
- mTransaction.deferTransactionUntil(mBoundsLayer,
- getRenderSurfaceControl(), mSurface.getNextFrameNumber())
- .apply();
+ mTransaction.deferTransactionUntil(mBoundsLayer, getRenderSurfaceControl(),
+ mSurface.getNextFrameNumber());
+
+ if (shouldReparent) {
+ mTransaction.reparent(mBoundsLayer, getRenderSurfaceControl());
+ }
+ mTransaction.apply();
}
}
@@ -2913,7 +2919,16 @@ public final class ViewRootImpl implements ViewParent,
}
if (surfaceSizeChanged || surfaceReplaced || surfaceCreated || windowAttributesChanged) {
- updateBoundsLayer();
+ // If the surface has been replaced, there's a chance the bounds layer is not parented
+ // to the new layer. When updating bounds layer, also reparent to the main VRI
+ // SurfaceControl to ensure it's correctly placed in the hierarchy.
+ //
+ // This needs to be done on the client side since WMS won't reparent the children to the
+ // new surface if it thinks the app is closing. WMS gets the signal that the app is
+ // stopping, but on the client side it doesn't get stopped since it's restarted quick
+ // enough. WMS doesn't want to keep around old children since they will leak when the
+ // client creates new children.
+ updateBoundsLayer(surfaceReplaced);
}
final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);