From 2e20bcd65ecdb06eeaac2dc8356dec90c756d271 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 22 Jan 2020 13:32:38 -0800 Subject: [PATCH] WM: Defer transactions for BLAST Surfaces too. For switching on BLAST we are implementing deferred transactions for compatibility. Presently the BLAST Surface is constructed by the ViewRootImpl and so the WM has no reference to pass when using it as a barrier layer for deferTransactionUntil. To resolve this we construct and hold a reference to the BLAST Surface on the server side, and pass it down to the client in relayoutWindow. We don't use the WindowStateAnimator surface directly as both the BLAST Adapter and the WindowStateAnimator would then be setting crops on it. Bug: 146598493 Test: Builds, existing tests pass. Change-Id: I6513e0442f5c75f01eb8dde5f1924dd7b636163c --- .../core/src/android/wm/RelayoutPerfTest.java | 2 +- .../service/wallpaper/WallpaperService.java | 5 ++- core/java/android/view/IWindowSession.aidl | 6 +++- core/java/android/view/ViewRootImpl.java | 17 ++++----- .../android/view/WindowlessWindowManager.java | 2 +- .../android/systemui/wm/SystemWindows.java | 4 +-- .../server/wm/InsetsSourceProvider.java | 2 +- .../android/server/wm/SeamlessRotator.java | 4 +-- .../java/com/android/server/wm/Session.java | 5 +-- .../server/wm/TaskSnapshotSurface.java | 8 +++-- .../server/wm/WindowManagerService.java | 10 ++++-- .../com/android/server/wm/WindowState.java | 4 +++ .../server/wm/WindowStateAnimator.java | 11 ++++-- .../server/wm/WindowSurfaceController.java | 36 +++++++++++++++++-- 14 files changed, 84 insertions(+), 32 deletions(-) diff --git a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java index c62aad622f25b..b6e39e14602ac 100644 --- a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java +++ b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java @@ -150,7 +150,7 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase { mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrame, mOutContentInsets, mOutVisibleInsets, mOutStableInsets, mOutBackDropFrame, mOutDisplayCutout, mOutMergedConfiguration, - mOutSurfaceControl, mOutInsetsState, new Point()); + mOutSurfaceControl, mOutInsetsState, new Point(), new SurfaceControl()); } } } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index dd78c78654c38..e9285cc7931d3 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -223,6 +223,9 @@ public abstract class WallpaperService extends Service { SurfaceControl mSurfaceControl = new SurfaceControl(); + // Unused relayout out-param + SurfaceControl mTmpSurfaceControl = new SurfaceControl(); + final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() { { mRequestedFormat = PixelFormat.RGBX_8888; @@ -902,7 +905,7 @@ public abstract class WallpaperService extends Service { View.VISIBLE, 0, -1, mWinFrame, mContentInsets, mVisibleInsets, mStableInsets, mBackdropFrame, mDisplayCutout, mMergedConfiguration, mSurfaceControl, - mInsetsState, mSurfaceSize); + mInsetsState, mSurfaceSize, mTmpSurfaceControl); if (mSurfaceControl.isValid()) { mSurfaceHolder.mSurface.copyFrom(mSurfaceControl); mSurfaceControl.release(); diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index e3446e1f7b579..1677357dedbe5 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -92,6 +92,9 @@ interface IWindowSession { * @param outSurface Object in which is placed the new display surface. * @param insetsState The current insets state in the system. * @param outSurfaceSize The width and height of the surface control + * @param outBlastSurfaceControl A BLAST SurfaceControl allocated by the WindowManager + * the SurfaceControl willl be managed by the client side, but the WindowManager + * may use it as a deferTransaction barrier. * * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS}, * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}. @@ -103,7 +106,8 @@ interface IWindowSession { out Rect outBackdropFrame, out DisplayCutout.ParcelableWrapper displayCutout, out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl, - out InsetsState insetsState, out Point outSurfaceSize); + out InsetsState insetsState, out Point outSurfaceSize, + out SurfaceControl outBlastSurfaceControl); /* * Notify the window manager that an application is relaunching and diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 7a93dcc9e4ec3..fbcc261a956ec 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -507,7 +507,7 @@ public final class ViewRootImpl implements ViewParent, @UnsupportedAppUsage public final Surface mSurface = new Surface(); private final SurfaceControl mSurfaceControl = new SurfaceControl(); - private SurfaceControl mBlastSurfaceControl; + private SurfaceControl mBlastSurfaceControl = new SurfaceControl(); private BLASTBufferQueue mBlastBufferQueue; @@ -1690,23 +1690,17 @@ public final class ViewRootImpl implements ViewParent, .build(); setBoundsLayerCrop(); mTransaction.show(mBoundsLayer).apply(); - } - return mBoundsLayer; + } + return mBoundsLayer; } Surface getOrCreateBLASTSurface(int width, int height) { if (mSurfaceControl == null || !mSurfaceControl.isValid()) { return null; } - if (mBlastSurfaceControl == null) { - mBlastSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) - .setParent(mSurfaceControl) - .setName("BLAST") - .setBLASTLayer() - .build(); + if ((mBlastBufferQueue != null) && mBlastSurfaceControl.isValid()) { mBlastBufferQueue = new BLASTBufferQueue( mBlastSurfaceControl, width, height); - } mBlastBufferQueue.update(mBlastSurfaceControl, width, height); @@ -7344,7 +7338,8 @@ public final class ViewRootImpl implements ViewParent, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber, mTmpFrame, mPendingContentInsets, mPendingVisibleInsets, mPendingStableInsets, mPendingBackDropFrame, mPendingDisplayCutout, - mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mSurfaceSize); + mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mSurfaceSize, + mBlastSurfaceControl); if (mSurfaceControl.isValid()) { if (!WindowManagerGlobal.USE_BLAST_ADAPTER) { mSurface.copyFrom(mSurfaceControl); diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index 9f2784889cab6..91778aaf51fda 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -161,7 +161,7 @@ public class WindowlessWindowManager implements IWindowSession { Rect outStableInsets, Rect outBackdropFrame, DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - Point outSurfaceSize) { + Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) { State state = null; synchronized (this) { state = mStateForWindow.get(window.asBinder()); diff --git a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java index 5aba013a7fb8e..adce1248b04bc 100644 --- a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java +++ b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java @@ -239,12 +239,12 @@ public class SystemWindows { Rect outVisibleInsets, Rect outStableInsets, DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - Point outSurfaceSize) { + Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) { int res = super.relayout(window, seq, attrs, requestedWidth, requestedHeight, viewVisibility, flags, frameNumber, outFrame, outOverscanInsets, outContentInsets, outVisibleInsets, outStableInsets, cutout, mergedConfiguration, outSurfaceControl, outInsetsState, - outSurfaceSize); + outSurfaceSize, outBLASTSurfaceControl); if (res != 0) { return res; } diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 5a591ecd47466..2bb58ddc5b387 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -233,7 +233,7 @@ class InsetsSourceProvider { // window crop of the surface controls (including the leash) until the client finishes // drawing the new frame of the new orientation. Although we cannot defer the reparent // operation, it is fine, because reparent won't cause any visual effect. - final SurfaceControl barrier = mWin.mWinAnimator.mSurfaceController.mSurfaceControl; + final SurfaceControl barrier = mWin.getDeferTransactionBarrier(); t.deferTransactionUntil(mWin.getSurfaceControl(), barrier, frameNumber); t.deferTransactionUntil(leash, barrier, frameNumber); } diff --git a/services/core/java/com/android/server/wm/SeamlessRotator.java b/services/core/java/com/android/server/wm/SeamlessRotator.java index ba31818d63310..c621c48b00287 100644 --- a/services/core/java/com/android/server/wm/SeamlessRotator.java +++ b/services/core/java/com/android/server/wm/SeamlessRotator.java @@ -101,9 +101,9 @@ public class SeamlessRotator { t.setPosition(win.mSurfaceControl, win.mLastSurfacePosition.x, win.mLastSurfacePosition.y); if (win.mWinAnimator.mSurfaceController != null && !timeout) { t.deferTransactionUntil(win.mSurfaceControl, - win.mWinAnimator.mSurfaceController.mSurfaceControl, win.getFrameNumber()); + win.getDeferTransactionBarrier(), win.getFrameNumber()); t.deferTransactionUntil(win.mWinAnimator.mSurfaceController.mSurfaceControl, - win.mWinAnimator.mSurfaceController.mSurfaceControl, win.getFrameNumber()); + win.getDeferTransactionBarrier(), win.getFrameNumber()); } } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 5babdafc856df..de7f9e41cac08 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -191,7 +191,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { Rect outStableInsets, Rect outBackdropFrame, DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - Point outSurfaceSize) { + Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) { if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from " + Binder.getCallingPid()); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag); @@ -199,7 +199,8 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { requestedWidth, requestedHeight, viewFlags, flags, frameNumber, outFrame, outContentInsets, outVisibleInsets, outStableInsets, outBackdropFrame, cutout, - mergedConfiguration, outSurfaceControl, outInsetsState, outSurfaceSize); + mergedConfiguration, outSurfaceControl, outInsetsState, outSurfaceSize, + outBLASTSurfaceControl); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index 57de7536409fe..e47eaee5bce46 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -116,7 +116,11 @@ class TaskSnapshotSurface implements StartingSurface { private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM; private static final int MSG_REPORT_DRAW = 0; private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s"; - private static final Point sSurfaceSize = new Point(); //tmp var for unused relayout param + + //tmp vars for unused relayout params + private static final Point sTmpSurfaceSize = new Point(); + private static final SurfaceControl sTmpSurfaceControl = new SurfaceControl(); + private final Window mWindow; private final Surface mSurface; private SurfaceControl mSurfaceControl; @@ -230,7 +234,7 @@ class TaskSnapshotSurface implements StartingSurface { session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1, tmpFrame, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, tmpCutout, tmpMergedConfiguration, surfaceControl, mTmpInsetsState, - sSurfaceSize); + sTmpSurfaceSize, sTmpSurfaceControl); } catch (RemoteException e) { // Local call. } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e130830072376..2c6c756dda3b3 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2071,7 +2071,7 @@ public class WindowManagerService extends IWindowManager.Stub Rect outVisibleInsets, Rect outStableInsets, Rect outBackdropFrame, DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - Point outSurfaceSize) { + Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) { int result = 0; boolean configChanged; final int pid = Binder.getCallingPid(); @@ -2238,7 +2238,8 @@ public class WindowManagerService extends IWindowManager.Stub result = win.relayoutVisibleWindow(result, attrChanges); try { - result = createSurfaceControl(outSurfaceControl, result, win, winAnimator); + result = createSurfaceControl(outSurfaceControl, outBLASTSurfaceControl, + result, win, winAnimator); } catch (Exception e) { displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/); @@ -2270,6 +2271,7 @@ public class WindowManagerService extends IWindowManager.Stub // surface, let the client use that, but don't create new surface at this point. Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface"); winAnimator.mSurfaceController.getSurfaceControl(outSurfaceControl); + winAnimator.mSurfaceController.getBLASTSurfaceControl(outBLASTSurfaceControl); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } else { if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win); @@ -2451,7 +2453,8 @@ public class WindowManagerService extends IWindowManager.Stub } private int createSurfaceControl(SurfaceControl outSurfaceControl, - int result, WindowState win, WindowStateAnimator winAnimator) { + SurfaceControl outBLASTSurfaceControl, int result, + WindowState win, WindowStateAnimator winAnimator) { if (!win.mHasSurface) { result |= RELAYOUT_RES_SURFACE_CHANGED; } @@ -2465,6 +2468,7 @@ public class WindowManagerService extends IWindowManager.Stub } if (surfaceController != null) { surfaceController.getSurfaceControl(outSurfaceControl); + surfaceController.getBLASTSurfaceControl(outBLASTSurfaceControl); ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl); } else { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 73984fd49f734..b9694c3b9bd3b 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5616,4 +5616,8 @@ class WindowState extends WindowContainer implements WindowManagerP boolean isNonToastWindowVisibleForPid(int pid) { return mSession.mPid == pid && isNonToastOrStarting() && isVisibleNow(); } + + SurfaceControl getDeferTransactionBarrier() { + return mWinAnimator.getDeferTransactionBarrier(); + } } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 069ee4fea8ec7..9552df7b58993 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1010,7 +1010,7 @@ class WindowStateAnimator { // the WS position is reset (so the stack position is shown) at the same // time that the buffer size changes. setOffsetPositionForStackResize(false); - mSurfaceController.deferTransactionUntil(mSurfaceController.mSurfaceControl, + mSurfaceController.deferTransactionUntil(mWin.getDeferTransactionBarrier(), mWin.getFrameNumber()); } else { final ActivityStack stack = mWin.getRootTask(); @@ -1041,7 +1041,7 @@ class WindowStateAnimator { // comes in at the new size (normally position and crop are unfrozen). // deferTransactionUntil accomplishes this for us. if (wasForceScaled && !mForceScaleUntilResize) { - mSurfaceController.deferTransactionUntil(mSurfaceController.mSurfaceControl, + mSurfaceController.deferTransactionUntil(mWin.getDeferTransactionBarrier(), mWin.getFrameNumber()); mSurfaceController.forceScaleableInTransaction(false); } @@ -1518,4 +1518,11 @@ class WindowStateAnimator { void setOffsetPositionForStackResize(boolean offsetPositionForStackResize) { mOffsetPositionForStackResize = offsetPositionForStackResize; } + + SurfaceControl getDeferTransactionBarrier() { + if (!hasSurface()) { + return null; + } + return mSurfaceController.getDeferTransactionBarrier(); + } } diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 5b8015be1a7ad..383c0d9ab3d42 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -51,6 +51,11 @@ class WindowSurfaceController { SurfaceControl mSurfaceControl; + /** + * WM only uses for deferred transactions. + */ + SurfaceControl mBLASTSurfaceControl; + // Should only be set from within setShown(). private boolean mSurfaceShown = false; private float mSurfaceX = 0; @@ -110,13 +115,22 @@ class WindowSurfaceController { .setMetadata(METADATA_WINDOW_TYPE, windowType) .setMetadata(METADATA_OWNER_UID, ownerUid); - if ((win.getAttrs().privateFlags & - WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0) { + final boolean useBLAST = (win.getAttrs().privateFlags & + WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0; + if (useBLAST) { b.setContainerLayer(); } - mSurfaceControl = b.build(); + + if (useBLAST) { + mBLASTSurfaceControl = win.makeSurface() + .setParent(mSurfaceControl) + .setName("BLAST Adapter Layer") + .setBLASTLayer() + .build(); + } + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } @@ -168,6 +182,9 @@ class WindowSurfaceController { } finally { setShown(false); mSurfaceControl = null; + if (mBLASTSurfaceControl != null) { + mBLASTSurfaceControl.release(); + } } } @@ -474,6 +491,12 @@ class WindowSurfaceController { outSurfaceControl.copyFrom(mSurfaceControl); } + void getBLASTSurfaceControl(SurfaceControl outSurfaceControl) { + if (mBLASTSurfaceControl != null) { + outSurfaceControl.copyFrom(mBLASTSurfaceControl); + } + } + int getLayer() { return mSurfaceLayer; } @@ -510,6 +533,13 @@ class WindowSurfaceController { return mSurfaceH; } + SurfaceControl getDeferTransactionBarrier() { + if (mBLASTSurfaceControl != null) { + return mBLASTSurfaceControl; + } + return mSurfaceControl; + } + void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); proto.write(SHOWN, mSurfaceShown);