diff options
-rw-r--r-- | cmds/screencap/screencap.cpp | 2 | ||||
-rw-r--r-- | core/java/android/view/SurfaceControl.java | 34 | ||||
-rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 55 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 4 |
4 files changed, 62 insertions, 33 deletions
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp index 2efe4d30cd37..6296dd1bbf50 100644 --- a/cmds/screencap/screencap.cpp +++ b/cmds/screencap/screencap.cpp @@ -141,7 +141,7 @@ int main(int argc, char** argv) ScreenshotClient screenshot; sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId); - if (display != NULL && screenshot.update(display, false) == NO_ERROR) { + if (display != NULL && screenshot.update(display, Rect(), false) == NO_ERROR) { base = screenshot.getPixels(); w = screenshot.getWidth(); h = screenshot.getHeight(); diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index c15ce44eb2a2..5cd3d6272571 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -38,11 +38,11 @@ public class SurfaceControl { private static native void nativeDestroy(long nativeObject); private static native Bitmap nativeScreenshot(IBinder displayToken, - int width, int height, int minLayer, int maxLayer, boolean allLayers, - boolean useIdentityTransform); + Rect sourceCrop, int width, int height, int minLayer, int maxLayer, + boolean allLayers, boolean useIdentityTransform); private static native void nativeScreenshot(IBinder displayToken, Surface consumer, - int width, int height, int minLayer, int maxLayer, boolean allLayers, - boolean useIdentityTransform); + Rect sourceCrop, int width, int height, int minLayer, int maxLayer, + boolean allLayers, boolean useIdentityTransform); private static native void nativeOpenTransaction(); private static native void nativeCloseTransaction(); @@ -597,8 +597,8 @@ public class SurfaceControl { public static void screenshot(IBinder display, Surface consumer, int width, int height, int minLayer, int maxLayer, boolean useIdentityTransform) { - screenshot(display, consumer, width, height, minLayer, maxLayer, false, - useIdentityTransform); + screenshot(display, consumer, new Rect(), width, height, minLayer, maxLayer, + false, useIdentityTransform); } /** @@ -613,7 +613,7 @@ public class SurfaceControl { */ public static void screenshot(IBinder display, Surface consumer, int width, int height) { - screenshot(display, consumer, width, height, 0, 0, true, false); + screenshot(display, consumer, new Rect(), width, height, 0, 0, true, false); } /** @@ -623,7 +623,7 @@ public class SurfaceControl { * @param consumer The {@link Surface} to take the screenshot into. */ public static void screenshot(IBinder display, Surface consumer) { - screenshot(display, consumer, 0, 0, 0, 0, true, false); + screenshot(display, consumer, new Rect(), 0, 0, 0, 0, true, false); } /** @@ -634,6 +634,8 @@ public class SurfaceControl { * the versions that use a {@link Surface} instead, such as * {@link SurfaceControl#screenshot(IBinder, Surface)}. * + * @param sourceCrop The portion of the screen to capture into the Bitmap; + * caller may pass in 'new Rect()' if no cropping is desired. * @param width The desired width of the returned bitmap; the raw * screen will be scaled down to this size. * @param height The desired height of the returned bitmap; the raw @@ -649,13 +651,13 @@ public class SurfaceControl { * if an error occurs. Make sure to call Bitmap.recycle() as soon as * possible, once its content is not needed anymore. */ - public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer, - boolean useIdentityTransform) { + public static Bitmap screenshot(Rect sourceCrop, int width, int height, + int minLayer, int maxLayer, boolean useIdentityTransform) { // TODO: should take the display as a parameter IBinder displayToken = SurfaceControl.getBuiltInDisplay( SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN); - return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false, - useIdentityTransform); + return nativeScreenshot(displayToken, sourceCrop, width, height, + minLayer, maxLayer, false, useIdentityTransform); } /** @@ -674,10 +676,10 @@ public class SurfaceControl { // TODO: should take the display as a parameter IBinder displayToken = SurfaceControl.getBuiltInDisplay( SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN); - return nativeScreenshot(displayToken, width, height, 0, 0, true, false); + return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true, false); } - private static void screenshot(IBinder display, Surface consumer, + private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop, int width, int height, int minLayer, int maxLayer, boolean allLayers, boolean useIdentityTransform) { if (display == null) { @@ -686,7 +688,7 @@ public class SurfaceControl { if (consumer == null) { throw new IllegalArgumentException("consumer must not be null"); } - nativeScreenshot(display, consumer, width, height, minLayer, maxLayer, allLayers, - useIdentityTransform); + nativeScreenshot(display, consumer, sourceCrop, width, height, + minLayer, maxLayer, allLayers, useIdentityTransform); } } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 5a935a96eaff..4594cc31adac 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -61,6 +61,13 @@ static struct { jfieldID secure; } gPhysicalDisplayInfoClassInfo; +static struct { + jfieldID bottom; + jfieldID left; + jfieldID right; + jfieldID top; +} gRectClassInfo; + // Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref. void DeleteScreenshot(void* addr, void* context) { SkASSERT(addr == ((ScreenshotClient*) context)->getPixels()); @@ -104,25 +111,32 @@ static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) { ctrl->decStrong((void *)nativeCreate); } -static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject displayTokenObj, - jint width, jint height, jint minLayer, jint maxLayer, bool allLayers, - bool useIdentityTransform) { +static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, + jobject displayTokenObj, jobject sourceCropObj, jint width, jint height, + jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) { sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); if (displayToken == NULL) { return NULL; } + int left = env->GetIntField(sourceCropObj, gRectClassInfo.left); + int top = env->GetIntField(sourceCropObj, gRectClassInfo.top); + int right = env->GetIntField(sourceCropObj, gRectClassInfo.right); + int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom); + Rect sourceCrop(left, top, right, bottom); + ScreenshotClient* screenshot = new ScreenshotClient(); status_t res; if (width > 0 && height > 0) { if (allLayers) { - res = screenshot->update(displayToken, width, height, useIdentityTransform); - } else { - res = screenshot->update(displayToken, width, height, minLayer, maxLayer, + res = screenshot->update(displayToken, sourceCrop, width, height, useIdentityTransform); + } else { + res = screenshot->update(displayToken, sourceCrop, width, height, + minLayer, maxLayer, useIdentityTransform); } } else { - res = screenshot->update(displayToken, useIdentityTransform); + res = screenshot->update(displayToken, sourceCrop, useIdentityTransform); } if (res != NO_ERROR) { delete screenshot; @@ -174,20 +188,25 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject display GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL); } -static void nativeScreenshot(JNIEnv* env, jclass clazz, - jobject displayTokenObj, jobject surfaceObj, - jint width, jint height, jint minLayer, jint maxLayer, bool allLayers, - bool useIdentityTransform) { +static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj, + jobject surfaceObj, jobject sourceCropObj, jint width, jint height, + jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) { sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); if (displayToken != NULL) { sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj); if (consumer != NULL) { + int left = env->GetIntField(sourceCropObj, gRectClassInfo.left); + int top = env->GetIntField(sourceCropObj, gRectClassInfo.top); + int right = env->GetIntField(sourceCropObj, gRectClassInfo.right); + int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom); + Rect sourceCrop(left, top, right, bottom); + if (allLayers) { minLayer = 0; maxLayer = -1; } - ScreenshotClient::capture( - displayToken, consumer->getIGraphicBufferProducer(), + ScreenshotClient::capture(displayToken, + consumer->getIGraphicBufferProducer(), sourceCrop, width, height, uint32_t(minLayer), uint32_t(maxLayer), useIdentityTransform); } @@ -563,9 +582,9 @@ static JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeRelease }, {"nativeDestroy", "(J)V", (void*)nativeDestroy }, - {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZZ)Landroid/graphics/Bitmap;", + {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZ)Landroid/graphics/Bitmap;", (void*)nativeScreenshotBitmap }, - {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;IIIIZZ)V", + {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V", (void*)nativeScreenshot }, {"nativeOpenTransaction", "()V", (void*)nativeOpenTransaction }, @@ -640,6 +659,12 @@ int register_android_view_SurfaceControl(JNIEnv* env) gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F"); gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z"); + jclass rectClazz = env->FindClass("android/graphics/Rect"); + gRectClassInfo.bottom = env->GetFieldID(rectClazz, "bottom", "I"); + gRectClassInfo.left = env->GetFieldID(rectClazz, "left", "I"); + gRectClassInfo.right = env->GetFieldID(rectClazz, "right", "I"); + gRectClassInfo.top = env->GetFieldID(rectClazz, "top", "I"); + jclass frameStatsClazz = env->FindClass("android/view/FrameStats"); jfieldID undefined_time_nano_field = env->GetStaticFieldID(frameStatsClazz, "UNDEFINED_TIME_NANO", "J"); nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 1a0dd82a6f53..97a42a493a3f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -5801,7 +5801,9 @@ public class WindowManagerService extends IWindowManager.Stub // whether the screenshot should use the identity transformation matrix // (e.g., enable it when taking a screenshot for recents, since we might be in // the middle of the rotation animation, but don't want a rotated recent image). - rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer, false); + // TODO: Replace 'new Rect()' with the portion of the screen to capture for the + // screenshot. + rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer, false); } } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " + |