diff options
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; |