diff options
author | chaviw <chaviw@google.com> | 2020-07-27 16:44:35 -0700 |
---|---|---|
committer | chaviw <chaviw@google.com> | 2020-07-31 10:56:04 -0700 |
commit | bc27bc7189eb424c66d4529d5c750ebde1dba265 (patch) | |
tree | d05db5e253f7006668379f286545e4c8602dac19 | |
parent | e9bb6aa4ba807e59b00a6f7e0798fa38540aebf0 (diff) |
Updated display capture and screencap to match native functions
Modified Java and JNI display capture functions to match the new
function in SurfaceComposerClient. The Java method will send an args
object instead of individual arguments to SurfaceComposerClient
Test: display screenshots working
Test: adb shell screencap
Bug: 162367424
Change-Id: Ic8d9cbc626e9ef73300304ce155a50f76f017dfc
-rw-r--r-- | cmds/screencap/screencap.cpp | 31 | ||||
-rw-r--r-- | core/java/android/view/SurfaceControl.java | 35 | ||||
-rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 107 |
3 files changed, 123 insertions, 50 deletions
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp index c1d8399d91a5..a46a54cc2063 100644 --- a/cmds/screencap/screencap.cpp +++ b/cmds/screencap/screencap.cpp @@ -182,16 +182,17 @@ int main(int argc, char** argv) ProcessState::self()->setThreadPoolMaxThreadCount(0); ProcessState::self()->startThreadPool(); - ui::Dataspace outDataspace; - sp<GraphicBuffer> outBuffer; - - status_t result = ScreenshotClient::capture(*displayId, &outDataspace, &outBuffer); + ScreenCaptureResults captureResults; + status_t result = ScreenshotClient::captureDisplay(*displayId, captureResults); if (result != NO_ERROR) { close(fd); return 1; } - result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base); + ui::Dataspace dataspace = captureResults.capturedDataspace; + sp<GraphicBuffer> buffer = captureResults.buffer; + + result = buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base); if (base == nullptr || result != NO_ERROR) { String8 reason; @@ -207,13 +208,13 @@ int main(int argc, char** argv) if (png) { AndroidBitmapInfo info; - info.format = flinger2bitmapFormat(outBuffer->getPixelFormat()); + info.format = flinger2bitmapFormat(buffer->getPixelFormat()); info.flags = ANDROID_BITMAP_FLAGS_ALPHA_PREMUL; - info.width = outBuffer->getWidth(); - info.height = outBuffer->getHeight(); - info.stride = outBuffer->getStride() * bytesPerPixel(outBuffer->getPixelFormat()); + info.width = buffer->getWidth(); + info.height = buffer->getHeight(); + info.stride = buffer->getStride() * bytesPerPixel(buffer->getPixelFormat()); - int result = AndroidBitmap_compress(&info, static_cast<int32_t>(outDataspace), base, + int result = AndroidBitmap_compress(&info, static_cast<int32_t>(dataspace), base, ANDROID_BITMAP_COMPRESS_FORMAT_PNG, 100, &fd, [](void* fdPtr, const void* data, size_t size) -> bool { int bytesWritten = write(*static_cast<int*>(fdPtr), @@ -229,11 +230,11 @@ int main(int argc, char** argv) notifyMediaScanner(fn); } } else { - uint32_t w = outBuffer->getWidth(); - uint32_t h = outBuffer->getHeight(); - uint32_t s = outBuffer->getStride(); - uint32_t f = outBuffer->getPixelFormat(); - uint32_t c = dataSpaceToInt(outDataspace); + uint32_t w = buffer->getWidth(); + uint32_t h = buffer->getHeight(); + uint32_t s = buffer->getStride(); + uint32_t f = buffer->getPixelFormat(); + uint32_t c = dataSpaceToInt(dataspace); write(fd, &w, 4); write(fd, &h, 4); diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index eaa7eafc23cc..0f87adad2a53 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -89,10 +89,8 @@ 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 nativeScreenshot(IBinder displayToken, - Rect sourceCrop, int width, int height, boolean useIdentityTransform, int rotation, - boolean captureSecureLayers); + private static native ScreenshotHardwareBuffer nativeCaptureDisplay( + DisplayCaptureArgs captureArgs); private static native ScreenshotHardwareBuffer nativeCaptureLayers(IBinder displayToken, long layerObject, Rect sourceCrop, float frameScale, long[] excludeLayerObjects, int format); @@ -662,14 +660,14 @@ public final class SurfaceControl implements Parcelable { /** * Each sub class should return itself to allow the builder to chain properly */ - public abstract T getThis(); + abstract T getThis(); } } /** * The arguments class used to make display capture requests. * - * @see #nativeScreenshot(IBinder, Rect, int, int, boolean, int, boolean) + * @see #nativeCaptureDisplay(DisplayCaptureArgs) * @hide */ public static class DisplayCaptureArgs extends CaptureArgs { @@ -759,7 +757,7 @@ public final class SurfaceControl implements Parcelable { } @Override - public Builder getThis() { + Builder getThis() { return this; } } @@ -837,7 +835,7 @@ public final class SurfaceControl implements Parcelable { } @Override - public Builder getThis() { + Builder getThis() { return this; } @@ -2293,8 +2291,14 @@ public final class SurfaceControl implements Parcelable { throw new IllegalArgumentException("displayToken must not be null"); } - return nativeScreenshot(display, sourceCrop, width, height, useIdentityTransform, rotation, - false /* captureSecureLayers */); + DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display) + .setSourceCrop(sourceCrop) + .setSize(width, height) + .setUseIdentityTransform(useIdentityTransform) + .setRotation(rotation) + .build(); + + return nativeCaptureDisplay(captureArgs); } /** @@ -2314,8 +2318,15 @@ public final class SurfaceControl implements Parcelable { throw new IllegalArgumentException("displayToken must not be null"); } - return nativeScreenshot(display, sourceCrop, width, height, useIdentityTransform, rotation, - true /* captureSecureLayers */); + DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display) + .setSourceCrop(sourceCrop) + .setSize(width, height) + .setUseIdentityTransform(useIdentityTransform) + .setRotation(rotation) + .setCaptureSecureLayers(true) + .build(); + + return nativeCaptureDisplay(captureArgs); } private static void rotateCropForSF(Rect crop, int rot) { diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index a965ab310205..905e69ddff24 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -104,6 +104,21 @@ static struct { jfieldID top; } gRectClassInfo; +static struct { + jfieldID pixelFormat; + jfieldID sourceCrop; + jfieldID frameScale; + jfieldID captureSecureLayers; +} gCaptureArgsClassInfo; + +static struct { + jfieldID displayToken; + jfieldID width; + jfieldID height; + jfieldID useIdentityTransform; + jfieldID rotation; +} gDisplayCaptureArgsClassInfo; + // Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref. void DeleteScreenshot(void* addr, void* context) { delete ((ScreenshotClient*) context); @@ -276,35 +291,60 @@ static Rect rectFromObj(JNIEnv* env, jobject rectObj) { return Rect(left, top, right, bottom); } -static jobject nativeScreenshot(JNIEnv* env, jclass clazz, - jobject displayTokenObj, jobject sourceCropObj, jint width, jint height, - bool useIdentityTransform, int rotation, bool captureSecureLayers) { - sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); - if (displayToken == NULL) { +static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs& captureArgs) { + captureArgs.pixelFormat = static_cast<ui::PixelFormat>( + env->GetIntField(captureArgsObject, gCaptureArgsClassInfo.pixelFormat)); + captureArgs.sourceCrop = + rectFromObj(env, + env->GetObjectField(captureArgsObject, gCaptureArgsClassInfo.sourceCrop)); + captureArgs.frameScale = + env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScale); + captureArgs.captureSecureLayers = + env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.captureSecureLayers); +} + +static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env, + jobject displayCaptureArgsObject) { + DisplayCaptureArgs captureArgs; + getCaptureArgs(env, displayCaptureArgsObject, captureArgs); + + captureArgs.displayToken = + ibinderForJavaObject(env, + env->GetObjectField(displayCaptureArgsObject, + gDisplayCaptureArgsClassInfo.displayToken)); + captureArgs.width = + env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.width); + captureArgs.height = + env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.height); + captureArgs.useIdentityTransform = + env->GetBooleanField(displayCaptureArgsObject, + gDisplayCaptureArgsClassInfo.useIdentityTransform); + captureArgs.rotation = ui::toRotation( + env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.rotation)); + return captureArgs; +} + +static jobject nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject) { + const DisplayCaptureArgs captureArgs = + displayCaptureArgsFromObject(env, displayCaptureArgsObject); + + if (captureArgs.displayToken == NULL) { return NULL; } - const ui::ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(displayToken); - const ui::Dataspace dataspace = pickDataspaceFromColorMode(colorMode); - Rect sourceCrop = rectFromObj(env, sourceCropObj); - sp<GraphicBuffer> buffer; - bool capturedSecureLayers = false; - status_t res = ScreenshotClient::capture(displayToken, dataspace, - ui::PixelFormat::RGBA_8888, - sourceCrop, width, height, - useIdentityTransform, ui::toRotation(rotation), - captureSecureLayers, &buffer, capturedSecureLayers); + ScreenCaptureResults captureResults; + status_t res = ScreenshotClient::captureDisplay(captureArgs, captureResults); if (res != NO_ERROR) { return NULL; } - jobject jhardwareBuffer = - android_hardware_HardwareBuffer_createFromAHardwareBuffer(env, - buffer->toAHardwareBuffer()); - const jint namedColorSpace = fromDataspaceToNamedColorSpaceValue(dataspace); + jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer( + env, captureResults.buffer->toAHardwareBuffer()); + const jint namedColorSpace = + fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace); return env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz, gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer, - namedColorSpace, capturedSecureLayers); + namedColorSpace, captureResults.capturedSecureLayers); } static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject displayTokenObj, @@ -1614,10 +1654,10 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSeverChildren } , {"nativeSetOverrideScalingMode", "(JJI)V", (void*)nativeSetOverrideScalingMode }, - {"nativeScreenshot", - "(Landroid/os/IBinder;Landroid/graphics/Rect;IIZIZ)" + {"nativeCaptureDisplay", + "(Landroid/view/SurfaceControl$DisplayCaptureArgs;)" "Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;", - (void*)nativeScreenshot }, + (void*)nativeCaptureDisplay }, {"nativeCaptureLayers", "(Landroid/os/IBinder;JLandroid/graphics/Rect;" "F[JI)" @@ -1795,6 +1835,27 @@ int register_android_view_SurfaceControl(JNIEnv* env) gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMax = GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "appRequestRefreshRateMax", "F"); + jclass captureArgsClazz = FindClassOrDie(env, "android/view/SurfaceControl$CaptureArgs"); + gCaptureArgsClassInfo.pixelFormat = GetFieldIDOrDie(env, captureArgsClazz, "mPixelFormat", "I"); + gCaptureArgsClassInfo.sourceCrop = + GetFieldIDOrDie(env, captureArgsClazz, "mSourceCrop", "Landroid/graphics/Rect;"); + gCaptureArgsClassInfo.frameScale = GetFieldIDOrDie(env, captureArgsClazz, "mFrameScale", "F"); + gCaptureArgsClassInfo.captureSecureLayers = + GetFieldIDOrDie(env, captureArgsClazz, "mCaptureSecureLayers", "Z"); + + jclass displayCaptureArgsClazz = + FindClassOrDie(env, "android/view/SurfaceControl$DisplayCaptureArgs"); + gDisplayCaptureArgsClassInfo.displayToken = + GetFieldIDOrDie(env, displayCaptureArgsClazz, "mDisplayToken", "Landroid/os/IBinder;"); + gDisplayCaptureArgsClassInfo.width = + GetFieldIDOrDie(env, displayCaptureArgsClazz, "mWidth", "I"); + gDisplayCaptureArgsClassInfo.height = + GetFieldIDOrDie(env, displayCaptureArgsClazz, "mHeight", "I"); + gDisplayCaptureArgsClassInfo.useIdentityTransform = + GetFieldIDOrDie(env, displayCaptureArgsClazz, "mUseIdentityTransform", "Z"); + gDisplayCaptureArgsClassInfo.rotation = + GetFieldIDOrDie(env, displayCaptureArgsClazz, "mRotation", "I"); + return err; } |