Loading core/java/android/view/IWindowManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -970,6 +970,10 @@ interface IWindowManager */ boolean isLetterboxBackgroundMultiColored(); /** * Captures the entire display specified by the displayId using the args provided. If the args * are null or if the sourceCrop is invalid or null, the entire display bounds will be captured. */ oneway void captureDisplay(int displayId, in @nullable ScreenCapture.CaptureArgs captureArgs, in ScreenCapture.ScreenCaptureListener listener); } core/java/android/window/ScreenCapture.java +8 −8 Original line number Diff line number Diff line Loading @@ -255,14 +255,14 @@ public class ScreenCapture { * @hide */ public static class CaptureArgs implements Parcelable { private final int mPixelFormat; private final Rect mSourceCrop = new Rect(); private final float mFrameScaleX; private final float mFrameScaleY; private final boolean mCaptureSecureLayers; private final boolean mAllowProtected; private final long mUid; private final boolean mGrayscale; public final int mPixelFormat; public final Rect mSourceCrop = new Rect(); public final float mFrameScaleX; public final float mFrameScaleY; public final boolean mCaptureSecureLayers; public final boolean mAllowProtected; public final long mUid; public final boolean mGrayscale; private CaptureArgs(CaptureArgs.Builder<? extends CaptureArgs.Builder<?>> builder) { mPixelFormat = builder.mPixelFormat; Loading services/core/java/com/android/server/wm/WindowManagerService.java +15 −7 Original line number Diff line number Diff line Loading @@ -9286,6 +9286,12 @@ public class WindowManagerService extends IWindowManager.Stub throw new SecurityException("Requires READ_FRAME_BUFFER permission"); } ScreenCapture.captureLayers(getCaptureArgs(displayId, captureArgs), listener); } @VisibleForTesting ScreenCapture.LayerCaptureArgs getCaptureArgs(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs) { final SurfaceControl displaySurfaceControl; synchronized (mGlobalLock) { DisplayContent displayContent = mRoot.getDisplayContent(displayId); Loading @@ -9297,18 +9303,20 @@ public class WindowManagerService extends IWindowManager.Stub displaySurfaceControl = displayContent.getSurfaceControl(); if (captureArgs == null) { displayContent.getBounds(mTmpRect); mTmpRect.offsetTo(0, 0); captureArgs = new ScreenCapture.CaptureArgs.Builder<>() .setSourceCrop(mTmpRect) .build(); } if (captureArgs.mSourceCrop.isEmpty()) { displayContent.getBounds(mTmpRect); mTmpRect.offsetTo(0, 0); } else { mTmpRect.set(captureArgs.mSourceCrop); } } ScreenCapture.LayerCaptureArgs args = new ScreenCapture.LayerCaptureArgs.Builder(displaySurfaceControl, captureArgs) return new ScreenCapture.LayerCaptureArgs.Builder(displaySurfaceControl, captureArgs) .setSourceCrop(mTmpRect) .build(); ScreenCapture.captureLayers(args, listener); } } services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java +41 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; Loading Loading @@ -68,6 +69,7 @@ import android.view.SurfaceControl; import android.view.View; import android.view.WindowManager; import android.window.ClientWindowFrames; import android.window.ScreenCapture; import android.window.WindowContainerToken; import androidx.test.filters.SmallTest; Loading Loading @@ -423,6 +425,45 @@ public class WindowManagerServiceTests extends WindowTestsBase { LETTERBOX_BACKGROUND_SOLID_COLOR)).isFalse(); } @Test public void testCaptureDisplay() { Rect displayBounds = new Rect(0, 0, 100, 200); spyOn(mDisplayContent); when(mDisplayContent.getBounds()).thenReturn(displayBounds); // Null captureArgs ScreenCapture.LayerCaptureArgs resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, null /* captureArgs */); assertEquals(displayBounds, resultingArgs.mSourceCrop); // Non null captureArgs, didn't set rect ScreenCapture.CaptureArgs captureArgs = new ScreenCapture.CaptureArgs.Builder<>().build(); resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs); assertEquals(displayBounds, resultingArgs.mSourceCrop); // Non null captureArgs, invalid rect captureArgs = new ScreenCapture.CaptureArgs.Builder<>() .setSourceCrop(new Rect(0, 0, -1, -1)) .build(); resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs); assertEquals(displayBounds, resultingArgs.mSourceCrop); // Non null captureArgs, null rect captureArgs = new ScreenCapture.CaptureArgs.Builder<>() .setSourceCrop(null) .build(); resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs); assertEquals(displayBounds, resultingArgs.mSourceCrop); // Non null captureArgs, valid rect Rect validRect = new Rect(0, 0, 10, 50); captureArgs = new ScreenCapture.CaptureArgs.Builder<>() .setSourceCrop(validRect) .build(); resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs); assertEquals(validRect, resultingArgs.mSourceCrop); } private void setupActivityWithLaunchCookie(IBinder launchCookie, WindowContainerToken wct) { final WindowContainer.RemoteToken remoteToken = mock(WindowContainer.RemoteToken.class); when(remoteToken.toWindowContainerToken()).thenReturn(wct); Loading Loading
core/java/android/view/IWindowManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -970,6 +970,10 @@ interface IWindowManager */ boolean isLetterboxBackgroundMultiColored(); /** * Captures the entire display specified by the displayId using the args provided. If the args * are null or if the sourceCrop is invalid or null, the entire display bounds will be captured. */ oneway void captureDisplay(int displayId, in @nullable ScreenCapture.CaptureArgs captureArgs, in ScreenCapture.ScreenCaptureListener listener); }
core/java/android/window/ScreenCapture.java +8 −8 Original line number Diff line number Diff line Loading @@ -255,14 +255,14 @@ public class ScreenCapture { * @hide */ public static class CaptureArgs implements Parcelable { private final int mPixelFormat; private final Rect mSourceCrop = new Rect(); private final float mFrameScaleX; private final float mFrameScaleY; private final boolean mCaptureSecureLayers; private final boolean mAllowProtected; private final long mUid; private final boolean mGrayscale; public final int mPixelFormat; public final Rect mSourceCrop = new Rect(); public final float mFrameScaleX; public final float mFrameScaleY; public final boolean mCaptureSecureLayers; public final boolean mAllowProtected; public final long mUid; public final boolean mGrayscale; private CaptureArgs(CaptureArgs.Builder<? extends CaptureArgs.Builder<?>> builder) { mPixelFormat = builder.mPixelFormat; Loading
services/core/java/com/android/server/wm/WindowManagerService.java +15 −7 Original line number Diff line number Diff line Loading @@ -9286,6 +9286,12 @@ public class WindowManagerService extends IWindowManager.Stub throw new SecurityException("Requires READ_FRAME_BUFFER permission"); } ScreenCapture.captureLayers(getCaptureArgs(displayId, captureArgs), listener); } @VisibleForTesting ScreenCapture.LayerCaptureArgs getCaptureArgs(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs) { final SurfaceControl displaySurfaceControl; synchronized (mGlobalLock) { DisplayContent displayContent = mRoot.getDisplayContent(displayId); Loading @@ -9297,18 +9303,20 @@ public class WindowManagerService extends IWindowManager.Stub displaySurfaceControl = displayContent.getSurfaceControl(); if (captureArgs == null) { displayContent.getBounds(mTmpRect); mTmpRect.offsetTo(0, 0); captureArgs = new ScreenCapture.CaptureArgs.Builder<>() .setSourceCrop(mTmpRect) .build(); } if (captureArgs.mSourceCrop.isEmpty()) { displayContent.getBounds(mTmpRect); mTmpRect.offsetTo(0, 0); } else { mTmpRect.set(captureArgs.mSourceCrop); } } ScreenCapture.LayerCaptureArgs args = new ScreenCapture.LayerCaptureArgs.Builder(displaySurfaceControl, captureArgs) return new ScreenCapture.LayerCaptureArgs.Builder(displaySurfaceControl, captureArgs) .setSourceCrop(mTmpRect) .build(); ScreenCapture.captureLayers(args, listener); } }
services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java +41 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; Loading Loading @@ -68,6 +69,7 @@ import android.view.SurfaceControl; import android.view.View; import android.view.WindowManager; import android.window.ClientWindowFrames; import android.window.ScreenCapture; import android.window.WindowContainerToken; import androidx.test.filters.SmallTest; Loading Loading @@ -423,6 +425,45 @@ public class WindowManagerServiceTests extends WindowTestsBase { LETTERBOX_BACKGROUND_SOLID_COLOR)).isFalse(); } @Test public void testCaptureDisplay() { Rect displayBounds = new Rect(0, 0, 100, 200); spyOn(mDisplayContent); when(mDisplayContent.getBounds()).thenReturn(displayBounds); // Null captureArgs ScreenCapture.LayerCaptureArgs resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, null /* captureArgs */); assertEquals(displayBounds, resultingArgs.mSourceCrop); // Non null captureArgs, didn't set rect ScreenCapture.CaptureArgs captureArgs = new ScreenCapture.CaptureArgs.Builder<>().build(); resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs); assertEquals(displayBounds, resultingArgs.mSourceCrop); // Non null captureArgs, invalid rect captureArgs = new ScreenCapture.CaptureArgs.Builder<>() .setSourceCrop(new Rect(0, 0, -1, -1)) .build(); resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs); assertEquals(displayBounds, resultingArgs.mSourceCrop); // Non null captureArgs, null rect captureArgs = new ScreenCapture.CaptureArgs.Builder<>() .setSourceCrop(null) .build(); resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs); assertEquals(displayBounds, resultingArgs.mSourceCrop); // Non null captureArgs, valid rect Rect validRect = new Rect(0, 0, 10, 50); captureArgs = new ScreenCapture.CaptureArgs.Builder<>() .setSourceCrop(validRect) .build(); resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs); assertEquals(validRect, resultingArgs.mSourceCrop); } private void setupActivityWithLaunchCookie(IBinder launchCookie, WindowContainerToken wct) { final WindowContainer.RemoteToken remoteToken = mock(WindowContainer.RemoteToken.class); when(remoteToken.toWindowContainerToken()).thenReturn(wct); Loading