summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Robert Carr <racarr@google.com> 2020-07-22 16:59:05 -0700
committer Robert Carr <racarr@google.com> 2020-09-28 12:20:27 -0700
commit55d882cf5f36edeafccfb97ed539a4c13e85fbfd (patch)
tree61d4ae82b77eed0cf34b9e877dd80c018ea217eb
parent0cf5818391155064e778f49d3784d06e11e8a63b (diff)
WindowStateAnimator/ViewRoot: Move surface resizing to client
The bounds on the client surface are controlled by higher levels of the hierarchy and so the client can use whatever Surface size it wants on its node. We move the SurfaceControl setSize call to the client, following 3 sort of ideas: 1. Project to make relayout window async, but currently it is used as a sync point for resizing, resizing on client, one problem solved! 2. WM Shouldn't do what it doesnt have to for clients 3. Totally move management of lowest level Surface to client clean up lots of WM code (see WindowStateAnimator slimming project) In the future maybe we don't need to set the SurfaceControl size at all and the client can just set its buffer size, but it may produce some differences in geometry handling on the server so I want to maintain the old semantics for this CL. Bug: 161937501 Test: Existing tests pass Change-Id: Icebd94f8443fdbe9f0e6968bc35bbb0504a1520c
-rw-r--r--core/java/android/view/ViewRootImpl.java43
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java33
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java56
4 files changed, 76 insertions, 60 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4176e887c0e7..b1b77edad07f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1790,7 +1790,7 @@ public final class ViewRootImpl implements ViewParent,
.setParent(getRenderSurfaceControl())
.setCallsite("ViewRootImpl.getBoundsLayer")
.build();
- setBoundsLayerCrop();
+ setBoundsLayerCrop(mTransaction);
mTransaction.show(mBoundsLayer).apply();
}
return mBoundsLayer;
@@ -1818,25 +1818,41 @@ public final class ViewRootImpl implements ViewParent,
return ret;
}
- private void setBoundsLayerCrop() {
+ 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(mBoundsLayer, 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.
*/
- private void updateBoundsLayer() {
+ private boolean updateBoundsLayer(SurfaceControl.Transaction t) {
if (mBoundsLayer != null) {
- setBoundsLayerCrop();
- mTransaction.deferTransactionUntil(mBoundsLayer,
- getRenderSurfaceControl(), mSurface.getNextFrameNumber())
- .apply();
+ setBoundsLayerCrop(t);
+ t.deferTransactionUntil(mBoundsLayer, getRenderSurfaceControl(),
+ mSurface.getNextFrameNumber());
+ return true;
+ }
+ return false;
+ }
+
+ private void prepareSurfaces(boolean sizeChanged) {
+ final SurfaceControl.Transaction t = mTransaction;
+ final SurfaceControl sc = getRenderSurfaceControl();
+ if (!sc.isValid()) return;
+
+ boolean applyTransaction = updateBoundsLayer(t);
+ if (sizeChanged) {
+ applyTransaction = true;
+ t.setBufferSize(sc, mSurfaceSize.x, mSurfaceSize.y);
+ }
+ if (applyTransaction) {
+ t.apply();
}
}
@@ -2927,7 +2943,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.
+ prepareSurfaces(surfaceSizeChanged);
}
final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d9c574ccc64c..a7f5eca9af94 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2427,8 +2427,8 @@ public class WindowManagerService extends IWindowManager.Stub
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
if (winAnimator.mSurfaceController != null) {
- outSurfaceSize.set(winAnimator.mSurfaceController.getWidth(),
- winAnimator.mSurfaceController.getHeight());
+ win.calculateSurfaceBounds(win.getAttrs(), mTmpRect);
+ outSurfaceSize.set(mTmpRect.width(), mTmpRect.height());
}
getInsetsSourceControls(win, outActiveControls);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8cdcb9b6af07..0a1c184d8485 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5940,4 +5940,37 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void requestRedrawForSync() {
mRedrawForSyncReported = false;
}
+
+ void calculateSurfaceBounds(WindowManager.LayoutParams attrs, Rect outSize) {
+ outSize.setEmpty();
+ if ((attrs.flags & FLAG_SCALED) != 0) {
+ // For a scaled surface, we always want the requested size.
+ outSize.right = mRequestedWidth;
+ outSize.bottom = mRequestedHeight;
+ } else {
+ // When we're doing a drag-resizing, request a surface that's fullscreen size,
+ // so that we don't need to reallocate during the process. This also prevents
+ // buffer drops due to size mismatch.
+ if (isDragResizing()) {
+ final DisplayInfo displayInfo = getDisplayInfo();
+ outSize.right = displayInfo.logicalWidth;
+ outSize.bottom = displayInfo.logicalHeight;
+ } else {
+ getCompatFrameSize(outSize);
+ }
+ }
+
+ // This doesn't necessarily mean that there is an error in the system. The sizes might be
+ // incorrect, because it is before the first layout or draw.
+ if (outSize.width() < 1) {
+ outSize.right = 1;
+ }
+ if (outSize.height() < 1) {
+ outSize.bottom = 1;
+ }
+
+ // Adjust for surface insets.
+ outSize.inset(-attrs.surfaceInsets.left, -attrs.surfaceInsets.top,
+ -attrs.surfaceInsets.right, -attrs.surfaceInsets.bottom);
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 7bb79555c52c..a31c5fef29b8 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -456,7 +456,8 @@ class WindowStateAnimator {
flags |= SurfaceControl.SKIP_SCREENSHOT;
}
- calculateSurfaceBounds(w, attrs, mTmpSize);
+ w.calculateSurfaceBounds(attrs, mTmpSize);
+
final int width = mTmpSize.width();
final int height = mTmpSize.height();
@@ -532,40 +533,6 @@ class WindowStateAnimator {
return mSurfaceController;
}
- private void calculateSurfaceBounds(WindowState w, LayoutParams attrs, Rect outSize) {
- outSize.setEmpty();
- if ((attrs.flags & FLAG_SCALED) != 0) {
- // For a scaled surface, we always want the requested size.
- outSize.right = w.mRequestedWidth;
- outSize.bottom = w.mRequestedHeight;
- } else {
- // When we're doing a drag-resizing, request a surface that's fullscreen size,
- // so that we don't need to reallocate during the process. This also prevents
- // buffer drops due to size mismatch.
- if (w.isDragResizing()) {
- final DisplayInfo displayInfo = w.getDisplayInfo();
- outSize.right = displayInfo.logicalWidth;
- outSize.bottom = displayInfo.logicalHeight;
- } else {
- w.getCompatFrameSize(outSize);
- }
- }
-
- // Something is wrong and SurfaceFlinger will not like this, try to revert to reasonable
- // values. This doesn't necessarily mean that there is an error in the system. The sizes
- // might be incorrect, because it is before the first layout or draw.
- if (outSize.width() < 1) {
- outSize.right = 1;
- }
- if (outSize.height() < 1) {
- outSize.bottom = 1;
- }
-
- // Adjust for surface insets.
- outSize.inset(-attrs.surfaceInsets.left, -attrs.surfaceInsets.top,
- -attrs.surfaceInsets.right, -attrs.surfaceInsets.bottom);
- }
-
boolean hasSurface() {
return mSurfaceController != null && mSurfaceController.hasSurface();
}
@@ -771,20 +738,6 @@ class WindowStateAnimator {
final LayoutParams attrs = mWin.getAttrs();
final Task task = w.getTask();
- calculateSurfaceBounds(w, attrs, mTmpSize);
-
- // Once relayout has been called at least once, we need to make sure
- // we only resize the client surface during calls to relayout. For
- // clients which use indeterminate measure specs (MATCH_PARENT),
- // we may try and change their window size without a call to relayout.
- // However, this would be unsafe, as the client may be in the middle
- // of producing a frame at the old size, having just completed layout
- // to find the surface size changed underneath it.
- final boolean relayout = !w.mRelayoutCalled || w.mInRelayout;
- if (relayout) {
- mSurfaceController.setBufferSizeInTransaction(
- mTmpSize.width(), mTmpSize.height(), recoveringMemory);
- }
// If we are undergoing seamless rotation, the surface has already
// been set up to persist at it's old location. We need to freeze
// updates until a resize occurs.
@@ -808,6 +761,11 @@ class WindowStateAnimator {
final Rect insets = attrs.surfaceInsets;
+ // getFrameNumber is only valid in the call-stack of relayoutWindow
+ // as this is the only-time we know the client renderer
+ // is paused.
+ final boolean relayout = !w.mRelayoutCalled || w.mInRelayout;
+
if (!w.mSeamlesslyRotated) {
// Used to offset the WSA when stack position changes before a resize.
int xOffset = mXOffset;