diff options
| author | chaviw <chaviw@google.com> | 2020-08-18 16:06:40 -0700 |
|---|---|---|
| committer | chaviw <chaviw@google.com> | 2020-09-08 09:59:50 -0700 |
| commit | 3510924a6de6ad44160de44051d28df87593edd3 (patch) | |
| tree | 1d547c3c90b165a509d26a7f9deeb70783224791 /core/java/android | |
| parent | 25953d498f68ac3cdc3b7f4c0a33946725ac960d (diff) | |
Send ScreenCaptureListener to native screen capture requests.
Allow for asynchronous screenshot by sending a ScreenCaptureListener to
handle screenshot callbacks. All existing calls are still synchronous
since the SurfaceControl method will block the caller until the results
from SurfaceFlinger are ready.
Test: power + volume down
Test: adb shell screencap
Bug: 162367424
Change-Id: I54c34003c0786b585dd20530a06dbd4b266e178c
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 96 |
1 files changed, 87 insertions, 9 deletions
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 6ef086b55c41..3af8958368dc 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -65,6 +65,9 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Objects; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; /** * Handle to an on-screen Surface managed by the system compositor. The SurfaceControl is @@ -87,10 +90,10 @@ public final class SurfaceControl implements Parcelable { private static native void nativeWriteToParcel(long nativeObject, Parcel out); private static native void nativeRelease(long nativeObject); private static native void nativeDisconnect(long nativeObject); - private static native ScreenshotHardwareBuffer nativeCaptureDisplay( - DisplayCaptureArgs captureArgs); - private static native ScreenshotHardwareBuffer nativeCaptureLayers( - LayerCaptureArgs captureArgs); + private static native int nativeCaptureDisplay(DisplayCaptureArgs captureArgs, + ScreenCaptureListener captureListener); + private static native int nativeCaptureLayers(LayerCaptureArgs captureArgs, + ScreenCaptureListener captureListener); private static native long nativeMirrorSurface(long mirrorOfObject); private static native long nativeCreateTransaction(); private static native long nativeGetNativeTransactionFinalizer(); @@ -493,6 +496,8 @@ public final class SurfaceControl implements Parcelable { private static final int INTERNAL_DATASPACE_DISPLAY_P3 = 143261696; private static final int INTERNAL_DATASPACE_SCRGB = 411107328; + private static final int SCREENSHOT_WAIT_TIME_S = 1; + private void assignNativeObject(long nativeObject, String callsite) { if (mNativeObject != 0) { release(); @@ -611,6 +616,13 @@ public final class SurfaceControl implements Parcelable { } /** + * @hide + */ + public abstract static class ScreenCaptureListener { + abstract void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer); + } + + /** * A common arguments class used for various screenshot requests. This contains arguments that * are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs} * @hide @@ -685,7 +697,7 @@ public final class SurfaceControl implements Parcelable { /** * The arguments class used to make display capture requests. * - * @see #nativeCaptureDisplay(DisplayCaptureArgs) + * @see #nativeCaptureDisplay(DisplayCaptureArgs, ScreenCaptureListener) * @hide */ public static class DisplayCaptureArgs extends CaptureArgs { @@ -2226,13 +2238,46 @@ public final class SurfaceControl implements Parcelable { } /** + * @param captureArgs Arguments about how to take the screenshot + * @param captureListener A listener to receive the screenshot callback + * @hide + */ + public static int captureDisplay(@NonNull DisplayCaptureArgs captureArgs, + @NonNull ScreenCaptureListener captureListener) { + return nativeCaptureDisplay(captureArgs, captureListener); + } + + /** * Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with * the content. * * @hide */ public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) { - return nativeCaptureDisplay(captureArgs); + final AtomicReference<ScreenshotHardwareBuffer> outHardwareBuffer = + new AtomicReference<>(null); + + final CountDownLatch countDownLatch = new CountDownLatch(1); + ScreenCaptureListener screenCaptureListener = new ScreenCaptureListener() { + @Override + void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer) { + outHardwareBuffer.set(hardwareBuffer); + countDownLatch.countDown(); + } + }; + + int status = captureDisplay(captureArgs, screenCaptureListener); + if (status != 0) { + return null; + } + + try { + countDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS); + } catch (Exception e) { + Log.e(TAG, "Failed to wait for captureDisplay result", e); + } + + return outHardwareBuffer.get(); } /** @@ -2277,14 +2322,37 @@ public final class SurfaceControl implements Parcelable { .setPixelFormat(format) .build(); - return nativeCaptureLayers(captureArgs); + return captureLayers(captureArgs); } /** * @hide */ public static ScreenshotHardwareBuffer captureLayers(LayerCaptureArgs captureArgs) { - return nativeCaptureLayers(captureArgs); + final AtomicReference<ScreenshotHardwareBuffer> outHardwareBuffer = + new AtomicReference<>(null); + + final CountDownLatch countDownLatch = new CountDownLatch(1); + ScreenCaptureListener screenCaptureListener = new ScreenCaptureListener() { + @Override + void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer) { + outHardwareBuffer.set(hardwareBuffer); + countDownLatch.countDown(); + } + }; + + int status = captureLayers(captureArgs, screenCaptureListener); + if (status != 0) { + return null; + } + + try { + countDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS); + } catch (Exception e) { + Log.e(TAG, "Failed to wait for captureLayers result", e); + } + + return outHardwareBuffer.get(); } /** @@ -2301,7 +2369,17 @@ public final class SurfaceControl implements Parcelable { .setExcludeLayers(exclude) .build(); - return nativeCaptureLayers(captureArgs); + return captureLayers(captureArgs); + } + + /** + * @param captureArgs Arguments about how to take the screenshot + * @param captureListener A listener to receive the screenshot callback + * @hide + */ + public static int captureLayers(@NonNull LayerCaptureArgs captureArgs, + @NonNull ScreenCaptureListener captureListener) { + return nativeCaptureLayers(captureArgs, captureListener); } /** |
