From cc6cdbc9deb1d97c4ba6b308badb14b8d0d3ddc6 Mon Sep 17 00:00:00 2001 From: chaviw Date: Fri, 19 Mar 2021 11:19:45 -0500 Subject: [PATCH] Use BLAST layer for snapshot starting windows Test: Snapshot starting window uses blast and works Bug: 170765639 Change-Id: Iab1e5cf200e02509d3ab72cb3f04e788e1c1aa38 --- .../startingsurface/TaskSnapshotWindow.java | 56 +++++++++--------- .../server/wm/TaskSnapshotSurface.java | 58 +++++++++---------- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java index e9ce2addd4640..b46846215ebb1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java @@ -38,6 +38,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES; @@ -52,8 +53,10 @@ import android.app.ActivityThread; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.GraphicBuffer; import android.graphics.Matrix; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; @@ -68,7 +71,6 @@ import android.view.IWindowSession; import android.view.InputChannel; import android.view.InsetsSourceControl; import android.view.InsetsState; -import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.View; @@ -122,11 +124,9 @@ public class TaskSnapshotWindow { private static final Point TMP_SURFACE_SIZE = new Point(); private final Window mWindow; - private final Surface mSurface; private final Runnable mClearWindowHandler; private final ShellExecutor mSplashScreenExecutor; - private SurfaceControl mSurfaceControl; - private SurfaceControl mChildSurfaceControl; + private final SurfaceControl mSurfaceControl; private final IWindowSession mSession; private final Rect mTaskBounds; private final Rect mFrame = new Rect(); @@ -179,7 +179,7 @@ public class TaskSnapshotWindow { // Setting as trusted overlay to let touches pass through. This is safe because this // window is controlled by the system. layoutParams.privateFlags = (windowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) - | PRIVATE_FLAG_TRUSTED_OVERLAY; + | PRIVATE_FLAG_TRUSTED_OVERLAY | PRIVATE_FLAG_USE_BLAST; layoutParams.token = appToken; layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT; layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT; @@ -259,7 +259,6 @@ public class TaskSnapshotWindow { int currentOrientation, int activityType, InsetsState topWindowInsetsState, Runnable clearWindowHandler, ShellExecutor splashScreenExecutor) { mSplashScreenExecutor = splashScreenExecutor; - mSurface = new Surface(); mSession = WindowManagerGlobal.getWindowSession(); mWindow = new Window(); mWindow.setSession(mSession); @@ -336,7 +335,6 @@ public class TaskSnapshotWindow { } private void drawSnapshot() { - mSurface.copyFrom(mSurfaceControl); if (DEBUG) { Slog.d(TAG, "Drawing snapshot surface sizeMismatch= " + mSizeMismatch); } @@ -357,15 +355,14 @@ public class TaskSnapshotWindow { } private void drawSizeMatchSnapshot() { - mSurface.attachAndQueueBufferWithColorSpace(mSnapshot.getHardwareBuffer(), - mSnapshot.getColorSpace()); - mSurface.release(); + GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer( + mSnapshot.getHardwareBuffer()); + mTransaction.setBuffer(mSurfaceControl, graphicBuffer) + .setColorSpace(mSurfaceControl, mSnapshot.getColorSpace()) + .apply(); } private void drawSizeMismatchSnapshot() { - if (!mSurface.isValid()) { - throw new IllegalStateException("mSurface does not hold a valid surface."); - } final HardwareBuffer buffer = mSnapshot.getHardwareBuffer(); final SurfaceSession session = new SurfaceSession(); @@ -376,26 +373,24 @@ public class TaskSnapshotWindow { - ((float) mFrame.width() / mFrame.height())) > 0.01f; // Keep a reference to it such that it doesn't get destroyed when finalized. - mChildSurfaceControl = new SurfaceControl.Builder(session) + SurfaceControl childSurfaceControl = new SurfaceControl.Builder(session) .setName(mTitle + " - task-snapshot-surface") - .setBufferSize(buffer.getWidth(), buffer.getHeight()) + .setBLASTLayer() .setFormat(buffer.getFormat()) .setParent(mSurfaceControl) .setCallsite("TaskSnapshotWindow.drawSizeMismatchSnapshot") .build(); - Surface surface = new Surface(); - surface.copyFrom(mChildSurfaceControl); final Rect frame; // We can just show the surface here as it will still be hidden as the parent is // still hidden. - mTransaction.show(mChildSurfaceControl); + mTransaction.show(childSurfaceControl); if (aspectRatioMismatch) { // Clip off ugly navigation bar. final Rect crop = calculateSnapshotCrop(); frame = calculateSnapshotFrame(crop); - mTransaction.setWindowCrop(mChildSurfaceControl, crop); - mTransaction.setPosition(mChildSurfaceControl, frame.left, frame.top); + mTransaction.setWindowCrop(childSurfaceControl, crop); + mTransaction.setPosition(childSurfaceControl, frame.left, frame.top); mTmpSnapshotSize.set(crop); mTmpDstFrame.set(frame); } else { @@ -407,18 +402,23 @@ public class TaskSnapshotWindow { // Scale the mismatch dimensions to fill the task bounds mSnapshotMatrix.setRectToRect(mTmpSnapshotSize, mTmpDstFrame, Matrix.ScaleToFit.FILL); - mTransaction.setMatrix(mChildSurfaceControl, mSnapshotMatrix, mTmpFloat9); - - mTransaction.apply(); - surface.attachAndQueueBufferWithColorSpace(buffer, mSnapshot.getColorSpace()); - surface.release(); + mTransaction.setMatrix(childSurfaceControl, mSnapshotMatrix, mTmpFloat9); + GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer( + mSnapshot.getHardwareBuffer()); + mTransaction.setColorSpace(childSurfaceControl, mSnapshot.getColorSpace()); + mTransaction.setBuffer(childSurfaceControl, graphicBuffer); if (aspectRatioMismatch) { - final Canvas c = mSurface.lockCanvas(null); + GraphicBuffer background = GraphicBuffer.create(mFrame.width(), mFrame.height(), + PixelFormat.RGBA_8888, + GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER + | GraphicBuffer.USAGE_SW_WRITE_RARELY); + final Canvas c = background.lockCanvas(); drawBackgroundAndBars(c, frame); - mSurface.unlockCanvasAndPost(c); - mSurface.release(); + background.unlockCanvasAndPost(c); + mTransaction.setBuffer(mSurfaceControl, background); } + mTransaction.apply(); } /** diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index 79a6bd7dcd2cf..cc4abab01b72a 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -37,6 +37,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES; @@ -53,8 +54,10 @@ import android.app.ActivityThread; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.GraphicBuffer; import android.graphics.Matrix; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; @@ -69,7 +72,6 @@ import android.util.Slog; import android.view.IWindowSession; import android.view.InsetsSourceControl; import android.view.InsetsState; -import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.View; @@ -124,9 +126,7 @@ class TaskSnapshotSurface implements StartingSurface { private static final Point sTmpSurfaceSize = new Point(); private final Window mWindow; - private final Surface mSurface; - private SurfaceControl mSurfaceControl; - private SurfaceControl mChildSurfaceControl; + private final SurfaceControl mSurfaceControl; private final IWindowSession mSession; private final WindowManagerService mService; private final int mDisplayId; @@ -200,7 +200,7 @@ class TaskSnapshotSurface implements StartingSurface { // Setting as trusted overlay to let touches pass through. This is safe because this // window is controlled by the system. layoutParams.privateFlags = (windowPrivateFlags & PRIVATE_FLAG_INHERITS) - | PRIVATE_FLAG_TRUSTED_OVERLAY; + | PRIVATE_FLAG_TRUSTED_OVERLAY | PRIVATE_FLAG_USE_BLAST; layoutParams.token = activity.token; layoutParams.width = LayoutParams.MATCH_PARENT; layoutParams.height = LayoutParams.MATCH_PARENT; @@ -262,7 +262,6 @@ class TaskSnapshotSurface implements StartingSurface { InsetsState insetsState) { mService = service; mDisplayId = displayId; - mSurface = service.mSurfaceFactory.get(); mHandler = new Handler(mService.mH.getLooper()); mSession = WindowManagerGlobal.getWindowSession(); mWindow = window; @@ -314,8 +313,6 @@ class TaskSnapshotSurface implements StartingSurface { } private void drawSnapshot() { - mSurface.copyFrom(mSurfaceControl); - ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Drawing snapshot surface sizeMismatch=%b", mSizeMismatch); if (mSizeMismatch) { @@ -337,15 +334,14 @@ class TaskSnapshotSurface implements StartingSurface { } private void drawSizeMatchSnapshot() { - mSurface.attachAndQueueBufferWithColorSpace(mSnapshot.getHardwareBuffer(), - mSnapshot.getColorSpace()); - mSurface.release(); + GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer( + mSnapshot.getHardwareBuffer()); + mTransaction.setBuffer(mSurfaceControl, graphicBuffer) + .setColorSpace(mSurfaceControl, mSnapshot.getColorSpace()) + .apply(); } private void drawSizeMismatchSnapshot() { - if (!mSurface.isValid()) { - throw new IllegalStateException("mSurface does not hold a valid surface."); - } final HardwareBuffer buffer = mSnapshot.getHardwareBuffer(); final SurfaceSession session = new SurfaceSession(); // We consider nearly matched dimensions as there can be rounding errors and the user won't @@ -356,26 +352,24 @@ class TaskSnapshotSurface implements StartingSurface { // Keep a reference to it such that it doesn't get destroyed when finalized. final String name = mTitle + " - task-snapshot-surface"; - mChildSurfaceControl = mService.mSurfaceControlFactory.apply(session) + SurfaceControl childSurfaceControl = mService.mSurfaceControlFactory.apply(session) .setName(name) - .setBufferSize(buffer.getWidth(), buffer.getHeight()) + .setBLASTLayer() .setFormat(buffer.getFormat()) .setParent(mSurfaceControl) .setCallsite("TaskSnapshotSurface.drawSizeMismatchSnapshot") .build(); - Surface surface = mService.mSurfaceFactory.get(); - surface.copyFrom(mChildSurfaceControl); final Rect frame; // We can just show the surface here as it will still be hidden as the parent is // still hidden. - mTransaction.show(mChildSurfaceControl); + mTransaction.show(childSurfaceControl); if (aspectRatioMismatch) { // Clip off ugly navigation bar. final Rect crop = calculateSnapshotCrop(); frame = calculateSnapshotFrame(crop); - mTransaction.setWindowCrop(mChildSurfaceControl, crop); - mTransaction.setPosition(mChildSurfaceControl, frame.left, frame.top); + mTransaction.setWindowCrop(childSurfaceControl, crop); + mTransaction.setPosition(childSurfaceControl, frame.left, frame.top); mTmpSnapshotSize.set(crop); mTmpDstFrame.set(frame); } else { @@ -387,23 +381,29 @@ class TaskSnapshotSurface implements StartingSurface { // Scale the mismatch dimensions to fill the task bounds mSnapshotMatrix.setRectToRect(mTmpSnapshotSize, mTmpDstFrame, Matrix.ScaleToFit.FILL); - mTransaction.setMatrix(mChildSurfaceControl, mSnapshotMatrix, mTmpFloat9); + mTransaction.setMatrix(childSurfaceControl, mSnapshotMatrix, mTmpFloat9); + GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer( + mSnapshot.getHardwareBuffer()); + mTransaction.setColorSpace(childSurfaceControl, mSnapshot.getColorSpace()); + mTransaction.setBuffer(childSurfaceControl, graphicBuffer); // This is the way to tell the input system to exclude this surface from occlusion // detection since we don't have a window for it. We do this because this window is // generated by the system as well as its content (the snapshot of the app). - InputMonitor.setTrustedOverlayInputInfo(mChildSurfaceControl, mTransaction, mDisplayId, + InputMonitor.setTrustedOverlayInputInfo(childSurfaceControl, mTransaction, mDisplayId, name); - mTransaction.apply(); - surface.attachAndQueueBufferWithColorSpace(buffer, mSnapshot.getColorSpace()); - surface.release(); if (aspectRatioMismatch) { - final Canvas c = mSurface.lockCanvas(null); + GraphicBuffer background = GraphicBuffer.create(mFrame.width(), mFrame.height(), + PixelFormat.RGBA_8888, + GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER + | GraphicBuffer.USAGE_SW_WRITE_RARELY); + final Canvas c = background.lockCanvas(); drawBackgroundAndBars(c, frame); - mSurface.unlockCanvasAndPost(c); - mSurface.release(); + background.unlockCanvasAndPost(c); + mTransaction.setBuffer(mSurfaceControl, background); } + mTransaction.apply(); } /**