summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;